Magellan Linux

Diff of /tags/mkinitrd-6_3_1/busybox/networking/arping.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 8  Line 8 
8   * Busybox port: Nick Fedchik <nick@fedchik.org.ua>   * Busybox port: Nick Fedchik <nick@fedchik.org.ua>
9   */   */
10    
 #include <sys/ioctl.h>  
 #include <signal.h>  
   
11  #include <arpa/inet.h>  #include <arpa/inet.h>
12  #include <net/if.h>  #include <net/if.h>
13  #include <netinet/ether.h>  #include <netinet/ether.h>
14  #include <netpacket/packet.h>  #include <netpacket/packet.h>
15    
16  #include "busybox.h"  #include "libbb.h"
17    
18  static struct in_addr src;  /* We don't expect to see 1000+ seconds delay, unsigned is enough */
19  static struct in_addr dst;  #define MONOTONIC_US() ((unsigned)monotonic_us())
 static struct sockaddr_ll me;  
 static struct sockaddr_ll he;  
 static struct timeval last;  
   
 enum cfg_e {  
  dad = 1,  
  unsolicited = 2,  
  advert = 4,  
  quiet = 8,  
  quit_on_reply = 16,  
  broadcast_only = 32,  
  unicasting = 64  
 };  
 static int cfg;  
20    
21  static int s;  enum {
22  static unsigned count = UINT_MAX;   DAD = 1,
23  static unsigned timeout;   UNSOLICITED = 2,
24  static int sent;   ADVERT = 4,
25  static int brd_sent;   QUIET = 8,
26  static int received;   QUIT_ON_REPLY = 16,
27  static int brd_recv;   BCAST_ONLY = 32,
28  static int req_recv;   UNICASTING = 64
29    };
30    
31  #define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \  struct globals {
32   ((tv1).tv_usec-(tv2).tv_usec)/1000 )   struct in_addr src;
33     struct in_addr dst;
34     struct sockaddr_ll me;
35     struct sockaddr_ll he;
36     int sock_fd;
37    
38     int count; // = -1;
39     unsigned last;
40     unsigned timeout_us;
41     unsigned start;
42    
43     unsigned sent;
44     unsigned brd_sent;
45     unsigned received;
46     unsigned brd_recv;
47     unsigned req_recv;
48    };
49    #define G (*(struct globals*)&bb_common_bufsiz1)
50    #define src        (G.src       )
51    #define dst        (G.dst       )
52    #define me         (G.me        )
53    #define he         (G.he        )
54    #define sock_fd    (G.sock_fd   )
55    #define count      (G.count     )
56    #define last       (G.last      )
57    #define timeout_us (G.timeout_us)
58    #define start      (G.start     )
59    #define sent       (G.sent      )
60    #define brd_sent   (G.brd_sent  )
61    #define received   (G.received  )
62    #define brd_recv   (G.brd_recv  )
63    #define req_recv   (G.req_recv  )
64    #define INIT_G() do { \
65     count = -1; \
66    } while (0)
67    
68    // If GNUisms are not available...
69    //static void *mempcpy(void *_dst, const void *_src, int n)
70    //{
71    // memcpy(_dst, _src, n);
72    // return (char*)_dst + n;
73    //}
74    
75  static int send_pack(int sock, struct in_addr *src_addr,  static int send_pack(struct in_addr *src_addr,
76   struct in_addr *dst_addr, struct sockaddr_ll *ME,   struct in_addr *dst_addr, struct sockaddr_ll *ME,
77   struct sockaddr_ll *HE)   struct sockaddr_ll *HE)
78  {  {
79   int err;   int err;
80   struct timeval now;   unsigned char buf[256];
  RESERVE_CONFIG_UBUFFER(buf, 256);  
81   struct arphdr *ah = (struct arphdr *) buf;   struct arphdr *ah = (struct arphdr *) buf;
82   unsigned char *p = (unsigned char *) (ah + 1);   unsigned char *p = (unsigned char *) (ah + 1);
83    
  ah->ar_hrd = htons(ME->sll_hatype);  
84   ah->ar_hrd = htons(ARPHRD_ETHER);   ah->ar_hrd = htons(ARPHRD_ETHER);
85   ah->ar_pro = htons(ETH_P_IP);   ah->ar_pro = htons(ETH_P_IP);
86   ah->ar_hln = ME->sll_halen;   ah->ar_hln = ME->sll_halen;
87   ah->ar_pln = 4;   ah->ar_pln = 4;
88   ah->ar_op = cfg & advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);   ah->ar_op = option_mask32 & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
89    
90   memcpy(p, &ME->sll_addr, ah->ar_hln);   p = mempcpy(p, &ME->sll_addr, ah->ar_hln);
91   p += ME->sll_halen;   p = mempcpy(p, src_addr, 4);
92    
93   memcpy(p, src_addr, 4);   if (option_mask32 & ADVERT)
94   p += 4;   p = mempcpy(p, &ME->sll_addr, ah->ar_hln);
   
  if (cfg & advert)  
  memcpy(p, &ME->sll_addr, ah->ar_hln);  
95   else   else
96   memcpy(p, &HE->sll_addr, ah->ar_hln);   p = mempcpy(p, &HE->sll_addr, ah->ar_hln);
  p += ah->ar_hln;  
97    
98   memcpy(p, dst_addr, 4);   p = mempcpy(p, dst_addr, 4);
  p += 4;  
99    
100   gettimeofday(&now, NULL);   err = sendto(sock_fd, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
  err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));  
