Skip to content

Commit d9cacf6

Browse files
committed
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
1 parent 25c8d94 commit d9cacf6

1 file changed

Lines changed: 104 additions & 98 deletions

File tree

sbin/ping/ping.c

Lines changed: 104 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ __FBSDID("$FreeBSD$");
9191
#include <errno.h>
9292
#include <math.h>
9393
#include <netdb.h>
94+
#include <stddef.h>
9495
#include <signal.h>
9596
#include <stdio.h>
9697
#include <stdlib.h>
@@ -217,10 +218,10 @@ static void finish(void) __dead2;
217218
static void pinger(void);
218219
static char *pr_addr(struct in_addr);
219220
static char *pr_ntime(n_time);
220-
static void pr_icmph(struct icmp *);
221+
static void pr_icmph(struct icmp *, struct ip *, const u_char *const);
221222
static void pr_iph(struct ip *);
222-
static void pr_pack(char *, int, struct sockaddr_in *, struct timespec *);
223-
static void pr_retip(struct ip *);
223+
static void pr_pack(char *, ssize_t, struct sockaddr_in *, struct timespec *);
224+
static void pr_retip(struct ip *, const u_char *);
224225
static void status(int);
225226
static void stopit(int);
226227
static void usage(void) __dead2;
@@ -232,7 +233,6 @@ main(int argc, char *const *argv)
232233
struct in_addr ifaddr;
233234
struct timespec last, intvl;
234235
struct iovec iov;
235-
struct ip *ip;
236236
struct msghdr msg;
237237
struct sigaction si_sa;
238238
size_t sz;
@@ -687,7 +687,9 @@ main(int argc, char *const *argv)
687687
#endif /*IPSEC*/
688688

689689
if (options & F_HDRINCL) {
690-
ip = (struct ip*)outpackhdr;
690+
struct ip ip;
691+
692+
memcpy(&ip, outpackhdr, sizeof(ip));
691693
if (!(options & (F_TTL | F_MTTL))) {
692694
mib[0] = CTL_NET;
693695
mib[1] = PF_INET;
@@ -698,15 +700,16 @@ main(int argc, char *const *argv)
698700
err(1, "sysctl(net.inet.ip.ttl)");
699701
}
700702
setsockopt(ssend, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold));
701-
ip->ip_v = IPVERSION;
702-
ip->ip_hl = sizeof(struct ip) >> 2;
703-
ip->ip_tos = tos;
704-
ip->ip_id = 0;
705-
ip->ip_off = htons(df ? IP_DF : 0);
706-
ip->ip_ttl = ttl;
707-
ip->ip_p = IPPROTO_ICMP;
708-
ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY;
709-
ip->ip_dst = to->sin_addr;
703+
ip.ip_v = IPVERSION;
704+
ip.ip_hl = sizeof(struct ip) >> 2;
705+
ip.ip_tos = tos;
706+
ip.ip_id = 0;
707+
ip.ip_off = htons(df ? IP_DF : 0);
708+
ip.ip_ttl = ttl;
709+
ip.ip_p = IPPROTO_ICMP;
710+
ip.ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY;
711+
ip.ip_dst = to->sin_addr;
712+
memcpy(outpackhdr, &ip, sizeof(ip));
710713
}
711714

712715
/*
@@ -898,7 +901,8 @@ main(int argc, char *const *argv)
898901
while (!finish_up) {
899902
struct timespec now, timeout;
900903
fd_set rfds;
901-
int cc, n;
904+
int n;
905+
ssize_t cc;
902906

903907
check_status();
904908
if ((unsigned)srecv >= FD_SETSIZE)
@@ -1016,18 +1020,17 @@ pinger(void)
10161020
{
10171021
struct timespec now;
10181022
struct tv32 tv32;
1019-
struct ip *ip;
1020-
struct icmp *icp;
1023+
struct icmp icp;
10211024
int cc, i;
10221025
u_char *packet;
10231026

10241027
packet = outpack;
1025-
icp = (struct icmp *)outpack;
1026-
icp->icmp_type = icmp_type;
1027-
icp->icmp_code = 0;
1028-
icp->icmp_cksum = 0;
1029-
icp->icmp_seq = htons(ntransmitted);
1030-
icp->icmp_id = ident; /* ID */
1028+
memcpy(&icp, outpack, ICMP_MINLEN + phdr_len);
1029+
icp.icmp_type = icmp_type;
1030+
icp.icmp_code = 0;
1031+
icp.icmp_cksum = 0;
1032+
icp.icmp_seq = htons(ntransmitted);
1033+
icp.icmp_id = ident; /* ID */
10311034

