Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/arping.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/arping.c
r821 r1770 9 9 */ 10 10 11 #include <sys/ioctl.h>12 #include <signal.h>13 14 #include <errno.h>15 #include <stdlib.h>16 #include <string.h>17 #include <unistd.h>18 19 11 #include <arpa/inet.h> 20 12 #include <net/if.h> … … 22 14 #include <netpacket/packet.h> 23 15 24 #include "busybox.h" 16 #include "libbb.h" 17 18 /* We don't expect to see 1000+ seconds delay, unsigned is enough */ 19 #define MONOTONIC_US() ((unsigned)monotonic_us()) 25 20 26 21 static struct in_addr src; … … 28 23 static struct sockaddr_ll me; 29 24 static struct sockaddr_ll he; 30 static struct timevallast;31 32 enum cfg_e{33 dad= 1,34 unsolicited= 2,35 advert= 4,36 quiet= 8,37 quit_on_reply= 16,38 broadcast_only= 32,39 unicasting= 6425 static unsigned last; 26 27 enum { 28 DAD = 1, 29 UNSOLICITED = 2, 30 ADVERT = 4, 31 QUIET = 8, 32 QUIT_ON_REPLY = 16, 33 BCAST_ONLY = 32, 34 UNICASTING = 64 40 35 }; 41 static int cfg; 42 43 static int s; 44 static int count = -1; 45 static int timeout; 46 static int sent; 47 static int brd_sent; 48 static int received; 49 static int brd_recv; 50 static int req_recv; 51 52 53 #define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \ 54 ((tv1).tv_usec-(tv2).tv_usec)/1000 ) 55 #if 0 56 static void set_signal(int signo, void (*handler) (void)) 57 { 58 struct sigaction sa; 59 60 memset(&sa, 0, sizeof(sa)); 61 sa.sa_handler = (void (*)(int)) handler; 62 sa.sa_flags = SA_RESTART; 63 sigaction(signo, &sa, NULL); 64 } 65 #endif 66 67 static int send_pack(int sock, struct in_addr *src_addr, 68 struct in_addr *dst_addr, struct sockaddr_ll *ME, 69 struct sockaddr_ll *HE) 36 37 static int sock; 38 static unsigned count = UINT_MAX; 39 static unsigned timeout_us; 40 static unsigned sent; 41 static unsigned brd_sent; 42 static unsigned received; 43 static unsigned brd_recv; 44 static unsigned req_recv; 45 46 static int send_pack(struct in_addr *src_addr, 47 struct in_addr *dst_addr, struct sockaddr_ll *ME, 48 struct sockaddr_ll *HE) 70 49 { 71 50 int err; 72 struct timevalnow;73 RESERVE_CONFIG_UBUFFER(buf, 256);51 unsigned now; 52 unsigned char buf[256]; 74 53 struct arphdr *ah = (struct arphdr *) buf; 75 54 unsigned char *p = (unsigned char *) (ah + 1); … … 80 59 ah->ar_hln = ME->sll_halen; 81 60 ah->ar_pln = 4; 82 ah->ar_op = cfg&advert? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);61 ah->ar_op = option_mask32 & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); 83 62 84 63 memcpy(p, &ME->sll_addr, ah->ar_hln); … … 88 67 p += 4; 89 68 90 if ( cfg&advert)69 if (option_mask32 & ADVERT) 91 70 memcpy(p, &ME->sll_addr, ah->ar_hln); 92 71 else … … 97 76 p += 4; 98 77 99 gettimeofday(&now, NULL);78 now = MONOTONIC_US(); 100 79 err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); 101 80 if (err == p - buf) { 102 81 last = now; 103 82 sent++; 104 if (!( cfg&unicasting))83 if (!(option_mask32 & UNICASTING)) 105 84 brd_sent++; 106 85 } 107 RELEASE_CONFIG_BUFFER(buf);108 86 return err; 109 87 } 110 88 89 static void finish(void) ATTRIBUTE_NORETURN; 111 90 static void finish(void) 112 91 { 113 if (!(cfg&quiet)) { 114 printf("Sent %d probes (%d broadcast(s))\n" 115 "Received %d repl%s", 92 if (!(option_mask32 & QUIET)) { 93 printf("Sent %u probe(s) (%u broadcast(s))\n" 94 "Received %u repl%s" 95 " (%u request(s), %u broadcast(s))\n", 116 96 sent, brd_sent, 117 received, (received > 1) ? "ies" : "y"); 118 if (brd_recv || req_recv) { 119 printf(" ("); 120 if (req_recv) 121 printf("%d request(s)", req_recv); 122 if (brd_recv) 123 printf("%s%d broadcast(s)", req_recv ? ", " : "", brd_recv); 124 putchar(')'); 125 } 126 putchar('\n'); 127 fflush(stdout); 128 } 129 if (cfg&dad) 97 received, (received == 1) ? "ies" : "y", 98 req_recv, brd_recv); 99 } 100 if (option_mask32 & DAD) 130 101 exit(!!received); 131 if ( cfg&unsolicited)102 if (option_mask32 & UNSOLICITED) 132 103 exit(0); 133 104 exit(!received); … … 136 107 static void catcher(void) 137 108 { 138 struct timeval tv; 139 static struct timeval start; 140 141 gettimeofday(&tv, NULL); 142 143 if (start.tv_sec == 0) 144 start = tv; 145 146 if (count-- == 0 147 || (timeout && MS_TDIFF(tv, start) > timeout * 1000 + 500)) 109 static unsigned start; 110 111 unsigned now; 112 113 now = MONOTONIC_US(); 114 if (start == 0) 115 start = now; 116 117 if (count == 0 || (timeout_us && (now - start) > (timeout_us + 500000))) 148 118 finish(); 149 119 150 if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) { 151 send_pack(s, &src, &dst, &me, &he); 152 if (count == 0 && cfg&unsolicited) 120 count--; 121 122 if (last == 0 || (now - last) > 500000) { 123 send_pack(&src, &dst, &me, &he); 124 if (count == 0 && (option_mask32 & UNSOLICITED)) 153 125 finish(); 154 126 } … … 163 135 164 136 /* Filter out wild packets */ 165 if (FROM->sll_pkttype != PACKET_HOST &&166 FROM->sll_pkttype != PACKET_BROADCAST &&167 137 if (FROM->sll_pkttype != PACKET_HOST 138 && FROM->sll_pkttype != PACKET_BROADCAST 139 && FROM->sll_pkttype != PACKET_MULTICAST) 168 140 return 0; 169 141 … … 173 145 174 146 /* ARPHRD check and this darned FDDI hack here :-( */ 175 if (ah->ar_hrd != htons(FROM->sll_hatype) && 176 (FROM->sll_hatype != ARPHRD_FDDI 177 || ah->ar_hrd != htons(ARPHRD_ETHER))) 147 if (ah->ar_hrd != htons(FROM->sll_hatype) 148 && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER))) 178 149 return 0; 179 150 … … 189 160 memcpy(&src_ip, p + ah->ar_hln, 4); 190 161 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); 191 if (!( cfg&dad)) {162 if (!(option_mask32 & DAD)) { 192 163 if (src_ip.s_addr != dst.s_addr) 193 164 return 0; … … 217 188 return 0; 218 189 } 219 if (!( cfg&quiet)) {190 if (!(option_mask32 & QUIET)) { 220 191 int s_printed = 0; 221 struct timeval tv; 222 223 gettimeofday(&tv, NULL); 224 225 printf("%s %s from %s [%s]", 226 FROM->sll_pkttype == PACKET_HOST ? "Unicast" : "Broadcast", 227 ah->ar_op == htons(ARPOP_REPLY) ? "reply" : "request", 192 193 printf("%scast re%s from %s [%s]", 194 FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad", 195 ah->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest", 228 196 inet_ntoa(src_ip), 229 197 ether_ntoa((struct ether_addr *) p)); … … 236 204 printf("for "); 237 205 printf("[%s]", 238 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); 239 } 240 241 if (last.tv_sec) { 242 long usecs = (tv.tv_sec - last.tv_sec) * 1000000 + 243 tv.tv_usec - last.tv_usec; 244 long msecs = (usecs + 500) / 1000; 245 246 usecs -= msecs * 1000 - 500; 247 printf(" %ld.%03ldms\n", msecs, usecs); 206 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); 207 } 208 209 if (last) { 210 printf(" %u.%03ums\n", last / 1000, last % 1000); 248 211 } else { 249 212 printf(" UNSOLICITED?\n"); … … 256 219 if (ah->ar_op == htons(ARPOP_REQUEST)) 257 220 req_recv++; 258 if ( cfg&quit_on_reply)221 if (option_mask32 & QUIT_ON_REPLY) 259 222 finish(); 260 if (!( cfg&broadcast_only)) {223 if (!(option_mask32 & BCAST_ONLY)) { 261 224 memcpy(he.sll_addr, p, me.sll_halen); 262 cfg |= unicasting;225 option_mask32 |= UNICASTING; 263 226 } 264 227 return 1; 265 228 } 266 229 230 int arping_main(int argc, char **argv); 267 231 int arping_main(int argc, char **argv) 268 232 { 269 c har *device = "eth0";233 const char *device = "eth0"; 270 234 int ifindex; 271 235 char *source = NULL; 272 236 char *target; 273 274 s = socket(PF_PACKET, SOCK_DGRAM, 0); 275 ifindex = errno;237 unsigned char *packet; 238 239 sock = xsocket(PF_PACKET, SOCK_DGRAM, 0); 276 240 277 241 // Drop suid root privileges … … 279 243 280 244 { 281 unsigned longopt;282 char * _count, *_timeout, *_device;245 unsigned opt; 246 char *str_count, *str_timeout; 283 247 284 248 /* Dad also sets quit_on_reply. 285 249 * Advert also sets unsolicited. 286 250 */ 287 bb_opt_complementally = "Df:AU"; 288 opt = bb_getopt_ulflags(argc, argv, "DUAqfbc:w:i:s:", 289 &_count, &_timeout, &_device); 290 cfg |= opt & 63; /* set respective flags */ 291 if (opt & 64) /* count */ 292 count = atoi(_count); 293 if (opt & 128) /* timeout */ 294 timeout = atoi(_timeout); 295 if (opt & 256) { /* interface */ 296 if (strlen(_device) > IF_NAMESIZE) { 297 bb_error_msg_and_die("Interface name `%s' must be less than %d", 298 _device, IF_NAMESIZE); 299 } 300 device = _device; 301 } 302 if (opt & 512) /* source */ 303 source = optarg; 304 } 305 argc -= optind; 306 argv += optind; 307 308 if (argc != 1) 309 bb_show_usage(); 310 311 target = *argv; 312 313 314 if (s < 0) { 315 bb_default_error_retval = ifindex; 316 bb_perror_msg_and_die("socket"); 317 } 318 bb_default_error_retval = 2; 251 opt_complementary = "=1:Df:AU"; 252 opt = getopt32(argv, "DUAqfbc:w:I:s:", 253 &str_count, &str_timeout, &device, &source); 254 if (opt & 0x40) /* -c: count */ 255 count = xatou(str_count); 256 if (opt & 0x80) /* -w: timeout */ 257 timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000; 258 //if (opt & 0x100) /* -I: interface */ 259 if (strlen(device) >= IF_NAMESIZE) { 260 bb_error_msg_and_die("interface name '%s' is too long", 261 device); 262 } 263 //if (opt & 0x200) /* -s: source */ 264 option_mask32 &= 0x3f; /* set respective flags */ 265 } 266 267 target = argv[optind]; 268 269 xfunc_error_retval = 2; 319 270 320 271 { … … 323 274 memset(&ifr, 0, sizeof(ifr)); 324 275 strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); 325 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 326 bb_error_msg_and_die("Interface %s not found", device); 327 } 276 ioctl_or_perror_and_die(sock, SIOCGIFINDEX, &ifr, "interface %s not found", device); 328 277 ifindex = ifr.ifr_ifindex; 329 278 330 if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) { 331 bb_error_msg_and_die("SIOCGIFFLAGS"); 332 } 279 xioctl(sock, SIOCGIFFLAGS, (char *) &ifr); 280 333 281 if (!(ifr.ifr_flags & IFF_UP)) { 334 bb_error_msg_and_die(" Interface %s is down", device);282 bb_error_msg_and_die("interface %s is down", device); 335 283 } 336 284 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { 337 bb_error_msg(" Interface %s is not ARPable", device);338 exit(cfg&dad? 0 : 2);285 bb_error_msg("interface %s is not ARPable", device); 286 return (option_mask32 & DAD ? 0 : 2); 339 287 } 340 288 } 341 289 342 290 if (!inet_aton(target, &dst)) { 343 struct hostent *hp; 344 345 hp = gethostbyname2(target, AF_INET); 346 if (!hp) { 347 bb_error_msg_and_die("invalid or unknown target %s", target); 348 } 349 memcpy(&dst, hp->h_addr, 4); 291 len_and_sockaddr *lsa; 292 lsa = xhost_and_af2sockaddr(target, 0, AF_INET); 293 memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4); 294 if (ENABLE_FEATURE_CLEAN_UP) 295 free(lsa); 350 296 } 351 297 … … 354 300 } 355 301 356 if (!( cfg&dad) && cfg&unsolicited&& src.s_addr == 0)302 if (!(option_mask32 & DAD) && (option_mask32 & UNSOLICITED) && src.s_addr == 0) 357 303 src = dst; 358 304 359 if (!( cfg&dad) || src.s_addr) {305 if (!(option_mask32 & DAD) || src.s_addr) { 360 306 struct sockaddr_in saddr; 361 int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); /* maybe use bb_xsocket? */ 362 363 if (probe_fd < 0) { 364 bb_error_msg_and_die("socket"); 365 } 307 int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); 308 366 309 if (device) { 367 if (setsockopt 368 (probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, 369 strlen(device) + 1) == -1) 370 bb_error_msg("WARNING: interface %s is ignored", device); 310 if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1) 311 bb_error_msg("warning: interface %s is ignored", device); 371 312 } 372 313 memset(&saddr, 0, sizeof(saddr)); … … 374 315 if (src.s_addr) { 375 316 saddr.sin_addr = src; 376 if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { 377 bb_error_msg_and_die("bind"); 378 } 379 } else if (!(cfg&dad)) { 380 int on = 1; 317 xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); 318 } else if (!(option_mask32 & DAD)) { 381 319 socklen_t alen = sizeof(saddr); 382 320 … … 384 322 saddr.sin_addr = dst; 385 323 386 if (setsockopt 387 (probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *) &on, 388 sizeof(on)) == -1) 389 bb_perror_msg("WARNING: setsockopt(SO_DONTROUTE)"); 390 if (connect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) 391 == -1) { 392 bb_error_msg_and_die("connect"); 393 } 394 if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == 395 -1) { 324 if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) 325 bb_perror_msg("warning: setsockopt(SO_DONTROUTE)"); 326 xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); 327 if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { 396 328 bb_error_msg_and_die("getsockname"); 397 329 } … … 399 331 } 400 332 close(probe_fd); 401 } ;333 } 402 334 403 335 me.sll_family = AF_PACKET; 404 336 me.sll_ifindex = ifindex; 405 337 me.sll_protocol = htons(ETH_P_ARP); 406 if (bind(s, (struct sockaddr *) &me, sizeof(me)) == -1) { 407 bb_error_msg_and_die("bind"); 408 } 338 xbind(sock, (struct sockaddr *) &me, sizeof(me)); 409 339 410 340 { 411 341 socklen_t alen = sizeof(me); 412 342 413 if (getsockname(s , (struct sockaddr *) &me, &alen) == -1) {343 if (getsockname(sock, (struct sockaddr *) &me, &alen) == -1) { 414 344 bb_error_msg_and_die("getsockname"); 415 345 } 416 346 } 417 347 if (me.sll_halen == 0) { 418 bb_error_msg(" Interface \"%s\" is not ARPable (no ll address)", device);419 exit(cfg&dad? 0 : 2);348 bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); 349 return (option_mask32 & DAD ? 0 : 2); 420 350 } 421 351 he = me; 422 352 memset(he.sll_addr, -1, he.sll_halen); 423 353 424 if (!( cfg&quiet)) {354 if (!(option_mask32 & QUIET)) { 425 355 printf("ARPING to %s from %s via %s\n", 426 356 inet_ntoa(dst), inet_ntoa(src), … … 428 358 } 429 359 430 if (!src.s_addr && !( cfg&dad)) {360 if (!src.s_addr && !(option_mask32 & DAD)) { 431 361 bb_error_msg_and_die("no src address in the non-DAD mode"); 432 362 } … … 447 377 catcher(); 448 378 379 packet = xmalloc(4096); 449 380 while (1) { 450 381 sigset_t sset, osset; 451 RESERVE_CONFIG_UBUFFER(packet, 4096);452 382 struct sockaddr_ll from; 453 383 socklen_t alen = sizeof(from); 454 384 int cc; 455 385 456 if ((cc = recvfrom(s, packet, 4096, 0,457 (struct sockaddr *) &from, &alen))< 0) {458 perror("recvfrom");386 cc = recvfrom(sock, packet, 4096, 0, (struct sockaddr *) &from, &alen); 387 if (cc < 0) { 388 bb_perror_msg("recvfrom"); 459 389 continue; 460 390 } … … 465 395 recv_pack(packet, cc, &from); 466 396 sigprocmask(SIG_SETMASK, &osset, NULL); 467 RELEASE_CONFIG_BUFFER(packet); 468 } 469 } 397 } 398 }
Note:
See TracChangeset
for help on using the changeset viewer.