101   if (err == p - buf) {   if (err == p - buf) {
102   last = now;   last = MONOTONIC_US();
103   sent++;   sent++;
104   if (!(cfg & unicasting))   if (!(option_mask32 & UNICASTING))
105   brd_sent++;   brd_sent++;
106   }   }
  RELEASE_CONFIG_BUFFER(buf);  
107   return err;   return err;
108  }  }
109    
110    static void finish(void) NORETURN;
111  static void finish(void)  static void finish(void)
112  {  {
113   if (!(cfg & quiet)) {   if (!(option_mask32 & QUIET)) {
114   printf("Sent %d probe(s) (%d broadcast(s))\n"   printf("Sent %u probe(s) (%u broadcast(s))\n"
115   "Received %d repl%s"   "Received %u repl%s"
116   " (%d request(s), %d broadcast(s))\n",   " (%u request(s), %u broadcast(s))\n",
117   sent, brd_sent,   sent, brd_sent,
118   received, (received == 1) ? "ies" : "y",   received, (received == 1) ? "ies" : "y",
119   req_recv, brd_recv);   req_recv, brd_recv);
120   }   }
121   if (cfg & dad)   if (option_mask32 & DAD)
122   exit(!!received);   exit(!!received);
123   if (cfg & unsolicited)   if (option_mask32 & UNSOLICITED)
124   exit(0);   exit(EXIT_SUCCESS);
125   exit(!received);   exit(!received);
126  }  }
127    
128  static void catcher(void)  static void catcher(void)
129  {  {
130   struct timeval tv;   unsigned now;
  static struct timeval start;  
   
  gettimeofday(&tv, NULL);  
131    
132   if (start.tv_sec == 0)   now = MONOTONIC_US();
133   start = tv;   if (start == 0)
134     start = now;
135    
136   if (count-- == 0   if (count == 0 || (timeout_us && (now - start) > timeout_us))
  || (timeout && MS_TDIFF(tv, start) > timeout * 1000 + 500))  
137   finish();   finish();
138    
139   if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) {   /* count < 0 means "infinite count" */
140   send_pack(s, &src, &dst, &me, &he);   if (count > 0)
141   if (count == 0 && (cfg & unsolicited))   count--;
142    
143     if (last == 0 || (now - last) > 500000) {
144     send_pack(&src, &dst, &me, &he);
145     if (count == 0 && (option_mask32 & UNSOLICITED))
146   finish();   finish();
147   }   }
148   alarm(1);   alarm(1);
149  }  }
150    
151  static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)  static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
152  {  {
153   struct arphdr *ah = (struct arphdr *) buf;   struct arphdr *ah = (struct arphdr *) buf;
154   unsigned char *p = (unsigned char *) (ah + 1);   unsigned char *p = (unsigned char *) (ah + 1);
# Line 140  static int recv_pack(unsigned char *buf, Line 158  static int recv_pack(unsigned char *buf,
158   if (FROM->sll_pkttype != PACKET_HOST   if (FROM->sll_pkttype != PACKET_HOST
159   && FROM->sll_pkttype != PACKET_BROADCAST   && FROM->sll_pkttype != PACKET_BROADCAST
160   && FROM->sll_pkttype != PACKET_MULTICAST)   && FROM->sll_pkttype != PACKET_MULTICAST)
161   return 0;   return false;
162    
163   /* Only these types are recognised */   /* Only these types are recognised */
164   if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))   if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
165   return 0;   return false;
166    
167   /* ARPHRD check and this darned FDDI hack here :-( */   /* ARPHRD check and this darned FDDI hack here :-( */
168   if (ah->ar_hrd != htons(FROM->sll_hatype)   if (ah->ar_hrd != htons(FROM->sll_hatype)
169   && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))   && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))
170   return 0;   return false;
171    
172   /* Protocol must be IP. */   /* Protocol must be IP. */
173   if (ah->ar_pro != htons(ETH_P_IP))   if (ah->ar_pro != htons(ETH_P_IP)
174   return 0;   || (ah->ar_pln != 4)
175   if (ah->ar_pln != 4)   || (ah->ar_hln != me.sll_halen)
176   return 0;   || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))))
177   if (ah->ar_hln != me.sll_halen)   return false;
178   return 0;  
  if (len < sizeof(*ah) + 2 * (4 + ah->ar_hln))  
  return 0;  