10321035
CLR(ntransmitted % mx_dup_ck);
10331036

@@ -1042,24 +1045,36 @@ pinger(void)
10421045
tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
10431046
tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec);
10441047
if (options & F_TIME)
1045-
icp->icmp_otime = htonl((now.tv_sec % (24*60*60))
1048+
icp.icmp_otime = htonl((now.tv_sec % (24*60*60))
10461049
* 1000 + now.tv_nsec / 1000000);
10471050
if (timing)
10481051
bcopy((void *)&tv32,
10491052
(void *)&outpack[ICMP_MINLEN + phdr_len],
10501053
sizeof(tv32));
10511054
}
10521055

1056+
memcpy(outpack, &icp, ICMP_MINLEN + phdr_len);
1057+
10531058
cc = ICMP_MINLEN + phdr_len + datalen;
10541059

10551060
/* compute ICMP checksum here */
1056-
icp->icmp_cksum = in_cksum((u_char *)icp, cc);
1061+
icp.icmp_cksum = in_cksum(outpack, cc);
1062+
/* Update icmp_cksum in the raw packet data buffer. */
1063+
memcpy(outpack + offsetof(struct icmp, icmp_cksum), &icp.icmp_cksum,
1064+
sizeof(icp.icmp_cksum));
10571065

