Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/networking/arping.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/networking/arping.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * arping.c - Ping hosts by ARP requests/replies3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 * 5 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 6 * 7 * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 5 * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 8 6 * Busybox port: Nick Fedchik <nick@fedchik.org.ua> 9 7 */ … … 18 16 /* We don't expect to see 1000+ seconds delay, unsigned is enough */ 19 17 #define MONOTONIC_US() ((unsigned)monotonic_us()) 20 21 static struct in_addr src;22 static struct in_addr dst;23 static struct sockaddr_ll me;24 static struct sockaddr_ll he;25 static unsigned last;26 18 27 19 enum { … … 35 27 }; 36 28 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; 29 struct globals { 30 struct in_addr src; 31 struct in_addr dst; 32 struct sockaddr_ll me; 33 struct sockaddr_ll he; 34 int sock_fd; 35 36 int count; // = -1; 37 unsigned last; 38 unsigned timeout_us; 39 unsigned start; 40 41 unsigned sent; 42 unsigned brd_sent; 43 unsigned received; 44 unsigned brd_recv; 45 unsigned req_recv; 46 } FIX_ALIASING; 47 #define G (*(struct globals*)&bb_common_bufsiz1) 48 #define src (G.src ) 49 #define dst (G.dst ) 50 #define me (G.me ) 51 #define he (G.he ) 52 #define sock_fd (G.sock_fd ) 53 #define count (G.count ) 54 #define last (G.last ) 55 #define timeout_us (G.timeout_us) 56 #define start (G.start ) 57 #define sent (G.sent ) 58 #define brd_sent (G.brd_sent ) 59 #define received (G.received ) 60 #define brd_recv (G.brd_recv ) 61 #define req_recv (G.req_recv ) 62 #define INIT_G() do { \ 63 count = -1; \ 64 } while (0) 65 66 // If GNUisms are not available... 67 //static void *mempcpy(void *_dst, const void *_src, int n) 68 //{ 69 // memcpy(_dst, _src, n); 70 // return (char*)_dst + n; 71 //} 45 72 46 73 static int send_pack(struct in_addr *src_addr, … … 49 76 { 50 77 int err; 51 unsigned now;52 78 unsigned char buf[256]; 53 79 struct arphdr *ah = (struct arphdr *) buf; 54 80 unsigned char *p = (unsigned char *) (ah + 1); 55 81 56 ah->ar_hrd = htons(ME->sll_hatype);57 82 ah->ar_hrd = htons(ARPHRD_ETHER); 58 83 ah->ar_pro = htons(ETH_P_IP); … … 61 86 ah->ar_op = option_mask32 & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); 62 87 63 memcpy(p, &ME->sll_addr, ah->ar_hln); 64 p += ME->sll_halen; 65 66 memcpy(p, src_addr, 4); 67 p += 4; 88 p = mempcpy(p, &ME->sll_addr, ah->ar_hln); 89 p = mempcpy(p, src_addr, 4); 68 90 69 91 if (option_mask32 & ADVERT) 70 memcpy(p, &ME->sll_addr, ah->ar_hln);92 p = mempcpy(p, &ME->sll_addr, ah->ar_hln); 71 93 else 72 memcpy(p, &HE->sll_addr, ah->ar_hln); 73 p += ah->ar_hln; 74 75 memcpy(p, dst_addr, 4); 76 p += 4; 77 78 now = MONOTONIC_US(); 79 err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); 94 p = mempcpy(p, &HE->sll_addr, ah->ar_hln); 95 96 p = mempcpy(p, dst_addr, 4); 97 98 err = sendto(sock_fd, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); 80 99 if (err == p - buf) { 81 last = now;100 last = MONOTONIC_US(); 82 101 sent++; 83 102 if (!(option_mask32 & UNICASTING)) … … 87 106 } 88 107 89 static void finish(void) ATTRIBUTE_NORETURN;108 static void finish(void) NORETURN; 90 109 static void finish(void) 91 110 { … … 101 120 exit(!!received); 102 121 if (option_mask32 & UNSOLICITED) 103 exit( 0);122 exit(EXIT_SUCCESS); 104 123 exit(!received); 105 124 } … … 107 126 static void catcher(void) 108 127 { 109 static unsigned start;110 111 128 unsigned now; 112 129 … … 115 132 start = now; 116 133 117 if (count == 0 || (timeout_us && (now - start) > (timeout_us + 500000)))134 if (count == 0 || (timeout_us && (now - start) > timeout_us)) 118 135 finish(); 119 136 120 count--; 137 /* count < 0 means "infinite count" */ 138 if (count > 0) 139 count--; 121 140 122 141 if (last == 0 || (now - last) > 500000) { … … 128 147 } 129 148 130 static intrecv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)149 static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) 131 150 { 132 151 struct arphdr *ah = (struct arphdr *) buf; 133 152 unsigned char *p = (unsigned char *) (ah + 1); 134 153 struct in_addr src_ip, dst_ip; 154 /* moves below assume in_addr is 4 bytes big, ensure that */ 155 struct BUG_in_addr_must_be_4 { 156 char BUG_in_addr_must_be_4[ 157 sizeof(struct in_addr) == 4 ? 1 : -1 158 ]; 159 char BUG_s_addr_must_be_4[ 160 sizeof(src_ip.s_addr) == 4 ? 1 : -1 161 ]; 162 }; 135 163 136 164 /* Filter out wild packets */ … … 138 166 && FROM->sll_pkttype != PACKET_BROADCAST 139 167 && FROM->sll_pkttype != PACKET_MULTICAST) 140 return 0;141 142 /* Only these types are recogni sed */168 return false; 169 170 /* Only these types are recognized */ 143 171 if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY)) 144 return 0;172 return false; 145 173 146 174 /* ARPHRD check and this darned FDDI hack here :-( */ 147 175 if (ah->ar_hrd != htons(FROM->sll_hatype) 148 176 && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER))) 149 return 0;177 return false; 150 178 151 179 /* Protocol must be IP. */ 152 if (ah->ar_pro != htons(ETH_P_IP)) 153 return 0; 154 if (ah->ar_pln != 4) 155 return 0; 156 if (ah->ar_hln != me.sll_halen) 157 return 0; 158 if (len < sizeof(*ah) + 2 * (4 + ah->ar_hln)) 159 return 0; 160 memcpy(&src_ip, p + ah->ar_hln, 4); 161 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); 180 if (ah->ar_pro != htons(ETH_P_IP) 181 || (ah->ar_pln != 4) 182 || (ah->ar_hln != me.sll_halen) 183 || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln)))) 184 return false; 185 186 move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln); 187 move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln); 188 189 if (dst.s_addr != src_ip.s_addr) 190 return false; 162 191 if (!(option_mask32 & DAD)) { 163 if (src_ip.s_addr != dst.s_addr) 164 return 0; 165 if (src.s_addr != dst_ip.s_addr) 166 return 0; 167 if (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)) 168 return 0; 192 if ((src.s_addr != dst_ip.s_addr) 193 || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln))) 194 return false; 169 195 } else { 170 196 /* DAD packet was: … … 181 207 dst_ip/dst_hw do not matter. 182 208 */ 183 if (src_ip.s_addr != dst.s_addr) 184 return 0; 185 if (memcmp(p, &me.sll_addr, me.sll_halen) == 0) 186 return 0; 187 if (src.s_addr && src.s_addr != dst_ip.s_addr) 188 return 0; 209 if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0) 210 || (src.s_addr && src.s_addr != dst_ip.s_addr)) 211 return false; 189 212 } 190 213 if (!(option_mask32 & QUIET)) { … … 208 231 209 232 if (last) { 210 printf(" %u.%03ums\n", last / 1000, last % 1000); 233 unsigned diff = MONOTONIC_US() - last; 234 printf(" %u.%03ums\n", diff / 1000, diff % 1000); 211 235 } else { 212 236 printf(" UNSOLICITED?\n"); 213 237 } 214 fflush (stdout);238 fflush_all(); 215 239 } 216 240 received++; … … 225 249 option_mask32 |= UNICASTING; 226 250 } 227 return 1;251 return true; 228 252 } 229 253 230 int arping_main(int argc, char **argv) ;231 int arping_main(int argc , char **argv)254 int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 255 int arping_main(int argc UNUSED_PARAM, char **argv) 232 256 { 233 257 const char *device = "eth0"; 234 int ifindex;235 258 char *source = NULL; 236 259 char *target; 237 260 unsigned char *packet; 238 239 sock = xsocket(PF_PACKET, SOCK_DGRAM, 0); 261 char *err_str; 262 263 INIT_G(); 264 265 sock_fd = xsocket(AF_PACKET, SOCK_DGRAM, 0); 240 266 241 267 // Drop suid root privileges 242 xsetuid(getuid()); 243 268 // Need to remove SUID_NEVER from applets.h for this to work 269 //xsetuid(getuid()); 270 271 err_str = xasprintf("interface %s %%s", device); 244 272 { 245 273 unsigned opt; 246 char *str_ count, *str_timeout;274 char *str_timeout; 247 275 248 276 /* Dad also sets quit_on_reply. 249 277 * Advert also sets unsolicited. 250 278 */ 251 opt_complementary = "=1:Df:AU ";279 opt_complementary = "=1:Df:AU:c+"; 252 280 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); 281 &count, &str_timeout, &device, &source); 256 282 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 } 283 timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000; 263 284 //if (opt & 0x200) /* -s: source */ 264 285 option_mask32 &= 0x3f; /* set respective flags */ … … 273 294 274 295 memset(&ifr, 0, sizeof(ifr)); 275 strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); 276 ioctl_or_perror_and_die(sock, SIOCGIFINDEX, &ifr, "interface %s not found", device); 277 ifindex = ifr.ifr_ifindex; 278 279 xioctl(sock, SIOCGIFFLAGS, (char *) &ifr); 296 strncpy_IFNAMSIZ(ifr.ifr_name, device); 297 /* We use ifr.ifr_name in error msg so that problem 298 * with truncated name will be visible */ 299 ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found"); 300 me.sll_ifindex = ifr.ifr_ifindex; 301 302 xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr); 280 303 281 304 if (!(ifr.ifr_flags & IFF_UP)) { 282 bb_error_msg_and_die( "interface %s is down", device);305 bb_error_msg_and_die(err_str, "is down"); 283 306 } 284 307 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { 285 bb_error_msg( "interface %s is not ARPable", device);308 bb_error_msg(err_str, "is not ARPable"); 286 309 return (option_mask32 & DAD ? 0 : 2); 287 310 } 288 311 } 289 312 290 if (!inet_aton(target, &dst)){313 /* if (!inet_aton(target, &dst)) - not needed */ { 291 314 len_and_sockaddr *lsa; 292 315 lsa = xhost_and_af2sockaddr(target, 0, AF_INET); 293 memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4);316 dst = lsa->u.sin.sin_addr; 294 317 if (ENABLE_FEATURE_CLEAN_UP) 295 318 free(lsa); … … 300 323 } 301 324 302 if ( !(option_mask32 & DAD) && (option_mask32 & UNSOLICITED)&& src.s_addr == 0)325 if ((option_mask32 & (DAD|UNSOLICITED)) == UNSOLICITED && src.s_addr == 0) 303 326 src = dst; 304 327 … … 307 330 int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); 308 331 309 if (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); 312 } 332 setsockopt_bindtodevice(probe_fd, device); 313 333 memset(&saddr, 0, sizeof(saddr)); 314 334 saddr.sin_family = AF_INET; 315 335 if (src.s_addr) { 336 /* Check that this is indeed our IP */ 316 337 saddr.sin_addr = src; 317 338 xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); 318 } else if (!(option_mask32 & DAD)) { 339 } else { /* !(option_mask32 & DAD) case */ 340 /* Find IP address on this iface */ 319 341 socklen_t alen = sizeof(saddr); 320 342 … … 323 345 324 346 if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) 325 bb_perror_msg(" warning:setsockopt(SO_DONTROUTE)");347 bb_perror_msg("setsockopt(SO_DONTROUTE)"); 326 348 xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); 327 if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { 328 bb_error_msg_and_die("getsockname"); 329 } 349 getsockname(probe_fd, (struct sockaddr *) &saddr, &alen); 350 //never happens: 351 //if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) 352 // bb_perror_msg_and_die("getsockname"); 353 if (saddr.sin_family != AF_INET) 354 bb_error_msg_and_die("no IP address configured"); 330 355 src = saddr.sin_addr; 331 356 } … … 334 359 335 360 me.sll_family = AF_PACKET; 336 me.sll_ifindex = ifindex;361 //me.sll_ifindex = ifindex; - done before 337 362 me.sll_protocol = htons(ETH_P_ARP); 338 xbind(sock , (struct sockaddr *) &me, sizeof(me));363 xbind(sock_fd, (struct sockaddr *) &me, sizeof(me)); 339 364 340 365 { 341 366 socklen_t alen = sizeof(me); 342 343 if (getsockname(sock, (struct sockaddr *) &me, &alen) == -1) {344 bb_error_msg_and_die("getsockname");345 }367 getsockname(sock_fd, (struct sockaddr *) &me, &alen); 368 //never happens: 369 //if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) 370 // bb_perror_msg_and_die("getsockname"); 346 371 } 347 372 if (me.sll_halen == 0) { 348 bb_error_msg( "interface \"%s\" is not ARPable (no ll address)", device);373 bb_error_msg(err_str, "is not ARPable (no ll address)"); 349 374 return (option_mask32 & DAD ? 0 : 2); 350 375 } … … 353 378 354 379 if (!(option_mask32 & QUIET)) { 355 printf("ARPING to %s from %s via %s\n", 356 inet_ntoa(dst), inet_ntoa(src), 357 device ? device : "unknown"); 358 } 359 360 if (!src.s_addr && !(option_mask32 & DAD)) { 361 bb_error_msg_and_die("no src address in the non-DAD mode"); 362 } 363 364 { 365 struct sigaction sa; 366 367 memset(&sa, 0, sizeof(sa)); 368 sa.sa_flags = SA_RESTART; 369 370 sa.sa_handler = (void (*)(int)) finish; 371 sigaction(SIGINT, &sa, NULL); 372 373 sa.sa_handler = (void (*)(int)) catcher; 374 sigaction(SIGALRM, &sa, NULL); 375 } 380 /* inet_ntoa uses static storage, can't use in same printf */ 381 printf("ARPING to %s", inet_ntoa(dst)); 382 printf(" from %s via %s\n", inet_ntoa(src), device); 383 } 384 385 signal_SA_RESTART_empty_mask(SIGINT, (void (*)(int))finish); 386 signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher); 376 387 377 388 catcher(); … … 384 395 int cc; 385 396 386 cc = recvfrom(sock , packet, 4096, 0, (struct sockaddr *) &from, &alen);397 cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen); 387 398 if (cc < 0) { 388 399 bb_perror_msg("recvfrom");
Note:
See TracChangeset
for help on using the changeset viewer.