diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-03 01:10:29 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-03 01:10:29 +0100 |
commit | 9341fd2d300e97f2bcf8e4b804c918240de4fe33 (patch) | |
tree | c7387c7eda05c2fecae7f17017c719df964f5849 /networking/ping.c | |
parent | 5749328b5634918888474222732572a3e0c97f70 (diff) | |
download | busybox-w32-9341fd2d300e97f2bcf8e4b804c918240de4fe33.tar.gz busybox-w32-9341fd2d300e97f2bcf8e4b804c918240de4fe33.tar.bz2 busybox-w32-9341fd2d300e97f2bcf8e4b804c918240de4fe33.zip |
ping: do not leak data from stack; shrink
FANCY ping:
function old new delta
common_ping_main 386 1732 +1346
sendping6 98 83 -15
sendping4 188 158 -30
ping4 575 - -575
ping6 756 - -756
------------------------------------------------------------------------------
(add/remove: 0/2 grow/shrink: 1/2 up/down: 1346/-1376) Total: -30 bytes
!FANCY ping:
function old new delta
hostname 4 - -4
common_ping_main 566 499 -67
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/ping.c')
-rw-r--r-- | networking/ping.c | 104 |
1 files changed, 57 insertions, 47 deletions
diff --git a/networking/ping.c b/networking/ping.c index 467b7f694..6a766a437 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -43,13 +43,12 @@ enum { | |||
43 | DEFDATALEN = 56, | 43 | DEFDATALEN = 56, |
44 | MAXIPLEN = 60, | 44 | MAXIPLEN = 60, |
45 | MAXICMPLEN = 76, | 45 | MAXICMPLEN = 76, |
46 | MAXPACKET = 65468, | ||
47 | MAX_DUP_CHK = (8 * 128), | 46 | MAX_DUP_CHK = (8 * 128), |
48 | MAXWAIT = 10, | 47 | MAXWAIT = 10, |
49 | PINGINTERVAL = 1, /* 1 second */ | 48 | PINGINTERVAL = 1, /* 1 second */ |
50 | }; | 49 | }; |
51 | 50 | ||
52 | /* common routines */ | 51 | /* Common routines */ |
53 | 52 | ||
54 | static int in_cksum(unsigned short *buf, int sz) | 53 | static int in_cksum(unsigned short *buf, int sz) |
55 | { | 54 | { |
@@ -76,40 +75,41 @@ static int in_cksum(unsigned short *buf, int sz) | |||
76 | 75 | ||
77 | #if !ENABLE_FEATURE_FANCY_PING | 76 | #if !ENABLE_FEATURE_FANCY_PING |
78 | 77 | ||
79 | /* simple version */ | 78 | /* Simple version */ |
80 | 79 | ||
81 | static char *hostname; | 80 | struct globals { |
81 | char *hostname; | ||
82 | char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; | ||
83 | } FIX_ALIASING; | ||
84 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
85 | #define INIT_G() do { } while (0) | ||
82 | 86 | ||
83 | static void noresp(int ign UNUSED_PARAM) | 87 | static void noresp(int ign UNUSED_PARAM) |
84 | { | 88 | { |
85 | printf("No response from %s\n", hostname); | 89 | printf("No response from %s\n", G.hostname); |
86 | exit(EXIT_FAILURE); | 90 | exit(EXIT_FAILURE); |
87 | } | 91 | } |
88 | 92 | ||
89 | static void ping4(len_and_sockaddr *lsa) | 93 | static void ping4(len_and_sockaddr *lsa) |
90 | { | 94 | { |
91 | struct sockaddr_in pingaddr; | ||
92 | struct icmp *pkt; | 95 | struct icmp *pkt; |
93 | int pingsock, c; | 96 | int pingsock, c; |
94 | char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; | ||
95 | 97 | ||
96 | pingsock = create_icmp_socket(); | 98 | pingsock = create_icmp_socket(); |
97 | pingaddr = lsa->u.sin; | ||
98 | 99 | ||
99 | pkt = (struct icmp *) packet; | 100 | pkt = (struct icmp *) G.packet; |
100 | memset(pkt, 0, sizeof(packet)); | 101 | memset(pkt, 0, sizeof(G.packet)); |
101 | pkt->icmp_type = ICMP_ECHO; | 102 | pkt->icmp_type = ICMP_ECHO; |
102 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet)); | 103 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(G.packet)); |
103 | 104 | ||
104 | c = xsendto(pingsock, packet, DEFDATALEN + ICMP_MINLEN, | 105 | xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); |
105 | (struct sockaddr *) &pingaddr, sizeof(pingaddr)); | ||
106 | 106 | ||
107 | /* listen for replies */ | 107 | /* listen for replies */ |
108 | while (1) { | 108 | while (1) { |
109 | struct sockaddr_in from; | 109 | struct sockaddr_in from; |
110 | socklen_t fromlen = sizeof(from); | 110 | socklen_t fromlen = sizeof(from); |
111 | 111 | ||
112 | c = recvfrom(pingsock, packet, sizeof(packet), 0, | 112 | c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, |
113 | (struct sockaddr *) &from, &fromlen); | 113 | (struct sockaddr *) &from, &fromlen); |
114 | if (c < 0) { | 114 | if (c < 0) { |
115 | if (errno != EINTR) | 115 | if (errno != EINTR) |
@@ -117,9 +117,9 @@ static void ping4(len_and_sockaddr *lsa) | |||
117 | continue; | 117 | continue; |
118 | } | 118 | } |
119 | if (c >= 76) { /* ip + icmp */ | 119 | if (c >= 76) { /* ip + icmp */ |
120 | struct iphdr *iphdr = (struct iphdr *) packet; | 120 | struct iphdr *iphdr = (struct iphdr *) G.packet; |
121 | 121 | ||
122 | pkt = (struct icmp *) (packet + (iphdr->ihl << 2)); /* skip ip hdr */ | 122 | pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ |
123 | if (pkt->icmp_type == ICMP_ECHOREPLY) | 123 | if (pkt->icmp_type == ICMP_ECHOREPLY) |
124 | break; | 124 | break; |
125 | } | 125 | } |
@@ -131,31 +131,27 @@ static void ping4(len_and_sockaddr *lsa) | |||
131 | #if ENABLE_PING6 | 131 | #if ENABLE_PING6 |
132 | static void ping6(len_and_sockaddr *lsa) | 132 | static void ping6(len_and_sockaddr *lsa) |
133 | { | 133 | { |
134 | struct sockaddr_in6 pingaddr; | ||
135 | struct icmp6_hdr *pkt; | 134 | struct icmp6_hdr *pkt; |
136 | int pingsock, c; | 135 | int pingsock, c; |
137 | int sockopt; | 136 | int sockopt; |
138 | char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; | ||
139 | 137 | ||
140 | pingsock = create_icmp6_socket(); | 138 | pingsock = create_icmp6_socket(); |
141 | pingaddr = lsa->u.sin6; | ||
142 | 139 | ||
143 | pkt = (struct icmp6_hdr *) packet; | 140 | pkt = (struct icmp6_hdr *) G.packet; |
144 | memset(pkt, 0, sizeof(packet)); | 141 | memset(pkt, 0, sizeof(G.packet)); |
145 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; | 142 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; |
146 | 143 | ||
147 | sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); | 144 | sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); |
148 | setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt)); | 145 | setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt)); |
149 | 146 | ||
150 | c = xsendto(pingsock, packet, DEFDATALEN + sizeof (struct icmp6_hdr), | 147 | xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len); |
151 | (struct sockaddr *) &pingaddr, sizeof(pingaddr)); | ||
152 | 148 | ||
153 | /* listen for replies */ | 149 | /* listen for replies */ |
154 | while (1) { | 150 | while (1) { |
155 | struct sockaddr_in6 from; | 151 | struct sockaddr_in6 from; |
156 | socklen_t fromlen = sizeof(from); | 152 | socklen_t fromlen = sizeof(from); |
157 | 153 | ||
158 | c = recvfrom(pingsock, packet, sizeof(packet), 0, | 154 | c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, |
159 | (struct sockaddr *) &from, &fromlen); | 155 | (struct sockaddr *) &from, &fromlen); |
160 | if (c < 0) { | 156 | if (c < 0) { |
161 | if (errno != EINTR) | 157 | if (errno != EINTR) |
@@ -163,7 +159,7 @@ static void ping6(len_and_sockaddr *lsa) | |||
163 | continue; | 159 | continue; |
164 | } | 160 | } |
165 | if (c >= ICMP_MINLEN) { /* icmp6_hdr */ | 161 | if (c >= ICMP_MINLEN) { /* icmp6_hdr */ |
166 | pkt = (struct icmp6_hdr *) packet; | 162 | pkt = (struct icmp6_hdr *) G.packet; |
167 | if (pkt->icmp6_type == ICMP6_ECHO_REPLY) | 163 | if (pkt->icmp6_type == ICMP6_ECHO_REPLY) |
168 | break; | 164 | break; |
169 | } | 165 | } |
@@ -180,6 +176,8 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
180 | { | 176 | { |
181 | len_and_sockaddr *lsa; | 177 | len_and_sockaddr *lsa; |
182 | 178 | ||
179 | INIT_G(); | ||
180 | |||
183 | #if ENABLE_PING6 | 181 | #if ENABLE_PING6 |
184 | while ((++argv)[0] && argv[0][0] == '-') { | 182 | while ((++argv)[0] && argv[0][0] == '-') { |
185 | if (argv[0][1] == '4') { | 183 | if (argv[0][1] == '4') { |
@@ -196,14 +194,14 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
196 | argv++; | 194 | argv++; |
197 | #endif | 195 | #endif |
198 | 196 | ||
199 | hostname = *argv; | 197 | G.hostname = *argv; |
200 | if (!hostname) | 198 | if (!G.hostname) |
201 | bb_show_usage(); | 199 | bb_show_usage(); |
202 | 200 | ||
203 | #if ENABLE_PING6 | 201 | #if ENABLE_PING6 |
204 | lsa = xhost_and_af2sockaddr(hostname, 0, af); | 202 | lsa = xhost_and_af2sockaddr(G.hostname, 0, af); |
205 | #else | 203 | #else |
206 | lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET); | 204 | lsa = xhost_and_af2sockaddr(G.hostname, 0, AF_INET); |
207 | #endif | 205 | #endif |
208 | /* Set timer _after_ DNS resolution */ | 206 | /* Set timer _after_ DNS resolution */ |
209 | signal(SIGALRM, noresp); | 207 | signal(SIGALRM, noresp); |
@@ -215,7 +213,7 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
215 | else | 213 | else |
216 | #endif | 214 | #endif |
217 | ping4(lsa); | 215 | ping4(lsa); |
218 | printf("%s is alive!\n", hostname); | 216 | printf("%s is alive!\n", G.hostname); |
219 | return EXIT_SUCCESS; | 217 | return EXIT_SUCCESS; |
220 | } | 218 | } |
221 | 219 | ||
@@ -223,7 +221,7 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
223 | #else /* FEATURE_FANCY_PING */ | 221 | #else /* FEATURE_FANCY_PING */ |
224 | 222 | ||
225 | 223 | ||
226 | /* full(er) version */ | 224 | /* Full(er) version */ |
227 | 225 | ||
228 | #define OPT_STRING ("qvc:s:w:W:I:4" IF_PING6("6")) | 226 | #define OPT_STRING ("qvc:s:w:W:I:4" IF_PING6("6")) |
229 | enum { | 227 | enum { |
@@ -253,6 +251,9 @@ struct globals { | |||
253 | unsigned deadline; | 251 | unsigned deadline; |
254 | unsigned timeout; | 252 | unsigned timeout; |
255 | unsigned total_secs; | 253 | unsigned total_secs; |
254 | unsigned sizeof_rcv_packet; | ||
255 | char *rcv_packet; /* [datalen + MAXIPLEN + MAXICMPLEN] */ | ||
256 | void *snd_packet; /* [datalen + ipv4/ipv6_const] */ | ||
256 | const char *hostname; | 257 | const char *hostname; |
257 | const char *dotted; | 258 | const char *dotted; |
258 | union { | 259 | union { |
@@ -370,19 +371,20 @@ static void sendping_tail(void (*sp)(int), const void *pkt, int size_pkt) | |||
370 | 371 | ||
371 | static void sendping4(int junk UNUSED_PARAM) | 372 | static void sendping4(int junk UNUSED_PARAM) |
372 | { | 373 | { |
373 | /* +4 reserves a place for timestamp, which may end up sitting | 374 | struct icmp *pkt = G.snd_packet; |
374 | * *after* packet. Saves one if() */ | ||
375 | struct icmp *pkt = alloca(datalen + ICMP_MINLEN + 4); | ||
376 | 375 | ||
377 | memset(pkt, 0, datalen + ICMP_MINLEN + 4); | 376 | //memset(pkt, 0, datalen + ICMP_MINLEN + 4); - G.snd_packet was xzalloced |
378 | pkt->icmp_type = ICMP_ECHO; | 377 | pkt->icmp_type = ICMP_ECHO; |
379 | /*pkt->icmp_code = 0;*/ | 378 | /*pkt->icmp_code = 0;*/ |
380 | /*pkt->icmp_cksum = 0;*/ | 379 | pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */ |
381 | pkt->icmp_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */ | 380 | pkt->icmp_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */ |
382 | pkt->icmp_id = myid; | 381 | pkt->icmp_id = myid; |
383 | 382 | ||
384 | /* We don't do hton, because we will read it back on the same machine */ | 383 | /* If datalen < 4, we store timestamp _past_ the packet, |
384 | * but it's ok - we allocated 4 extra bytes in xzalloc() just in case. | ||
385 | */ | ||
385 | /*if (datalen >= 4)*/ | 386 | /*if (datalen >= 4)*/ |
387 | /* No hton: we'll read it back on the same machine */ | ||
386 | *(uint32_t*)&pkt->icmp_dun = monotonic_us(); | 388 | *(uint32_t*)&pkt->icmp_dun = monotonic_us(); |
387 | 389 | ||
388 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN); | 390 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN); |
@@ -394,7 +396,7 @@ static void sendping6(int junk UNUSED_PARAM) | |||
394 | { | 396 | { |
395 | struct icmp6_hdr *pkt = alloca(datalen + sizeof(struct icmp6_hdr) + 4); | 397 | struct icmp6_hdr *pkt = alloca(datalen + sizeof(struct icmp6_hdr) + 4); |
396 | 398 | ||
397 | memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4); | 399 | //memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4); |
398 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; | 400 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; |
399 | /*pkt->icmp6_code = 0;*/ | 401 | /*pkt->icmp6_code = 0;*/ |
400 | /*pkt->icmp6_cksum = 0;*/ | 402 | /*pkt->icmp6_cksum = 0;*/ |
@@ -404,6 +406,8 @@ static void sendping6(int junk UNUSED_PARAM) | |||
404 | /*if (datalen >= 4)*/ | 406 | /*if (datalen >= 4)*/ |
405 | *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); | 407 | *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); |
406 | 408 | ||
409 | //TODO? pkt->icmp_cksum = in_cksum(...); | ||
410 | |||
407 | sendping_tail(sendping6, pkt, datalen + sizeof(struct icmp6_hdr)); | 411 | sendping_tail(sendping6, pkt, datalen + sizeof(struct icmp6_hdr)); |
408 | } | 412 | } |
409 | #endif | 413 | #endif |
@@ -561,7 +565,6 @@ static void unpack6(char *packet, int sz, /*struct sockaddr_in6 *from,*/ int hop | |||
561 | 565 | ||
562 | static void ping4(len_and_sockaddr *lsa) | 566 | static void ping4(len_and_sockaddr *lsa) |
563 | { | 567 | { |
564 | char packet[datalen + MAXIPLEN + MAXICMPLEN]; | ||
565 | int sockopt; | 568 | int sockopt; |
566 | 569 | ||
567 | pingsock = create_icmp_socket(); | 570 | pingsock = create_icmp_socket(); |
@@ -594,14 +597,14 @@ static void ping4(len_and_sockaddr *lsa) | |||
594 | socklen_t fromlen = (socklen_t) sizeof(from); | 597 | socklen_t fromlen = (socklen_t) sizeof(from); |
595 | int c; | 598 | int c; |
596 | 599 | ||
597 | c = recvfrom(pingsock, packet, sizeof(packet), 0, | 600 | c = recvfrom(pingsock, G.rcv_packet, G.sizeof_rcv_packet, 0, |
598 | (struct sockaddr *) &from, &fromlen); | 601 | (struct sockaddr *) &from, &fromlen); |
599 | if (c < 0) { | 602 | if (c < 0) { |
600 | if (errno != EINTR) | 603 | if (errno != EINTR) |
601 | bb_perror_msg("recvfrom"); | 604 | bb_perror_msg("recvfrom"); |
602 | continue; | 605 | continue; |
603 | } | 606 | } |
604 | unpack4(packet, c, &from); | 607 | unpack4(G.rcv_packet, c, &from); |
605 | if (pingcount && nreceived >= pingcount) | 608 | if (pingcount && nreceived >= pingcount) |
606 | break; | 609 | break; |
607 | } | 610 | } |
@@ -610,7 +613,6 @@ static void ping4(len_and_sockaddr *lsa) | |||
610 | extern int BUG_bad_offsetof_icmp6_cksum(void); | 613 | extern int BUG_bad_offsetof_icmp6_cksum(void); |
611 | static void ping6(len_and_sockaddr *lsa) | 614 | static void ping6(len_and_sockaddr *lsa) |
612 | { | 615 | { |
613 | char packet[datalen + MAXIPLEN + MAXICMPLEN]; | ||
614 | int sockopt; | 616 | int sockopt; |
615 | struct msghdr msg; | 617 | struct msghdr msg; |
616 | struct sockaddr_in6 from; | 618 | struct sockaddr_in6 from; |
@@ -670,8 +672,8 @@ static void ping6(len_and_sockaddr *lsa) | |||
670 | msg.msg_iov = &iov; | 672 | msg.msg_iov = &iov; |
671 | msg.msg_iovlen = 1; | 673 | msg.msg_iovlen = 1; |
672 | msg.msg_control = control_buf; | 674 | msg.msg_control = control_buf; |
673 | iov.iov_base = packet; | 675 | iov.iov_base = G.rcv_packet; |
674 | iov.iov_len = sizeof(packet); | 676 | iov.iov_len = G.sizeof_rcv_packet; |
675 | while (1) { | 677 | while (1) { |
676 | int c; | 678 | int c; |
677 | struct cmsghdr *mp; | 679 | struct cmsghdr *mp; |
@@ -694,7 +696,7 @@ static void ping6(len_and_sockaddr *lsa) | |||
694 | move_from_unaligned_int(hoplimit, CMSG_DATA(mp)); | 696 | move_from_unaligned_int(hoplimit, CMSG_DATA(mp)); |
695 | } | 697 | } |
696 | } | 698 | } |
697 | unpack6(packet, c, /*&from,*/ hoplimit); | 699 | unpack6(G.rcv_packet, c, /*&from,*/ hoplimit); |
698 | if (pingcount && nreceived >= pingcount) | 700 | if (pingcount && nreceived >= pingcount) |
699 | break; | 701 | break; |
700 | } | 702 | } |
@@ -710,12 +712,20 @@ static void ping(len_and_sockaddr *lsa) | |||
710 | } | 712 | } |
711 | printf(": %d data bytes\n", datalen); | 713 | printf(": %d data bytes\n", datalen); |
712 | 714 | ||
715 | G.sizeof_rcv_packet = datalen + MAXIPLEN + MAXICMPLEN; | ||
716 | G.rcv_packet = xzalloc(G.sizeof_rcv_packet); | ||
713 | #if ENABLE_PING6 | 717 | #if ENABLE_PING6 |
714 | if (lsa->u.sa.sa_family == AF_INET6) | 718 | if (lsa->u.sa.sa_family == AF_INET6) { |
719 | /* +4 reserves a place for timestamp, which may end up sitting | ||
720 | * _after_ packet. Saves one if() - see sendping4/6() */ | ||
721 | G.snd_packet = xzalloc(datalen + sizeof(struct icmp6_hdr) + 4); | ||
715 | ping6(lsa); | 722 | ping6(lsa); |
716 | else | 723 | } else |
717 | #endif | 724 | #endif |
725 | { | ||
726 | G.snd_packet = xzalloc(datalen + ICMP_MINLEN + 4); | ||
718 | ping4(lsa); | 727 | ping4(lsa); |
728 | } | ||
719 | } | 729 | } |
720 | 730 | ||
721 | static int common_ping_main(int opt, char **argv) | 731 | static int common_ping_main(int opt, char **argv) |