179   memcpy(&src_ip, p + ah->ar_hln, 4);   memcpy(&src_ip, p + ah->ar_hln, 4);
180   memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);   memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
181   if (!(cfg & dad)) {  
182   if (src_ip.s_addr != dst.s_addr)   if (dst.s_addr != src_ip.s_addr)
183   return 0;   return false;
184   if (src.s_addr != dst_ip.s_addr)   if (!(option_mask32 & DAD)) {
185   return 0;   if ((src.s_addr != dst_ip.s_addr)
186   if (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln))   || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)))
187   return 0;   return false;
188   } else {   } else {
189   /* DAD packet was:   /* DAD packet was:
190     src_ip = 0 (or some src)     src_ip = 0 (or some src)
# Line 183  static int recv_pack(unsigned char *buf, Line 199  static int recv_pack(unsigned char *buf,
199     also that it matches to dst_ip, otherwise     also that it matches to dst_ip, otherwise
200     dst_ip/dst_hw do not matter.     dst_ip/dst_hw do not matter.
201   */   */
202   if (src_ip.s_addr != dst.s_addr)   if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0)
203   return 0;   || (src.s_addr && src.s_addr != dst_ip.s_addr))
204   if (memcmp(p, &me.sll_addr, me.sll_halen) == 0)   return false;
  return 0;  
  if (src.s_addr && src.s_addr != dst_ip.s_addr)  
  return 0;  
