diff options
Diffstat (limited to 'networking/traceroute.c')
-rw-r--r-- | networking/traceroute.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c index ce8dc8395..5d39ae3cf 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -371,6 +371,8 @@ struct globals { | |||
371 | static int | 371 | static int |
372 | ifaddrlist(struct IFADDRLIST **ipaddrp) | 372 | ifaddrlist(struct IFADDRLIST **ipaddrp) |
373 | { | 373 | { |
374 | enum { IFREQ_BUFSIZE = (32 * 1024) / sizeof(struct ifreq) }; | ||
375 | |||
374 | int fd, nipaddr; | 376 | int fd, nipaddr; |
375 | #ifdef HAVE_SOCKADDR_SA_LEN | 377 | #ifdef HAVE_SOCKADDR_SA_LEN |
376 | int n; | 378 | int n; |
@@ -379,22 +381,24 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) | |||
379 | struct sockaddr_in *addr_sin; | 381 | struct sockaddr_in *addr_sin; |
380 | struct IFADDRLIST *al; | 382 | struct IFADDRLIST *al; |
381 | struct ifconf ifc; | 383 | struct ifconf ifc; |
382 | struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr; | 384 | struct ifreq ifr; |
385 | /* Was on stack, but 32k is a bit too much: */ | ||
386 | struct ifreq *ibuf = xmalloc(IFREQ_BUFSIZE * sizeof(ibuf[0])); | ||
383 | struct IFADDRLIST *st_ifaddrlist; | 387 | struct IFADDRLIST *st_ifaddrlist; |
384 | 388 | ||
385 | fd = xsocket(AF_INET, SOCK_DGRAM, 0); | 389 | fd = xsocket(AF_INET, SOCK_DGRAM, 0); |
386 | 390 | ||
387 | ifc.ifc_len = sizeof(ibuf); | 391 | ifc.ifc_len = IFREQ_BUFSIZE * sizeof(ibuf[0]); |
388 | ifc.ifc_buf = (caddr_t)ibuf; | 392 | ifc.ifc_buf = (caddr_t)ibuf; |
389 | 393 | ||
390 | if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || | 394 | if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 |
391 | ifc.ifc_len < sizeof(struct ifreq)) { | 395 | || ifc.ifc_len < sizeof(struct ifreq) |
396 | ) { | ||
392 | if (errno == EINVAL) | 397 | if (errno == EINVAL) |
393 | bb_error_msg_and_die( | 398 | bb_error_msg_and_die( |
394 | "SIOCGIFCONF: ifreq struct too small (%d bytes)", | 399 | "SIOCGIFCONF: ifreq struct too small (%d bytes)", |
395 | (int)sizeof(ibuf)); | 400 | IFREQ_BUFSIZE * sizeof(ibuf[0])); |
396 | else | 401 | bb_perror_msg_and_die("SIOCGIFCONF"); |
397 | bb_perror_msg_and_die("SIOCGIFCONF"); | ||
398 | } | 402 | } |
399 | ifrp = ibuf; | 403 | ifrp = ibuf; |
400 | ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); | 404 | ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); |
@@ -449,9 +453,10 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) | |||
449 | ++nipaddr; | 453 | ++nipaddr; |
450 | } | 454 | } |
451 | if (nipaddr == 0) | 455 | if (nipaddr == 0) |
452 | bb_error_msg_and_die ("can't find any network interfaces"); | 456 | bb_error_msg_and_die("can't find any network interfaces"); |
453 | (void)close(fd); | ||
454 | 457 | ||
458 | free(ibuf); | ||
459 | close(fd); | ||
455 | *ipaddrp = st_ifaddrlist; | 460 | *ipaddrp = st_ifaddrlist; |
456 | return nipaddr; | 461 | return nipaddr; |
457 | } | 462 | } |
@@ -492,11 +497,13 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) | |||
492 | ++n; | 497 | ++n; |
493 | if (n == 1 && strncmp(buf, "Iface", 5) == 0) | 498 | if (n == 1 && strncmp(buf, "Iface", 5) == 0) |
494 | continue; | 499 | continue; |
495 | if ((i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x", | 500 | i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x", |
496 | tdevice, &dest, &tmask)) != 3) | 501 | tdevice, &dest, &tmask); |
497 | bb_error_msg_and_die ("junk in buffer"); | 502 | if (i != 3) |
498 | if ((to->sin_addr.s_addr & tmask) == dest && | 503 | bb_error_msg_and_die("junk in buffer"); |
499 | (tmask > mask || mask == 0)) { | 504 | if ((to->sin_addr.s_addr & tmask) == dest |
505 | && (tmask > mask || mask == 0) | ||
506 | ) { | ||
500 | mask = tmask; | 507 | mask = tmask; |
501 | strcpy(device, tdevice); | 508 | strcpy(device, tdevice); |
502 | } | 509 | } |
@@ -504,7 +511,7 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) | |||
504 | fclose(f); | 511 | fclose(f); |
505 | 512 | ||
506 | if (device[0] == '\0') | 513 | if (device[0] == '\0') |
507 | bb_error_msg_and_die ("can't find interface"); | 514 | bb_error_msg_and_die("can't find interface"); |
508 | 515 | ||
509 | /* Get the interface address list */ | 516 | /* Get the interface address list */ |
510 | n = ifaddrlist(&al); | 517 | n = ifaddrlist(&al); |
@@ -808,7 +815,7 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq) | |||
808 | "%s: icmp type %d (%s) code %d\n", | 815 | "%s: icmp type %d (%s) code %d\n", |
809 | cc, inet_ntoa(from->sin_addr), | 816 | cc, inet_ntoa(from->sin_addr), |
810 | inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); | 817 | inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); |
811 | for (i = 4; i < cc ; i += sizeof(*lp)) | 818 | for (i = 4; i < cc; i += sizeof(*lp)) |
812 | printf("%2d: x%8.8x\n", i, *lp++); | 819 | printf("%2d: x%8.8x\n", i, *lp++); |
813 | } | 820 | } |
814 | #endif | 821 | #endif |