aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/arping.c75
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}