205   }   }
206   if (!(cfg & quiet)) {   if (!(option_mask32 & QUIET)) {
207   int s_printed = 0;   int s_printed = 0;
  struct timeval tv;  
   
  gettimeofday(&tv, NULL);  
208    
209   printf("%scast re%s from %s [%s]",   printf("%scast re%s from %s [%s]",
210   FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",   FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",
# Line 212  static int recv_pack(unsigned char *buf, Line 222  static int recv_pack(unsigned char *buf,
222   ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));   ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));
223   }   }
224    
225   if (last.tv_sec) {   if (last) {
226   long usecs = (tv.tv_sec - last.tv_sec) * 1000000 +   unsigned diff = MONOTONIC_US() - last;
227   tv.tv_usec - last.tv_usec;   printf(" %u.%03ums\n", diff / 1000, diff % 1000);
  long msecs = (usecs + 500) / 1000;  
   
  usecs -= msecs * 1000 - 500;  
  printf(" %ld.%03ldms\n", msecs, usecs);  
228   } else {   } else {
229   printf(" UNSOLICITED?\n");   printf(" UNSOLICITED?\n");
230   }   }
# Line 229  static int recv_pack(unsigned char *buf, Line 235  static int recv_pack(unsigned char *buf,
235   brd_recv++;   brd_recv++;
236   if (ah->ar_op == htons(ARPOP_REQUEST))   if (ah->ar_op == htons(ARPOP_REQUEST))
237   req_recv++;   req_recv++;
238   if (cfg & quit_on_reply)   if (option_mask32 & QUIT_ON_REPLY)
239   finish();   finish();
240   if (!(cfg & broadcast_only)) {   if (!(option_mask32 & BCAST_ONLY)) {
241   memcpy(he.sll_addr, p, me.sll_halen);   memcpy(he.sll_addr, p, me.sll_halen);
242   cfg |= unicasting;   option_mask32 |= UNICASTING;
243   }   }
244   return 1;   return true;
245  }  }
246    
247  int arping_main(int argc, char **argv)  int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
248    int arping_main(int argc UNUSED_PARAM, char **argv)
249  {  {
250   char *device = "eth0";   const char *device = "eth0";
  int ifindex;  
251   char *source = NULL;   char *source = NULL;
252   char *target;   char *target;
253     unsigned char *packet;
254     char *err_str;
255    
256   s = xsocket(PF_PACKET, SOCK_DGRAM, 0);   INIT_G();
257    
258     sock_fd = xsocket(AF_PACKET, SOCK_DGRAM, 0);
259    
260   // Drop suid root privileges   // Drop suid root privileges
261   xsetuid(getuid());   // Need to remove SUID_NEVER from applets.h for this to work
262     //xsetuid(getuid());
263    
264     err_str = xasprintf("interface %s %%s", device);
265   {   {
266   unsigned opt;   unsigned opt;
267   char *_count, *_timeout;   char *str_timeout;
268    
269   /* Dad also sets quit_on_reply.   /* Dad also sets quit_on_reply.
270   * Advert also sets unsolicited.   * Advert also sets unsolicited.
271   */   */
272   opt_complementary = "Df:AU";   opt_complementary = "=1:Df:AU:c+";
273   opt = getopt32(argc, argv, "DUAqfbc:w:i:s:",   opt = getopt32(argv, "DUAqfbc:w:I:s:",
274   &_count, &_timeout, &device, &source);   &count, &str_timeout, &device, &source);
  cfg |= opt & 0x3f; /* set respective flags */  
  if (opt & 0x40) /* -c: count */  
  count = xatou(_count);  
275   if (opt & 0x80) /* -w: timeout */   if (opt & 0x80) /* -w: timeout */
276   timeout = xatoul_range(_timeout, 0, INT_MAX/2000);   timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000;
  //if (opt & 0x100) /* -i: interface */  
  if (strlen(device) > IF_NAMESIZE) {  
  bb_error_msg_and_die("interface name '%s' is too long",  
  device);  
  }  
277   //if (opt & 0x200) /* -s: source */   //if (opt & 0x200) /* -s: source */
278     option_mask32 &= 0x3f; /* set respective flags */
279   }   }
  argc -= optind;  
  argv += optind;  
   
  if (argc != 1)  
  bb_show_usage();  
280    
281   target = *argv;   target = argv[optind];
282    
283   xfunc_error_retval = 2;   xfunc_error_retval = 2;
284    
# Line 286  int arping_main(int argc, char **argv) Line 286  int arping_main(int argc, char **argv)
286   struct ifreq ifr;   struct ifreq ifr;
287    
288   memset(&ifr, 0, sizeof(ifr));   memset(&ifr, 0, sizeof(ifr));
289   strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);   strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
290   if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {   /* We use ifr.ifr_name in error msg so that problem
291   bb_error_msg_and_die("interface %s not found", device);   * with truncated name will be visible */
292   }   ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found");
293   ifindex = ifr.ifr_ifindex;   me.sll_ifindex = ifr.ifr_ifindex;
294    
295     xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr);
296    
  if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) {  
  bb_error_msg_and_die("SIOCGIFFLAGS");  
  }  
