@@ -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;
217218static void pinger (void );
218219static char * pr_addr (struct in_addr );
219220static 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 );
221222static 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 * );
224225static void status (int );
225226static void stopit (int );
226227static 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 */
10911106static 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 */
14431474static 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 */
16481659static 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