10581066
if (options & F_HDRINCL) {
1067+
struct ip ip;
1068+
10591069
cc += sizeof(struct ip);
1060-
ip = (struct ip *)outpackhdr;
1061-
ip->ip_len = htons(cc);
1062-
ip->ip_sum = in_cksum(outpackhdr, cc);
1070+
ip.ip_len = htons(cc);
1071+
/* Update ip_len in the raw packet data buffer. */
1072+
memcpy(outpackhdr + offsetof(struct ip, ip_len), &ip.ip_len,
1073+
sizeof(ip.ip_len));
1074+
ip.ip_sum = in_cksum(outpackhdr, cc);
1075+
/* Update ip_sum in the raw packet data buffer. */
1076+
memcpy(outpackhdr + offsetof(struct ip, ip_sum), &ip.ip_sum,
1077+
sizeof(ip.ip_sum));
10631078
packet = outpackhdr;
10641079
}
10651080
i = send(ssend, (char *)packet, cc, 0);
@@ -1089,47 +1104,61 @@ pinger(void)
10891104
* program to be run without having intermingled output (or statistics!).
10901105
*/
10911106
static void
1092-
pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
1107+
pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
10931108
{
10941109
struct in_addr ina;
1095-
u_char *cp, *dp;
1096-
struct icmp *icp;
1097-
struct ip *ip;
1098-
const void *tp;
1110+
u_char *cp, *dp, l;
1111+
struct icmp icp;
1112+
struct ip ip;
1113+
const u_char *icmp_data_raw;
10991114
double triptime;
11001115
int dupflag, hlen, i, j, recv_len;
11011116
uint16_t seq;
11021117
static int old_rrlen;
11031118
static char old_rr[MAX_IPOPTLEN];
1119+
struct ip oip;
1120+
u_char oip_header_len;
1121+
struct icmp oicmp;
1122+
const u_char *oicmp_raw;
1123+
1124+
/*
1125+
* Get size of IP header of the received packet. The
1126+
* information is contained in the lower four bits of the
1127+
* first byte.
1128+
*/
1129+
memcpy(&l, buf, sizeof(l));
1130+
hlen = (l & 0x0f) << 2;
1131+
memcpy(&ip, buf, hlen);
11041132

11051133
/* Check the IP header */
1106-
ip = (struct ip *)buf;
1107-
hlen = ip->ip_hl << 2;
11081134
recv_len = cc;
11091135
if (cc < hlen + ICMP_MINLEN) {
11101136
if (options & F_VERBOSE)
1111-
warn("packet too short (%d bytes) from %s", cc,
1137+
warn("packet too short (%zd bytes) from %s", cc,
11121138
inet_ntoa(from->sin_addr));
11131139
return;
11141140
}
11151141

1142+
#ifndef icmp_data
1143+
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip);
1144+
#else
1145+
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data);
1146+
#endif
1147+
11161148
/* Now the ICMP part */
11171149
cc -= hlen;
1118-
icp = (struct icmp *)(buf + hlen);
1119-
if (icp->icmp_type == icmp_type_rsp) {
1120-
if (icp->icmp_id != ident)
1150+
memcpy(&icp, buf + hlen, MIN((ssize_t)sizeof(icp), cc));
1151+
if (icp.icmp_type == icmp_type_rsp) {
1152+
if (icp.icmp_id != ident)
11211153
return; /* 'Twas not our ECHO */
11221154
++nreceived;
11231155
triptime = 0.0;
11241156
if (timing) {
11251157
struct timespec tv1;
11261158
struct tv32 tv32;
1127-
#ifndef icmp_data
1128-
tp = &icp->icmp_ip;
1129-
#else
1130-
tp = icp->icmp_data;
1131-
#endif
1132-
tp = (const char *)tp + phdr_len;
1159+
const u_char *tp;
1160+
1161+
tp = icmp_data_raw + phdr_len;
11331162

11341163
if ((size_t)(cc - ICMP_MINLEN - phdr_len) >=
11351164
sizeof(tv1)) {
@@ -1150,7 +1179,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
11501179
timing = 0;
11511180
}
11521181

1153-
seq = ntohs(icp->icmp_seq);
1182+
seq = ntohs(icp.icmp_seq);
11541183

11551184
if (TST(seq % mx_dup_ck)) {
11561185
++nrepeats;
@@ -1172,9 +1201,9 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
11721201
if (options & F_FLOOD)
11731202
(void)write(STDOUT_FILENO, &BSPACE, 1);
11741203
else {
1175-
(void)printf("%d bytes from %s: icmp_seq=%u", cc,
1204+
(void)printf("%zd bytes from %s: icmp_seq=%u", cc,
11761205
pr_addr(from->sin_addr), seq);
1177-
(void)printf(" ttl=%d", ip->ip_ttl);
1206+
(void)printf(" ttl=%d", ip.ip_ttl);
11781207
if (timing)
11791208
(void)printf(" time=%.3f ms", triptime);
11801209
if (dupflag)
@@ -1184,20 +1213,21 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
11841213
if (options & F_MASK) {
11851214
/* Just prentend this cast isn't ugly */
11861215
(void)printf(" mask=%s",
1187-
inet_ntoa(*(struct in_addr *)&(icp->icmp_mask)));
1216+
inet_ntoa(*(struct in_addr *)&(icp.icmp_mask)));
11881217
}
11891218
if (options & F_TIME) {
1190-
(void)printf(" tso=%s", pr_ntime(icp->icmp_otime));
1191-
(void)printf(" tsr=%s", pr_ntime(icp->icmp_rtime));
1192-
(void)printf(" tst=%s", pr_ntime(icp->icmp_ttime));
1219+
(void)printf(" tso=%s", pr_ntime(icp.icmp_otime));
1220+
(void)printf(" tsr=%s", pr_ntime(icp.icmp_rtime));
1221+
(void)printf(" tst=%s", pr_ntime(icp.icmp_ttime));
11931222
}
11941223
if (recv_len != send_len) {
11951224
(void)printf(
11961225
"\nwrong total length %d instead of %d",
11971226
recv_len, send_len);
11981227
}
11991228
/* check the data */
1200-
cp = (u_char*)&icp->icmp_data[phdr_len];
1229+
cp = (u_char*)(buf + hlen + offsetof(struct icmp,
1230+
icmp_data) + phdr_len);
12011231
dp = &outpack[ICMP_MINLEN + phdr_len];
12021232
cc -= ICMP_MINLEN + phdr_len;
12031233
i = 0;
@@ -1212,7 +1242,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
12121242
(void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
12131243
i, *dp, *cp);
12141244
(void)printf("\ncp:");
1215-
cp = (u_char*)&icp->icmp_data[0];
1245+
cp = (u_char*)(buf + hlen +
1246+
offsetof(struct icmp, icmp_data));
12161247
for (i = 0; i < datalen; ++i, ++cp) {
12171248
if ((i % 16) == 8)
12181249
(void)printf("\n\t");
@@ -1240,22 +1271,22 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
12401271
* as root to avoid leaking information not normally
12411272
* available to those not running as root.
12421273
*/
1243-
#ifndef icmp_data
1244-
struct ip *oip = &icp->icmp_ip;
1245-
#else
1246-
struct ip *oip = (struct ip *)icp->icmp_data;
1247-
#endif
1248-
struct icmp *oicmp = (struct icmp *)(oip + 1);
1274+
memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len));
1275+
oip_header_len = (oip_header_len & 0x0f) << 2;
1276+
memcpy(&oip, icmp_data_raw, oip_header_len);
1277+
oicmp_raw = icmp_data_raw + oip_header_len;
1278+
memcpy(&oicmp, oicmp_raw, offsetof(struct icmp, icmp_id) +
1279+
sizeof(oicmp.icmp_id));
12491280

12501281
if (((options & F_VERBOSE) && uid == 0) ||
12511282
(!(options & F_QUIET2) &&
1252-
(oip->ip_dst.s_addr == whereto.sin_addr.s_addr) &&
1253-
(oip->ip_p == IPPROTO_ICMP) &&
1254-
(oicmp->icmp_type == ICMP_ECHO) &&
1255-
(oicmp->icmp_id == ident))) {
1256-
(void)printf("%d bytes from %s: ", cc,
1283+
(oip.ip_dst.s_addr == whereto.sin_addr.s_addr) &&
1284+
(oip.ip_p == IPPROTO_ICMP) &&
1285+
(oicmp.icmp_type == ICMP_ECHO) &&
1286+
(oicmp.icmp_id == ident))) {
1287+
(void)printf("%zd bytes from %s: ", cc,
12571288
pr_addr(from->sin_addr));
1258-
pr_icmph(icp);
1289+
pr_icmph(&icp, &oip, oicmp_raw);
12591290
} else
12601291
return;
12611292
}
@@ -1441,7 +1472,7 @@ static char *ttab[] = {
14411472
* Print a descriptive string about an ICMP header.
14421473
*/
14431474
static void
1444-
pr_icmph(struct icmp *icp)
1475+
pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw)
14451476
{
14461477

14471478
switch(icp->icmp_type) {
@@ -1479,19 +1510,11 @@ pr_icmph(struct icmp *icp)
14791510
break;
14801511
}
14811512
/* Print returned IP header information */
1482-
#ifndef icmp_data
1483-
pr_retip(&icp->icmp_ip);
1484-
#else
1485-
pr_retip((struct ip *)icp->icmp_data);
1486-
#endif
1513+
pr_retip(oip, oicmp_raw);
14871514
break;
14881515
case ICMP_SOURCEQUENCH:
14891516
(void)printf("Source Quench\n");
1490-
#ifndef icmp_data
1491-
pr_retip(&icp->icmp_ip);
1492-
#else
1493-
pr_retip((struct ip *)icp->icmp_data);
1494-
#endif
1517+
pr_retip(oip, oicmp_raw);
14951518
break;
14961519
case ICMP_REDIRECT:
14971520
switch(icp->icmp_code) {
@@ -1512,11 +1535,7 @@ pr_icmph(struct icmp *icp)
15121535
break;
15131536
}
15141537
(void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr));
1515-
#ifndef icmp_data
1516-
pr_retip(&icp->icmp_ip);
1517-
#else
1518-
pr_retip((struct ip *)icp->icmp_data);
1519-
#endif
1538+
pr_retip(oip, oicmp_raw);
15201539
break;
15211540
case ICMP_ECHO:
15221541
(void)printf("Echo Request\n");
@@ -1535,20 +1554,12 @@ pr_icmph(struct icmp *icp)
15351554
icp->icmp_code);
15361555
break;
15371556
}
1538-
#ifndef icmp_data
1539-
pr_retip(&icp->icmp_ip);
1540-
#else
1541-
pr_retip((struct ip *)icp->icmp_data);
1542-
#endif
1557+
pr_retip(oip, oicmp_raw);
15431558
break;
15441559
case ICMP_PARAMPROB:
15451560
(void)printf("Parameter problem: pointer = 0x%02x\n",
15461561
icp->icmp_hun.ih_pptr);
1547-
#ifndef icmp_data
1548-
pr_retip(&icp->icmp_ip);
1549-
#else
1550-
pr_retip((struct ip *)icp->icmp_data);
1551-
#endif
1562+
pr_retip(oip, oicmp_raw);
15521563
break;
15531564
case ICMP_TSTAMP:
15541565
(void)printf("Timestamp\n");
@@ -1646,14 +1657,9 @@ pr_addr(struct in_addr ina)
16461657
* Dump some info on a returned (via ICMP) IP packet.
16471658
*/
16481659
static void
1649-
pr_retip(struct ip *ip)
1660+
pr_retip(struct ip *ip, const u_char *cp)
16501661
{
1651-
u_char *cp;
1652-
int hlen;
1653-
16541662
pr_iph(ip);
1655-
hlen = ip->ip_hl << 2;
1656-
cp = (u_char *)ip + hlen;
16571663

16581664
if (ip->ip_p == 6)
16591665
(void)printf("TCP: from port %u, to port %u (decimal)\n",

0 commit comments

Comments
 (0)