297   if (!(ifr.ifr_flags & IFF_UP)) {   if (!(ifr.ifr_flags & IFF_UP)) {
298   bb_error_msg_and_die("interface %s is down", device);   bb_error_msg_and_die(err_str, "is down");
299   }   }
300   if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {   if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
301   bb_error_msg("interface %s is not ARPable", device);   bb_error_msg(err_str, "is not ARPable");
302   return (cfg & dad ? 0 : 2);   return (option_mask32 & DAD ? 0 : 2);
303   }   }
304   }   }
305    
306   if (!inet_aton(target, &dst)) {   /* if (!inet_aton(target, &dst)) - not needed */ {
307   struct hostent *hp;   len_and_sockaddr *lsa;
308     lsa = xhost_and_af2sockaddr(target, 0, AF_INET);
309   hp = gethostbyname2(target, AF_INET);   memcpy(&dst, &lsa->u.sin.sin_addr.s_addr, 4);
310   if (!hp) {   if (ENABLE_FEATURE_CLEAN_UP)
311   bb_error_msg_and_die("invalid or unknown target %s", target);   free(lsa);
  }  
  memcpy(&dst, hp->h_addr, 4);  
312   }   }
313    
314   if (source && !inet_aton(source, &src)) {   if (source && !inet_aton(source, &src)) {
315   bb_error_msg_and_die("invalid source address %s", source);   bb_error_msg_and_die("invalid source address %s", source);
316   }   }
317    
318   if (!(cfg & dad) && (cfg & unsolicited) && src.s_addr == 0)   if ((option_mask32 & (DAD|UNSOLICITED)) == UNSOLICITED && src.s_addr == 0)
319   src = dst;   src = dst;
320    
321   if (!(cfg & dad) || src.s_addr) {   if (!(option_mask32 & DAD) || src.s_addr) {
322   struct sockaddr_in saddr;   struct sockaddr_in saddr;
323   int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);   int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
324    
325   if (device) {   setsockopt_bindtodevice(probe_fd, device);
  if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)  
  bb_error_msg("warning: interface %s is ignored", device);  
  }  
