diff options
-rw-r--r-- | networking/arping.c | 75 |
1 files changed, 34 insertions, 41 deletions
diff --git a/networking/arping.c b/networking/arping.c index 97e9e680a..a16f04b9f 100644 --- a/networking/arping.c +++ b/networking/arping.c | |||
@@ -79,8 +79,11 @@ struct globals { | |||
79 | unsigned received; | 79 | unsigned received; |
80 | unsigned brd_recv; | 80 | unsigned brd_recv; |
81 | unsigned req_recv; | 81 | unsigned req_recv; |
82 | |||
83 | struct ifreq ifr; | ||
84 | sigset_t sset; | ||
85 | unsigned char packet[4096]; | ||
82 | } FIX_ALIASING; | 86 | } FIX_ALIASING; |
83 | #define G (*(struct globals*)bb_common_bufsiz1) | ||
84 | #define src (G.src ) | 87 | #define src (G.src ) |
85 | #define dst (G.dst ) | 88 | #define dst (G.dst ) |
86 | #define me (G.me ) | 89 | #define me (G.me ) |
@@ -95,8 +98,11 @@ struct globals { | |||
95 | #define received (G.received ) | 98 | #define received (G.received ) |
96 | #define brd_recv (G.brd_recv ) | 99 | #define brd_recv (G.brd_recv ) |
97 | #define req_recv (G.req_recv ) | 100 | #define req_recv (G.req_recv ) |
101 | //#define G (*(struct globals*)bb_common_bufsiz1) | ||
102 | #define G (*ptr_to_globals) | ||
98 | #define INIT_G() do { \ | 103 | #define INIT_G() do { \ |
99 | setup_common_bufsiz(); \ | 104 | /*setup_common_bufsiz();*/ \ |
105 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
100 | count = -1; \ | 106 | count = -1; \ |
101 | } while (0) | 107 | } while (0) |
102 | 108 | ||
@@ -183,15 +189,10 @@ static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
183 | struct arphdr *ah = (struct arphdr *) buf; | 189 | struct arphdr *ah = (struct arphdr *) buf; |
184 | unsigned char *p = (unsigned char *) (ah + 1); | 190 | unsigned char *p = (unsigned char *) (ah + 1); |
185 | struct in_addr src_ip, dst_ip; | 191 | struct in_addr src_ip, dst_ip; |
192 | |||
186 | /* moves below assume in_addr is 4 bytes big, ensure that */ | 193 | /* moves below assume in_addr is 4 bytes big, ensure that */ |
187 | struct BUG_in_addr_must_be_4 { | 194 | BUILD_BUG_ON(sizeof(struct in_addr) != 4); |
188 | char BUG_in_addr_must_be_4[ | 195 | BUILD_BUG_ON(sizeof(src_ip.s_addr) != 4); |
189 | sizeof(struct in_addr) == 4 ? 1 : -1 | ||
190 | ]; | ||
191 | char BUG_s_addr_must_be_4[ | ||
192 | sizeof(src_ip.s_addr) == 4 ? 1 : -1 | ||
193 | ]; | ||
194 | }; | ||
195 | 196 | ||
196 | /* Filter out wild packets */ | 197 | /* Filter out wild packets */ |
197 | if (FROM->sll_pkttype != PACKET_HOST | 198 | if (FROM->sll_pkttype != PACKET_HOST |
@@ -212,8 +213,10 @@ static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
212 | if (ah->ar_pro != htons(ETH_P_IP) | 213 | if (ah->ar_pro != htons(ETH_P_IP) |
213 | || (ah->ar_pln != 4) | 214 | || (ah->ar_pln != 4) |
214 | || (ah->ar_hln != me.sll_halen) | 215 | || (ah->ar_hln != me.sll_halen) |
215 | || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln)))) | 216 | || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))) |
217 | ) { | ||
216 | return; | 218 | return; |
219 | } | ||
217 | 220 | ||
218 | move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln); | 221 | move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln); |
219 | move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln); | 222 | move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln); |
@@ -292,7 +295,6 @@ int arping_main(int argc UNUSED_PARAM, char **argv) | |||
292 | const char *device = "eth0"; | 295 | const char *device = "eth0"; |
293 | char *source = NULL; | 296 | char *source = NULL; |
294 | char *target; | 297 | char *target; |
295 | unsigned char *packet; | ||
296 | char *err_str; | 298 | char *err_str; |
297 | 299 | ||
298 | INIT_G(); | 300 | INIT_G(); |
@@ -316,27 +318,21 @@ int arping_main(int argc UNUSED_PARAM, char **argv) | |||
316 | err_str = xasprintf("interface %s %%s", device); | 318 | err_str = xasprintf("interface %s %%s", device); |
317 | xfunc_error_retval = 2; | 319 | xfunc_error_retval = 2; |
318 | 320 | ||
319 | { | 321 | /*memset(&G.ifr, 0, sizeof(G.ifr)); - zeroed by INIT_G */ |
320 | struct ifreq ifr; | 322 | strncpy_IFNAMSIZ(G.ifr.ifr_name, device); |
321 | 323 | ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &G.ifr, err_str, "not found"); | |
322 | memset(&ifr, 0, sizeof(ifr)); | 324 | me.sll_ifindex = G.ifr.ifr_ifindex; |
323 | strncpy_IFNAMSIZ(ifr.ifr_name, device); | ||
324 | /* We use ifr.ifr_name in error msg so that problem | ||
325 | * with truncated name will be visible */ | ||
326 | ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found"); | ||
327 | me.sll_ifindex = ifr.ifr_ifindex; | ||
328 | 325 | ||
329 | xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr); | 326 | xioctl(sock_fd, SIOCGIFFLAGS, (char *) &G.ifr); |
330 | 327 | ||
331 | if (!(ifr.ifr_flags & IFF_UP)) { | 328 | if (!(G.ifr.ifr_flags & IFF_UP)) { |
332 | bb_error_msg_and_die(err_str, "is down"); | 329 | bb_error_msg_and_die(err_str, "is down"); |
333 | } | 330 | } |
334 | if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { | 331 | if (G.ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { |
335 | bb_error_msg(err_str, "is not ARPable"); | 332 | bb_error_msg(err_str, "is not ARPable"); |
336 | BUILD_BUG_ON(DAD != 2); | 333 | BUILD_BUG_ON(DAD != 2); |
337 | /* exit 0 if DAD, else exit 2 */ | 334 | /* exit 0 if DAD, else exit 2 */ |
338 | return (~option_mask32 & DAD); | 335 | return (~option_mask32 & DAD); |
339 | } | ||
340 | } | 336 | } |
341 | 337 | ||
342 | /* if (!inet_aton(target, &dst)) - not needed */ { | 338 | /* if (!inet_aton(target, &dst)) - not needed */ { |
@@ -413,8 +409,9 @@ int arping_main(int argc UNUSED_PARAM, char **argv) | |||
413 | printf(" from %s %s\n", inet_ntoa(src), device); | 409 | printf(" from %s %s\n", inet_ntoa(src), device); |
414 | } | 410 | } |
415 | 411 | ||
416 | packet = xmalloc(4096); | 412 | /*sigemptyset(&G.sset); - zeroed by INIT_G */ |
417 | 413 | sigaddset(&G.sset, SIGALRM); | |
414 | sigaddset(&G.sset, SIGINT); | ||
418 | signal_SA_RESTART_empty_mask(SIGINT, (void (*)(int))finish); | 415 | signal_SA_RESTART_empty_mask(SIGINT, (void (*)(int))finish); |
419 | signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher); | 416 | signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher); |
420 | 417 | ||
@@ -422,28 +419,24 @@ int arping_main(int argc UNUSED_PARAM, char **argv) | |||
422 | catcher(); | 419 | catcher(); |
423 | 420 | ||
424 | while (1) { | 421 | while (1) { |
425 | sigset_t sset; | ||
426 | struct sockaddr_ll from; | 422 | struct sockaddr_ll from; |
427 | socklen_t alen = sizeof(from); | 423 | socklen_t alen = sizeof(from); |
428 | int cc; | 424 | int cc; |
429 | 425 | ||
430 | sigemptyset(&sset); | ||
431 | sigaddset(&sset, SIGALRM); | ||
432 | sigaddset(&sset, SIGINT); | ||
433 | /* Unblock SIGALRM so that the previously called alarm() | 426 | /* Unblock SIGALRM so that the previously called alarm() |
434 | * can prevent recvfrom from blocking forever in case the | 427 | * can prevent recvfrom from blocking forever in case the |
435 | * inherited procmask is blocking SIGALRM. | 428 | * inherited procmask is blocking SIGALRM. |
436 | */ | 429 | */ |
437 | sigprocmask(SIG_UNBLOCK, &sset, NULL); | 430 | sigprocmask(SIG_UNBLOCK, &G.sset, NULL); |
438 | 431 | ||
439 | cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen); | 432 | cc = recvfrom(sock_fd, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &alen); |
440 | 433 | ||
441 | /* Don't allow SIGALRMs while we process the reply */ | 434 | /* Don't allow SIGALRMs while we process the reply */ |
442 | sigprocmask(SIG_BLOCK, &sset, NULL); | 435 | sigprocmask(SIG_BLOCK, &G.sset, NULL); |
443 | if (cc < 0) { | 436 | if (cc < 0) { |
444 | bb_perror_msg("recvfrom"); | 437 | bb_perror_msg("recvfrom"); |
445 | continue; | 438 | continue; |
446 | } | 439 | } |
447 | recv_pack(packet, cc, &from); | 440 | recv_pack(G.packet, cc, &from); |
448 | } | 441 | } |
449 | } | 442 | } |