int main(int argc, char **argv) { int fd; int on; struct sockaddr_in6 sin; int ttl; char *p; struct addrinfo hints, *ai, *ai0; int ch; int gai; char pbuf[NI_MAXSERV]; while ((ch = getopt(argc, argv, "nbh?l:")) != EOF) { switch(ch) { case 'n': no_resolve = 1; break; case 'b': show_both = 1; break; case 'l': if ((mtu = atoi(optarg)) <= overhead) { fprintf(stderr, "Error: length must be >= %d\n", overhead); exit(1); } break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); memset(&sin, 0, sizeof(sin)); p = strchr(argv[0], '/'); if (p) { *p = 0; sprintf(pbuf, "%u", (unsigned)atoi(p+1)); } else { sprintf(pbuf, "%u", (0x8000 | getpid()) & 0xffff); } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; hints.ai_flags = no_resolve ? AI_NUMERICHOST : 0; gai = getaddrinfo(argv[0], pbuf, &hints, &ai0); if (gai) { herror("getaddrinfo"); /*XXX*/ exit(1); } fd = -1; for (ai = ai0; ai; ai = ai->ai_next) { fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd < 0) continue; if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) { close(fd); fd = -1; continue; } memcpy(&sin, ai->ai_addr, sizeof(sin)); break; } if (fd < 0) { perror("socket/connect"); exit(1); } freeaddrinfo(ai0); if (!sin.sin6_addr.s6_addr32[0] && !sin.sin6_addr.s6_addr32[1] && sin.sin6_addr.s6_addr32[2] == htonl(0xFFFF)) { mtu = 65535; overhead = 28; mapped = 1; } on = IPV6_PMTUDISC_PROBE; if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)) && (on = IPV6_PMTUDISC_DO, setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)))) { perror("IPV6_MTU_DISCOVER"); exit(1); } if (mapped && setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on))) { perror("IP_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IPV6, IPV6_RECVERR, &on, sizeof(on))) { perror("IPV6_RECVERR"); exit(1); } if (mapped && setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) { perror("IP_RECVERR"); exit(1); } if ( #ifdef IPV6_RECVHOPLIMIT setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)) && setsockopt(fd, SOL_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on)) #else setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)) #endif ) { perror("IPV6_HOPLIMIT"); exit(1); } if (mapped && setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) { perror("IP_RECVTTL"); exit(1); } for (ttl=1; ttl<32; ttl++) { int res; int i; on = ttl; if (setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &on, sizeof(on))) { perror("IPV6_UNICAST_HOPS"); exit(1); } if (mapped && setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) { perror("IP_TTL"); exit(1); } restart: for (i=0; i<3; i++) { int old_mtu; old_mtu = mtu; res = probe_ttl(fd, ttl); if (mtu != old_mtu) goto restart; if (res == 0) goto done; if (res > 0) break; } if (res < 0) printf("%2d: no reply\n", ttl); } printf(" Too many hops: pmtu %d\n", mtu); done: printf(" Resume: pmtu %d ", mtu); if (hops_to>=0) printf("hops %d ", hops_to); if (hops_from>=0) printf("back %d ", hops_from); printf("\n"); exit(0); }
int main(int argc, char **argv) { struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_RAW, #ifdef USE_IDN .ai_flags = AI_IDN | AI_CANONIDN, #endif }; struct addrinfo *ai; int status; int fd; int on; int ttl; char *p; int ch; while ((ch = getopt(argc, argv, "nbh?l:m:p:")) != EOF) { switch(ch) { case 'n': no_resolve = 1; break; case 'b': show_both = 1; break; case 'l': if ((mtu = atoi(optarg)) <= overhead) { fprintf(stderr, "Error: pktlen must be > %d and <= %d.\n", overhead, INT_MAX); exit(1); } break; case 'm': max_hops = atoi(optarg); if (max_hops < 0 || max_hops > MAX_HOPS_LIMIT) { fprintf(stderr, "Error: max hops must be 0 .. %d (inclusive).\n", MAX_HOPS_LIMIT); } break; case 'p': base_port = atoi(optarg); break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); exit(1); } target.sin_family = AF_INET; /* Backward compatiblity */ if (!base_port) { p = strchr(argv[0], '/'); if (p) { *p = 0; base_port = atoi(p+1); } else base_port = 44444; } status = getaddrinfo(argv[0], NULL, &hints, &ai); if (status) { fprintf(stderr, "tracepath: %s: %s\n", argv[0], gai_strerror(status)); exit(1); } memcpy(&target.sin_addr, &((struct sockaddr_in *) ai->ai_addr)->sin_addr, sizeof target.sin_addr); freeaddrinfo(ai); on = IP_PMTUDISC_PROBE; if (setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on)) && (on = IP_PMTUDISC_DO, setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on)))) { perror("IP_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) { perror("IP_RECVERR"); exit(1); } if (setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) { perror("IP_RECVTTL"); exit(1); } pktbuf = malloc(mtu); if (!pktbuf) { perror("malloc"); exit(1); } for (ttl = 1; ttl <= max_hops; ttl++) { int res; int i; on = ttl; if (setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) { perror("IP_TTL"); exit(1); } restart: for (i=0; i<3; i++) { int old_mtu; old_mtu = mtu; res = probe_ttl(fd, ttl); if (mtu != old_mtu) goto restart; if (res == 0) goto done; if (res > 0) break; } if (res < 0) printf("%2d: no reply\n", ttl); } printf(" Too many hops: pmtu %d\n", mtu); done: printf(" Resume: pmtu %d ", mtu); if (hops_to>=0) printf("hops %d ", hops_to); if (hops_from>=0) printf("back %d ", hops_from); printf("\n"); exit(0); }
int main(int argc, char **argv) { struct hostent *he; int fd; int on; int ttl; char *p; if (argc < 2) { fprintf(stderr, "tracepath [-n] <destination>[/<port>]\n"); exit(-1); } ipfile_loaded = !ipfile_init(); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); exit(1); } target.sin_family = AF_INET; if (!strcmp(argv[1], "-n")) { no_resolve = 1; argv++; argc--; } p = strchr(argv[1], '/'); if (p) { *p = 0; base_port = atoi(p+1); } else base_port = 44444; he = gethostbyname(argv[1]); if (he == NULL) { herror("gethostbyname"); exit(1); } memcpy(&target.sin_addr, he->h_addr, 4); on = IP_PMTUDISC_DO; if (setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on))) { perror("IP_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) { perror("IP_RECVERR"); exit(1); } if (setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) { perror("IP_RECVTTL"); exit(1); } for (ttl=1; ttl<32; ttl++) { int res; int i; on = ttl; if (setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) { perror("IP_TTL"); exit(1); } for (i=0; i<3; i++) { res = probe_ttl(fd, ttl); if (res == 0) goto done; if (res > 0) break; } if (res < 0) printf("%2d: no reply\n", ttl); } printf(" Too many hops: pmtu %d\n", mtu); done: printf(" Resume: pmtu %d ", mtu); if (hops_to>=0) printf("hops %d ", hops_to); if (hops_from>=0) printf("back %d ", hops_from); printf("\n"); if (ipfile_loaded) ipfile_cleanup(); exit(0); }
int main(int argc, char **argv) { int fd; int on; int ttl; char *p; struct addrinfo hints = { .ai_family = family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, #ifdef USE_IDN .ai_flags = AI_IDN | AI_CANONNAME, #endif }; struct addrinfo *ai, *result; int ch; int status; char pbuf[NI_MAXSERV]; #ifdef USE_IDN setlocale(LC_ALL, ""); #endif while ((ch = getopt(argc, argv, "nbh?l:m:p:")) != EOF) { switch(ch) { case 'n': no_resolve = 1; break; case 'b': show_both = 1; break; case 'l': mtu = atoi(optarg); break; case 'm': max_hops = atoi(optarg); if (max_hops < 0 || max_hops > MAX_HOPS_LIMIT) { fprintf(stderr, "Error: max hops must be 0 .. %d (inclusive).\n", MAX_HOPS_LIMIT); } break; case 'p': base_port = atoi(optarg); break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); /* Backward compatiblity */ if (!base_port) { p = strchr(argv[0], '/'); if (p) { *p = 0; base_port = (unsigned)atoi(p+1); } else { base_port = 44444; } } sprintf(pbuf, "%u", base_port); status = getaddrinfo(argv[0], pbuf, &hints, &result); if (status) { fprintf(stderr, "tracepath6: %s: %s\n", argv[0], gai_strerror(status)); exit(1); } fd = -1; for (ai = result; ai; ai = ai->ai_next) { /* sanity check */ if (family && ai->ai_family != family) continue; if (ai->ai_family != AF_INET6 && ai->ai_family != AF_INET) continue; family = ai->ai_family; fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd < 0) continue; memcpy(&target, ai->ai_addr, sizeof(target)); targetlen = ai->ai_addrlen; break; } if (fd < 0) { perror("socket/connect"); exit(1); } freeaddrinfo(result); switch (family) { case AF_INET6: overhead = 48; if (!mtu) mtu = 128000; if (mtu <= overhead) goto pktlen_error; on = IPV6_PMTUDISC_DO; if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)) && (on = IPV6_PMTUDISC_DO, setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)))) { perror("IPV6_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IPV6, IPV6_RECVERR, &on, sizeof(on))) { perror("IPV6_RECVERR"); exit(1); } if ( #ifdef IPV6_RECVHOPLIMIT setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)) && setsockopt(fd, SOL_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on)) #else setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)) #endif ) { perror("IPV6_HOPLIMIT"); exit(1); } if (!IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *)&target)->sin6_addr))) break; mapped = 1; /*FALLTHROUGH*/ case AF_INET: overhead = 28; if (!mtu) mtu = 65535; if (mtu <= overhead) goto pktlen_error; on = IP_PMTUDISC_DO; if (setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on))) { perror("IP_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) { perror("IP_RECVERR"); exit(1); } if (setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) { perror("IP_RECVTTL"); exit(1); } } pktbuf = malloc(mtu); if (!pktbuf) { perror("malloc"); exit(1); } for (ttl = 1; ttl <= max_hops; ttl++) { int res; int i; on = ttl; switch (family) { case AF_INET6: if (setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &on, sizeof(on))) { perror("IPV6_UNICAST_HOPS"); exit(1); } if (!mapped) break; /*FALLTHROUGH*/ case AF_INET: if (setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) { perror("IP_TTL"); exit(1); } } restart: for (i=0; i<3; i++) { int old_mtu; old_mtu = mtu; res = probe_ttl(fd, ttl); if (mtu != old_mtu) goto restart; if (res == 0) goto done; if (res > 0) break; } if (res < 0) printf("%2d: no reply\n", ttl); } printf(" Too many hops: pmtu %d\n", mtu); done: printf(" Resume: pmtu %d ", mtu); if (hops_to>=0) printf("hops %d ", hops_to); if (hops_from>=0) printf("back %d ", hops_from); printf("\n"); exit(0); pktlen_error: fprintf(stderr, "Error: pktlen must be > %d and <= %d\n", overhead, INT_MAX); exit(1); }
int main(int argc, char **argv) { struct hostent *he; int fd; int on; int ttl; char *p; int ch; while ((ch = getopt(argc, argv, "nh?")) != EOF) { switch(ch) { case 'n': no_resolve = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); exit(1); } target.sin_family = AF_INET; p = strchr(argv[0], '/'); if (p) { *p = 0; base_port = atoi(p+1); } else base_port = 44444; he = gethostbyname(argv[0]); if (he == NULL) { herror("gethostbyname"); exit(1); } memcpy(&target.sin_addr, he->h_addr, 4); on = IP_PMTUDISC_DO; if (setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on))) { perror("IP_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) { perror("IP_RECVERR"); exit(1); } if (setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) { perror("IP_RECVTTL"); exit(1); } for (ttl=1; ttl<32; ttl++) { int res; int i; on = ttl; if (setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) { perror("IP_TTL"); exit(1); } for (i=0; i<3; i++) { res = probe_ttl(fd, ttl); if (res == 0) goto done; if (res > 0) break; } if (res < 0) printf("%2d: no reply\n", ttl); } printf(" Too many hops: pmtu %d\n", mtu); done: printf(" Resume: pmtu %d ", mtu); if (hops_to>=0) printf("hops %d ", hops_to); if (hops_from>=0) printf("back %d ", hops_from); printf("\n"); exit(0); }
int main(int argc, char **argv) { int fd; int on; int ttl; char *p; struct addrinfo hints, *ai, *ai0; int ch; int gai; char pbuf[NI_MAXSERV]; while ((ch = getopt(argc, argv, "nbh?l:")) != EOF) { switch(ch) { case 'n': no_resolve = 1; break; case 'b': show_both = 1; break; case 'l': if ((mtu = atoi(optarg)) <= overhead) { fprintf(stderr, "Error: length must be >= %d\n", overhead); exit(1); } break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); p = strchr(argv[0], '/'); if (p) { *p = 0; base_port = (unsigned)atoi(p+1); } else { base_port = 44444; } sprintf(pbuf, "%u", base_port); memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; hints.ai_flags = 0; gai = getaddrinfo(argv[0], pbuf, &hints, &ai0); if (gai) { herror("getaddrinfo"); exit(1); } fd = -1; for (ai = ai0; ai; ai = ai->ai_next) { /* sanity check */ if (family && ai->ai_family != family) continue; family = ai->ai_family; fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd < 0) continue; memcpy(&target, ai->ai_addr, sizeof(target)); targetlen = ai->ai_addrlen; break; } if (fd < 0) { perror("socket/connect"); exit(1); } freeaddrinfo(ai0); switch (family) { case AF_INET6: mtu = 128000; overhead = 48; on = IPV6_PMTUDISC_DO; if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)) && (on = IPV6_PMTUDISC_DO, setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)))) { perror("IPV6_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IPV6, IPV6_RECVERR, &on, sizeof(on))) { perror("IPV6_RECVERR"); exit(1); } if ( #ifdef IPV6_RECVHOPLIMIT setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)) && setsockopt(fd, SOL_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on)) #else setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)) #endif ) { perror("IPV6_HOPLIMIT"); exit(1); } if (!IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *)&target)->sin6_addr))) break; mapped = 1; /*FALLTHROUGH*/ case AF_INET: mtu = 65535; overhead = 28; on = IP_PMTUDISC_DO; if (setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on))) { perror("IP_MTU_DISCOVER"); exit(1); } on = 1; if (setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) { perror("IP_RECVERR"); exit(1); } if (setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) { perror("IP_RECVTTL"); exit(1); } } for (ttl=1; ttl<32; ttl++) { int res; int i; on = ttl; switch (family) { case AF_INET6: if (setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &on, sizeof(on))) { perror("IPV6_UNICAST_HOPS"); exit(1); } if (!mapped) break; /*FALLTHROUGH*/ case AF_INET: if (setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) { perror("IP_TTL"); exit(1); } } restart: for (i=0; i<3; i++) { int old_mtu; old_mtu = mtu; res = probe_ttl(fd, ttl); if (mtu != old_mtu) goto restart; if (res == 0) goto done; if (res > 0) break; } if (res < 0) printf("%2d: no reply\n", ttl); } printf(" Too many hops: pmtu %d\n", mtu); done: printf(" Resume: pmtu %d ", mtu); if (hops_to>=0) printf("hops %d ", hops_to); if (hops_from>=0) printf("back %d ", hops_from); printf("\n"); exit(0); }