326   memset(&saddr, 0, sizeof(saddr));   memset(&saddr, 0, sizeof(saddr));
327   saddr.sin_family = AF_INET;   saddr.sin_family = AF_INET;
328   if (src.s_addr) {   if (src.s_addr) {
329     /* Check that this is indeed our IP */
330   saddr.sin_addr = src;   saddr.sin_addr = src;
331   xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));   xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
332   } else if (!(cfg & dad)) {   } else { /* !(option_mask32 & DAD) case */
333   static const int on = 1;   /* Find IP address on this iface */
334   socklen_t alen = sizeof(saddr);   socklen_t alen = sizeof(saddr);
335    
336   saddr.sin_port = htons(1025);   saddr.sin_port = htons(1025);
337   saddr.sin_addr = dst;   saddr.sin_addr = dst;
338    
339   if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *) &on, sizeof(on)) == -1)   if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1)
340   bb_perror_msg("warning: setsockopt(SO_DONTROUTE)");   bb_perror_msg("setsockopt(SO_DONTROUTE)");
341   xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));   xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
342   if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) {   if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) {
343   bb_error_msg_and_die("getsockname");   bb_perror_msg_and_die("getsockname");
344   }   }
345     if (saddr.sin_family != AF_INET)
346     bb_error_msg_and_die("no IP address configured");
347   src = saddr.sin_addr;   src = saddr.sin_addr;
348   }   }
349   close(probe_fd);   close(probe_fd);
350   }   }
351    
352   me.sll_family = AF_PACKET;   me.sll_family = AF_PACKET;
353   me.sll_ifindex = ifindex;   //me.sll_ifindex = ifindex; - done before
354   me.sll_protocol = htons(ETH_P_ARP);   me.sll_protocol = htons(ETH_P_ARP);
355   xbind(s, (struct sockaddr *) &me, sizeof(me));   xbind(sock_fd, (struct sockaddr *) &me, sizeof(me));
356    
357   {   {
358   socklen_t alen = sizeof(me);   socklen_t alen = sizeof(me);
359    
360   if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) {   if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) {
361   bb_error_msg_and_die("getsockname");   bb_perror_msg_and_die("getsockname");
362   }   }
363   }   }
364   if (me.sll_halen == 0) {   if (me.sll_halen == 0) {
365   bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device);   bb_error_msg(err_str, "is not ARPable (no ll address)");
366   return (cfg & dad ? 0 : 2);   return (option_mask32 & DAD ? 0 : 2);
367   }   }
368   he = me;   he = me;
369   memset(he.sll_addr, -1, he.sll_halen);   memset(he.sll_addr, -1, he.sll_halen);
370    
371   if (!(cfg & quiet)) {   if (!(option_mask32 & QUIET)) {
372   printf("ARPING to %s from %s via %s\n",   /* inet_ntoa uses static storage, can't use in same printf */
373   inet_ntoa(dst), inet_ntoa(src),   printf("ARPING to %s", inet_ntoa(dst));
374   device ? device : "unknown");   printf(" from %s via %s\n", inet_ntoa(src), device);
375   }   }
376    
377   if (!src.s_addr && !(cfg & dad)) {   signal_SA_RESTART_empty_mask(SIGINT,  (void (*)(int))finish);
378   bb_error_msg_and_die("no src address in the non-DAD mode");   signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher);
  }  
   
  {  
  struct sigaction sa;  
   
  memset(&sa, 0, sizeof(sa));  
  sa.sa_flags = SA_RESTART;  
   
  sa.sa_handler = (void (*)(int)) finish;  
  sigaction(SIGINT, &sa, NULL);  
   
  sa.sa_handler = (void (*)(int)) catcher;  
  sigaction(SIGALRM, &sa, NULL);  
  }  
379    
380   catcher();   catcher();
381    
382     packet = xmalloc(4096);
383   while (1) {   while (1) {
384   sigset_t sset, osset;   sigset_t sset, osset;
  RESERVE_CONFIG_UBUFFER(packet, 4096);  
385   struct sockaddr_ll from;   struct sockaddr_ll from;
386   socklen_t alen = sizeof(from);   socklen_t alen = sizeof(from);
387   int cc;   int cc;
388    
389   cc = recvfrom(s, packet, 4096, 0, (struct sockaddr *) &from, &alen);   cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen);
390   if (cc < 0) {   if (cc < 0) {
391   bb_perror_msg("recvfrom");   bb_perror_msg("recvfrom");
392   continue;   continue;
# Line 414  int arping_main(int argc, char **argv) Line 397  int arping_main(int argc, char **argv)
397   sigprocmask(SIG_BLOCK, &sset, &osset);   sigprocmask(SIG_BLOCK, &sset, &osset);
398   recv_pack(packet, cc, &from);   recv_pack(packet, cc, &from);
399   sigprocmask(SIG_SETMASK, &osset, NULL);   sigprocmask(SIG_SETMASK, &osset, NULL);
  RELEASE_CONFIG_BUFFER(packet);  
400   }   }
401  }  }

Legend:
Removed from v.532  
changed lines
  Added in v.816