ping: Fix alignment errors

This fixes -Wcast-align errors when compiled with WARNS=6.

Submitted by:	Ján Sučan <sucanjan@gmail.com>
MFC after:	2 weeks
Sponsored by:	Google LLC (Google Summer of Code 2019)
Differential Revision:	https://reviews.freebsd.org/D21327
This commit is contained in:
asomers 2019-08-23 22:04:26 +00:00
parent 2d3cff4bfc
commit 6a537df465

View File

@ -91,6 +91,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include <netdb.h> #include <netdb.h>
#include <stddef.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -217,10 +218,10 @@ static void finish(void) __dead2;
static void pinger(void); static void pinger(void);
static char *pr_addr(struct in_addr); static char *pr_addr(struct in_addr);
static char *pr_ntime(n_time); static char *pr_ntime(n_time);
static void pr_icmph(struct icmp *); static void pr_icmph(struct icmp *, struct ip *, const u_char *const);
static void pr_iph(struct ip *); static void pr_iph(struct ip *);
static void pr_pack(char *, int, struct sockaddr_in *, struct timespec *); static void pr_pack(char *, ssize_t, struct sockaddr_in *, struct timespec *);
static void pr_retip(struct ip *); static void pr_retip(struct ip *, const u_char *);
static void status(int); static void status(int);
static void stopit(int); static void stopit(int);
static void usage(void) __dead2; static void usage(void) __dead2;
@ -232,7 +233,6 @@ main(int argc, char *const *argv)
struct in_addr ifaddr; struct in_addr ifaddr;
struct timespec last, intvl; struct timespec last, intvl;
struct iovec iov; struct iovec iov;
struct ip *ip;
struct msghdr msg; struct msghdr msg;
struct sigaction si_sa; struct sigaction si_sa;
size_t sz; size_t sz;
@ -687,7 +687,9 @@ main(int argc, char *const *argv)
#endif /*IPSEC*/ #endif /*IPSEC*/
if (options & F_HDRINCL) { if (options & F_HDRINCL) {
ip = (struct ip*)outpackhdr; struct ip ip;
memcpy(&ip, outpackhdr, sizeof(ip));
if (!(options & (F_TTL | F_MTTL))) { if (!(options & (F_TTL | F_MTTL))) {
mib[0] = CTL_NET; mib[0] = CTL_NET;
mib[1] = PF_INET; mib[1] = PF_INET;
@ -698,15 +700,16 @@ main(int argc, char *const *argv)
err(1, "sysctl(net.inet.ip.ttl)"); err(1, "sysctl(net.inet.ip.ttl)");
} }
setsockopt(ssend, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold)); setsockopt(ssend, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold));
ip->ip_v = IPVERSION; ip.ip_v = IPVERSION;
ip->ip_hl = sizeof(struct ip) >> 2; ip.ip_hl = sizeof(struct ip) >> 2;
ip->ip_tos = tos; ip.ip_tos = tos;
ip->ip_id = 0; ip.ip_id = 0;
ip->ip_off = htons(df ? IP_DF : 0); ip.ip_off = htons(df ? IP_DF : 0);
ip->ip_ttl = ttl; ip.ip_ttl = ttl;
ip->ip_p = IPPROTO_ICMP; ip.ip_p = IPPROTO_ICMP;
ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; ip.ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY;
ip->ip_dst = to->sin_addr; ip.ip_dst = to->sin_addr;
memcpy(outpackhdr, &ip, sizeof(ip));
} }
/* /*
@ -898,7 +901,8 @@ main(int argc, char *const *argv)
while (!finish_up) { while (!finish_up) {
struct timespec now, timeout; struct timespec now, timeout;
fd_set rfds; fd_set rfds;
int cc, n; int n;
ssize_t cc;
check_status(); check_status();
if ((unsigned)srecv >= FD_SETSIZE) if ((unsigned)srecv >= FD_SETSIZE)
@ -1016,18 +1020,17 @@ pinger(void)
{ {
struct timespec now; struct timespec now;
struct tv32 tv32; struct tv32 tv32;
struct ip *ip; struct icmp icp;
struct icmp *icp;
int cc, i; int cc, i;
u_char *packet; u_char *packet;
packet = outpack; packet = outpack;
icp = (struct icmp *)outpack; memcpy(&icp, outpack, ICMP_MINLEN + phdr_len);
icp->icmp_type = icmp_type; icp.icmp_type = icmp_type;
icp->icmp_code = 0; icp.icmp_code = 0;
icp->icmp_cksum = 0; icp.icmp_cksum = 0;
icp->icmp_seq = htons(ntransmitted); icp.icmp_seq = htons(ntransmitted);
icp->icmp_id = ident; /* ID */ icp.icmp_id = ident; /* ID */
CLR(ntransmitted % mx_dup_ck); CLR(ntransmitted % mx_dup_ck);
@ -1042,7 +1045,7 @@ pinger(void)
tv32.tv32_sec = (uint32_t)htonl(now.tv_sec); tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec); tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec);
if (options & F_TIME) if (options & F_TIME)
icp->icmp_otime = htonl((now.tv_sec % (24*60*60)) icp.icmp_otime = htonl((now.tv_sec % (24*60*60))
* 1000 + now.tv_nsec / 1000000); * 1000 + now.tv_nsec / 1000000);
if (timing) if (timing)
bcopy((void *)&tv32, bcopy((void *)&tv32,
@ -1050,16 +1053,28 @@ pinger(void)
sizeof(tv32)); sizeof(tv32));
} }
memcpy(outpack, &icp, ICMP_MINLEN + phdr_len);
cc = ICMP_MINLEN + phdr_len + datalen; cc = ICMP_MINLEN + phdr_len + datalen;
/* compute ICMP checksum here */ /* compute ICMP checksum here */
icp->icmp_cksum = in_cksum((u_char *)icp, cc); icp.icmp_cksum = in_cksum(outpack, cc);
/* Update icmp_cksum in the raw packet data buffer. */
memcpy(outpack + offsetof(struct icmp, icmp_cksum), &icp.icmp_cksum,
sizeof(icp.icmp_cksum));
if (options & F_HDRINCL) { if (options & F_HDRINCL) {
struct ip ip;
cc += sizeof(struct ip); cc += sizeof(struct ip);
ip = (struct ip *)outpackhdr; ip.ip_len = htons(cc);
ip->ip_len = htons(cc); /* Update ip_len in the raw packet data buffer. */
ip->ip_sum = in_cksum(outpackhdr, cc); memcpy(outpackhdr + offsetof(struct ip, ip_len), &ip.ip_len,
sizeof(ip.ip_len));
ip.ip_sum = in_cksum(outpackhdr, cc);
/* Update ip_sum in the raw packet data buffer. */
memcpy(outpackhdr + offsetof(struct ip, ip_sum), &ip.ip_sum,
sizeof(ip.ip_sum));
packet = outpackhdr; packet = outpackhdr;
} }
i = send(ssend, (char *)packet, cc, 0); i = send(ssend, (char *)packet, cc, 0);
@ -1089,47 +1104,61 @@ pinger(void)
* program to be run without having intermingled output (or statistics!). * program to be run without having intermingled output (or statistics!).
*/ */
static void static void
pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv) pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
{ {
struct in_addr ina; struct in_addr ina;
u_char *cp, *dp; u_char *cp, *dp, l;
struct icmp *icp; struct icmp icp;
struct ip *ip; struct ip ip;
const void *tp; const u_char *icmp_data_raw;
double triptime; double triptime;
int dupflag, hlen, i, j, recv_len; int dupflag, hlen, i, j, recv_len;
uint16_t seq; uint16_t seq;
static int old_rrlen; static int old_rrlen;
static char old_rr[MAX_IPOPTLEN]; static char old_rr[MAX_IPOPTLEN];
struct ip oip;
u_char oip_header_len;
struct icmp oicmp;
const u_char *oicmp_raw;
/*
* Get size of IP header of the received packet. The
* information is contained in the lower four bits of the
* first byte.
*/
memcpy(&l, buf, sizeof(l));
hlen = (l & 0x0f) << 2;
memcpy(&ip, buf, hlen);
/* Check the IP header */ /* Check the IP header */
ip = (struct ip *)buf;
hlen = ip->ip_hl << 2;
recv_len = cc; recv_len = cc;
if (cc < hlen + ICMP_MINLEN) { if (cc < hlen + ICMP_MINLEN) {
if (options & F_VERBOSE) if (options & F_VERBOSE)
warn("packet too short (%d bytes) from %s", cc, warn("packet too short (%zd bytes) from %s", cc,
inet_ntoa(from->sin_addr)); inet_ntoa(from->sin_addr));
return; return;
} }
#ifndef icmp_data
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip);
#else
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data);
#endif
/* Now the ICMP part */ /* Now the ICMP part */
cc -= hlen; cc -= hlen;
icp = (struct icmp *)(buf + hlen); memcpy(&icp, buf + hlen, MIN((ssize_t)sizeof(icp), cc));
if (icp->icmp_type == icmp_type_rsp) { if (icp.icmp_type == icmp_type_rsp) {
if (icp->icmp_id != ident) if (icp.icmp_id != ident)
return; /* 'Twas not our ECHO */ return; /* 'Twas not our ECHO */
++nreceived; ++nreceived;
triptime = 0.0; triptime = 0.0;
if (timing) { if (timing) {
struct timespec tv1; struct timespec tv1;
struct tv32 tv32; struct tv32 tv32;
#ifndef icmp_data const u_char *tp;
tp = &icp->icmp_ip;
#else tp = icmp_data_raw + phdr_len;
tp = icp->icmp_data;
#endif
tp = (const char *)tp + phdr_len;
if ((size_t)(cc - ICMP_MINLEN - phdr_len) >= if ((size_t)(cc - ICMP_MINLEN - phdr_len) >=
sizeof(tv1)) { sizeof(tv1)) {
@ -1150,7 +1179,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
timing = 0; timing = 0;
} }
seq = ntohs(icp->icmp_seq); seq = ntohs(icp.icmp_seq);
if (TST(seq % mx_dup_ck)) { if (TST(seq % mx_dup_ck)) {
++nrepeats; ++nrepeats;
@ -1172,9 +1201,9 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
if (options & F_FLOOD) if (options & F_FLOOD)
(void)write(STDOUT_FILENO, &BSPACE, 1); (void)write(STDOUT_FILENO, &BSPACE, 1);
else { else {
(void)printf("%d bytes from %s: icmp_seq=%u", cc, (void)printf("%zd bytes from %s: icmp_seq=%u", cc,
pr_addr(from->sin_addr), seq); pr_addr(from->sin_addr), seq);
(void)printf(" ttl=%d", ip->ip_ttl); (void)printf(" ttl=%d", ip.ip_ttl);
if (timing) if (timing)
(void)printf(" time=%.3f ms", triptime); (void)printf(" time=%.3f ms", triptime);
if (dupflag) if (dupflag)
@ -1184,12 +1213,12 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
if (options & F_MASK) { if (options & F_MASK) {
/* Just prentend this cast isn't ugly */ /* Just prentend this cast isn't ugly */
(void)printf(" mask=%s", (void)printf(" mask=%s",
inet_ntoa(*(struct in_addr *)&(icp->icmp_mask))); inet_ntoa(*(struct in_addr *)&(icp.icmp_mask)));
} }
if (options & F_TIME) { if (options & F_TIME) {
(void)printf(" tso=%s", pr_ntime(icp->icmp_otime)); (void)printf(" tso=%s", pr_ntime(icp.icmp_otime));
(void)printf(" tsr=%s", pr_ntime(icp->icmp_rtime)); (void)printf(" tsr=%s", pr_ntime(icp.icmp_rtime));
(void)printf(" tst=%s", pr_ntime(icp->icmp_ttime)); (void)printf(" tst=%s", pr_ntime(icp.icmp_ttime));
} }
if (recv_len != send_len) { if (recv_len != send_len) {
(void)printf( (void)printf(
@ -1197,7 +1226,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
recv_len, send_len); recv_len, send_len);
} }
/* check the data */ /* check the data */
cp = (u_char*)&icp->icmp_data[phdr_len]; cp = (u_char*)(buf + hlen + offsetof(struct icmp,
icmp_data) + phdr_len);
dp = &outpack[ICMP_MINLEN + phdr_len]; dp = &outpack[ICMP_MINLEN + phdr_len];
cc -= ICMP_MINLEN + phdr_len; cc -= ICMP_MINLEN + phdr_len;
i = 0; i = 0;
@ -1212,7 +1242,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
(void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
i, *dp, *cp); i, *dp, *cp);
(void)printf("\ncp:"); (void)printf("\ncp:");
cp = (u_char*)&icp->icmp_data[0]; cp = (u_char*)(buf + hlen +
offsetof(struct icmp, icmp_data));
for (i = 0; i < datalen; ++i, ++cp) { for (i = 0; i < datalen; ++i, ++cp) {
if ((i % 16) == 8) if ((i % 16) == 8)
(void)printf("\n\t"); (void)printf("\n\t");
@ -1240,22 +1271,22 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
* as root to avoid leaking information not normally * as root to avoid leaking information not normally
* available to those not running as root. * available to those not running as root.
*/ */
#ifndef icmp_data memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len));
struct ip *oip = &icp->icmp_ip; oip_header_len = (oip_header_len & 0x0f) << 2;
#else memcpy(&oip, icmp_data_raw, oip_header_len);
struct ip *oip = (struct ip *)icp->icmp_data; oicmp_raw = icmp_data_raw + oip_header_len;
#endif memcpy(&oicmp, oicmp_raw, offsetof(struct icmp, icmp_id) +
struct icmp *oicmp = (struct icmp *)(oip + 1); sizeof(oicmp.icmp_id));
if (((options & F_VERBOSE) && uid == 0) || if (((options & F_VERBOSE) && uid == 0) ||
(!(options & F_QUIET2) && (!(options & F_QUIET2) &&
(oip->ip_dst.s_addr == whereto.sin_addr.s_addr) && (oip.ip_dst.s_addr == whereto.sin_addr.s_addr) &&
(oip->ip_p == IPPROTO_ICMP) && (oip.ip_p == IPPROTO_ICMP) &&
(oicmp->icmp_type == ICMP_ECHO) && (oicmp.icmp_type == ICMP_ECHO) &&
(oicmp->icmp_id == ident))) { (oicmp.icmp_id == ident))) {
(void)printf("%d bytes from %s: ", cc, (void)printf("%zd bytes from %s: ", cc,
pr_addr(from->sin_addr)); pr_addr(from->sin_addr));
pr_icmph(icp); pr_icmph(&icp, &oip, oicmp_raw);
} else } else
return; return;
} }
@ -1441,7 +1472,7 @@ static char *ttab[] = {
* Print a descriptive string about an ICMP header. * Print a descriptive string about an ICMP header.
*/ */
static void static void
pr_icmph(struct icmp *icp) pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw)
{ {
switch(icp->icmp_type) { switch(icp->icmp_type) {
@ -1479,19 +1510,11 @@ pr_icmph(struct icmp *icp)
break; break;
} }
/* Print returned IP header information */ /* Print returned IP header information */
#ifndef icmp_data pr_retip(oip, oicmp_raw);
pr_retip(&icp->icmp_ip);
#else
pr_retip((struct ip *)icp->icmp_data);
#endif
break; break;
case ICMP_SOURCEQUENCH: case ICMP_SOURCEQUENCH:
(void)printf("Source Quench\n"); (void)printf("Source Quench\n");
#ifndef icmp_data pr_retip(oip, oicmp_raw);
pr_retip(&icp->icmp_ip);
#else
pr_retip((struct ip *)icp->icmp_data);
#endif
break; break;
case ICMP_REDIRECT: case ICMP_REDIRECT:
switch(icp->icmp_code) { switch(icp->icmp_code) {
@ -1512,11 +1535,7 @@ pr_icmph(struct icmp *icp)
break; break;
} }
(void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr)); (void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr));
#ifndef icmp_data pr_retip(oip, oicmp_raw);
pr_retip(&icp->icmp_ip);
#else
pr_retip((struct ip *)icp->icmp_data);
#endif
break; break;
case ICMP_ECHO: case ICMP_ECHO:
(void)printf("Echo Request\n"); (void)printf("Echo Request\n");
@ -1535,20 +1554,12 @@ pr_icmph(struct icmp *icp)
icp->icmp_code); icp->icmp_code);
break; break;
} }
#ifndef icmp_data pr_retip(oip, oicmp_raw);
pr_retip(&icp->icmp_ip);
#else
pr_retip((struct ip *)icp->icmp_data);
#endif
break; break;
case ICMP_PARAMPROB: case ICMP_PARAMPROB:
(void)printf("Parameter problem: pointer = 0x%02x\n", (void)printf("Parameter problem: pointer = 0x%02x\n",
icp->icmp_hun.ih_pptr); icp->icmp_hun.ih_pptr);
#ifndef icmp_data pr_retip(oip, oicmp_raw);
pr_retip(&icp->icmp_ip);
#else
pr_retip((struct ip *)icp->icmp_data);
#endif
break; break;
case ICMP_TSTAMP: case ICMP_TSTAMP:
(void)printf("Timestamp\n"); (void)printf("Timestamp\n");
@ -1646,14 +1657,9 @@ pr_addr(struct in_addr ina)
* Dump some info on a returned (via ICMP) IP packet. * Dump some info on a returned (via ICMP) IP packet.
*/ */
static void static void
pr_retip(struct ip *ip) pr_retip(struct ip *ip, const u_char *cp)
{ {
u_char *cp;
int hlen;
pr_iph(ip); pr_iph(ip);
hlen = ip->ip_hl << 2;
cp = (u_char *)ip + hlen;
if (ip->ip_p == 6) if (ip->ip_p == 6)
(void)printf("TCP: from port %u, to port %u (decimal)\n", (void)printf("TCP: from port %u, to port %u (decimal)\n",