123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634 |
- /* traceroute - trace the route to "host".
- *
- * Copyright 2012 Madhur Verma <mad.flexi@gmail.com>
- * Copyright 2013 Kyungwan Han <asura321@gmail.com>
- * Copyright 2013 Bilal Qureshi <bilal.jmi@gmail.com>
- * Copyright 2013 Ashwini Kumar <ak.ashwini1981@gmail.com>
- *
- * No Standard
- USE_TRACEROUTE(NEWTOY(traceroute, "<1>2i:f#<1>255=1z#<0>86400=0g*w#<0>86400=5t#<0>255=0s:q#<1>255=3p#<1>65535=33434m#<1>255=30rvndlIUF64", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
- USE_TRACEROUTE(OLDTOY(traceroute6,traceroute, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
- config TRACEROUTE
- bool "traceroute"
- default n
- help
- usage: traceroute [-46FUIldnvr] [-f 1ST_TTL] [-m MAXTTL] [-p PORT] [-q PROBES]
- [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-g GATEWAY] [-i IFACE] [-z PAUSE_MSEC] HOST [BYTES]
- traceroute6 [-dnrv] [-m MAXTTL] [-p PORT] [-q PROBES][-s SRC_IP] [-t TOS] [-w WAIT_SEC]
- [-i IFACE] HOST [BYTES]
- Trace the route to HOST
- -4,-6 Force IP or IPv6 name resolution
- -F Set the don't fragment bit (supports IPV4 only)
- -U Use UDP datagrams instead of ICMP ECHO (supports IPV4 only)
- -I Use ICMP ECHO instead of UDP datagrams (supports IPV4 only)
- -l Display the TTL value of the returned packet (supports IPV4 only)
- -d Set SO_DEBUG options to socket
- -n Print numeric addresses
- -v verbose
- -r Bypass routing tables, send directly to HOST
- -m Max time-to-live (max number of hops)(RANGE 1 to 255)
- -p Base UDP port number used in probes(default 33434)(RANGE 1 to 65535)
- -q Number of probes per TTL (default 3)(RANGE 1 to 255)
- -s IP address to use as the source address
- -t Type-of-service in probe packets (default 0)(RANGE 0 to 255)
- -w Time in seconds to wait for a response (default 3)(RANGE 0 to 86400)
- -g Loose source route gateway (8 max) (supports IPV4 only)
- -z Pause Time in ms (default 0)(RANGE 0 to 86400) (supports IPV4 only)
- -f Start from the 1ST_TTL hop (instead from 1)(RANGE 1 to 255) (supports IPV4 only)
- -i Specify a network interface to operate with
- */
- #define FOR_traceroute
- #include "toys.h"
- #include <netinet/udp.h>
- #include <netinet/ip_icmp.h>
- #include <netinet/ip6.h>
- #include <netinet/icmp6.h>
- GLOBALS(
- long max_ttl;
- long port;
- long ttl_probes;
- char *src_ip;
- long tos;
- long wait_time;
- struct arg_list *loose_source;
- long pause_time;
- long first_ttl;
- char *iface;
- uint32_t gw_list[9];
- int recv_sock;
- int snd_sock;
- unsigned msg_len;
- char *packet;
- uint32_t ident;
- int istraceroute6;
- )
- #ifndef SOL_IPV6
- # define SOL_IPV6 IPPROTO_IPV6
- #endif
- #define ICMP_HD_SIZE4 8
- #define USEC 1000000ULL
- struct payload_s {
- uint32_t seq;
- uint32_t ident;
- };
- char addr_str[INET6_ADDRSTRLEN];
- struct sockaddr_storage dest;
- //Compute checksum SUM of buffer P of length LEN
- static u_int16_t in_cksum(u_int16_t *p, u_int len)
- {
- u_int32_t sum = 0;
- int nwords = len >> 1;
- while (nwords-- != 0) sum += *p++;
- if (len & 1) {
- union {
- u_int16_t w;
- u_int8_t c[2];
- } u;
- u.c[0] = *(u_char *) p;
- u.c[1] = 0;
- sum += u.w;
- }
- // end-around-carry
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- return (~sum);
- }
- //sends a single probe packet with sequence(SEQ) and time-to-live(TTL)
- static void send_probe4(int seq, int ttl)
- {
- int res, len;
- void *out;
- struct payload_s *send_data4 = (struct payload_s *)(TT.packet);
- struct icmp *send_icmp4 = (struct icmp *)(TT.packet);
- if (toys.optflags & FLAG_U) {
- send_data4->seq = seq;
- send_data4->ident = TT.ident;
- ((struct sockaddr_in *)&dest)->sin_port = TT.port + seq;
- out = send_data4;
- } else {
- send_icmp4->icmp_type = ICMP_ECHO;
- send_icmp4->icmp_id = htons(TT.ident);
- send_icmp4->icmp_seq = htons(seq);
- send_icmp4->icmp_cksum = 0;
- send_icmp4->icmp_cksum = in_cksum((uint16_t *) send_icmp4, TT.msg_len);
- if (send_icmp4->icmp_cksum == 0) send_icmp4->icmp_cksum = 0xffff;
- out = send_icmp4;
- }
- res = setsockopt(TT.snd_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- if (res < 0) perror_exit("setsockopt ttl %d", ttl);
- len = TT.msg_len;
- res = sendto(TT.snd_sock, out, len, 0, (struct sockaddr *) &dest,
- sizeof(struct sockaddr_in));
- if (res != len) perror_exit(" sendto");
- }
- //sends a single probe packet with sequence(SEQ) and time-to-live(TTL)
- static void send_probe6(int seq, int ttl)
- {
- void *out;
- struct payload_s *send_data6 = (struct payload_s *) (TT.packet);
- send_data6->seq = seq;
- send_data6->ident = TT.ident;
- ((struct sockaddr_in6 *)&dest)->sin6_port = TT.port;
- if (setsockopt(TT.snd_sock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl,
- sizeof(ttl)) < 0) error_exit("setsockopt ttl %d", ttl);
- out = send_data6;
- if (sendto(TT.snd_sock, out, TT.msg_len, 0,
- (struct sockaddr *) &dest, sizeof(struct sockaddr_in6)) < 0)
- perror_exit("sendto");
- }
- static void set_flag_dr(int sock)
- {
- int set = 1;
- if ((toys.optflags & FLAG_d) && (setsockopt(sock,SOL_SOCKET, SO_DEBUG,
- &set, sizeof(set)) < 0)) perror_exit("SO_DEBUG failed ");
- if ((toys.optflags & FLAG_r) && (setsockopt(sock, SOL_SOCKET, SO_DONTROUTE,
- &set, sizeof(set)) < 0)) perror_exit("SO_DONTROUTE failed ");
- }
- static void bind_to_interface(int sock)
- {
- struct ifreq ifr;
- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", TT.iface);
- if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)))
- perror_msg("can't bind to interface %s", TT.iface);
- }
- static void resolve_addr(char *host, int family, int type, int proto, void *sock)
- {
- struct addrinfo *info, hint;
- int ret;
- memset(&hint, 0, sizeof(hint));
- hint.ai_family = family;
- hint.ai_socktype = type;
- hint.ai_protocol = proto;
- ret = getaddrinfo(host, NULL, &hint, &info);
- if (ret || !info) error_exit("bad address: %s ", host);
- memcpy(sock, info->ai_addr, info->ai_addrlen);
- freeaddrinfo(info);
- }
- static void do_trace()
- {
- int seq, fexit, ttl, tv = TT.wait_time * 1000;
- struct pollfd pfd[1];
- struct sockaddr_storage from;
- memset(&from, 0, sizeof(from));
- pfd[0].fd = TT.recv_sock;
- pfd[0].events = POLLIN;
- for (ttl = TT.first_ttl; ttl <= TT.max_ttl; ++ttl) {
- int probe, dest_reach = 0, print_verbose = 1;
- struct timeval t1, t2;
- struct sockaddr_storage last_addr;
- memset(&last_addr, 0, sizeof(last_addr));
- fexit = 0;
- xprintf("%2d", ttl);
- for (probe = 0, seq = 0; probe < TT.ttl_probes; ++probe) {
- int res = 0, tleft;
- fflush(NULL);
- if (!TT.istraceroute6)
- if (probe && (toys.optflags & FLAG_z)) msleep(TT.pause_time);
- if (!TT.istraceroute6) send_probe4(++seq, ttl);
- else send_probe6(++seq, ttl);
- gettimeofday(&t1, NULL);
- t2 = t1;
- while ((tleft = (int)(tv - ((unsigned long long)(t2.tv_sec * 1000ULL
- + t2.tv_usec/1000) - (unsigned long long)(t1.tv_sec * 1000ULL
- + t1.tv_usec/1000)))) >= 0) {
- unsigned delta = 0;
- if (!(res = poll(pfd, 1, tleft))) {
- xprintf(" *");
- break;
- }
- gettimeofday(&t2, NULL);
- if (res < 0) {
- if (errno != EINTR) perror_exit("poll");
- continue;
- }
- delta = (t2.tv_sec * USEC + t2.tv_usec)
- - (t1.tv_sec * USEC + t1.tv_usec);
- if (pfd[0].revents) {
- socklen_t addrlen = sizeof(struct sockaddr_storage);
- int rcv_len, icmp_res = 0;
- rcv_len = recvfrom(TT.recv_sock, toybuf, sizeof(toybuf),
- MSG_DONTWAIT, (struct sockaddr *) &from, &addrlen);
- if (rcv_len <= 0) continue;
- if (!TT.istraceroute6) {
- int pmtu = 0;
- struct ip *rcv_pkt = (struct ip*) toybuf;
- struct icmp *ricmp;
- ricmp = (struct icmp *) ((char*)rcv_pkt + (rcv_pkt->ip_hl << 2));
- if (ricmp->icmp_code == ICMP_UNREACH_NEEDFRAG)
- pmtu = ntohs(ricmp->icmp_nextmtu);
- if ((ricmp->icmp_type == ICMP_TIMXCEED
- && ricmp->icmp_code == ICMP_TIMXCEED_INTRANS)
- || ricmp->icmp_type == ICMP_UNREACH
- || ricmp->icmp_type == ICMP_ECHOREPLY) {
- struct udphdr *hudp;
- struct icmp *hicmp;
- struct ip *hip = &ricmp->icmp_ip;
- if (toys.optflags & FLAG_U) {
- hudp = (struct udphdr*) ((char*)hip + (hip->ip_hl << 2));
- if ((hip->ip_hl << 2) + 12 <=(rcv_len - (rcv_pkt->ip_hl << 2))
- && hip->ip_p == IPPROTO_UDP
- && hudp->dest == (TT.port + seq))
- icmp_res = (ricmp->icmp_type == ICMP_TIMXCEED ? -1 :
- ricmp->icmp_code);
- } else {
- hicmp = (struct icmp *) ((char*)hip + (hip->ip_hl << 2));
- if (ricmp->icmp_type == ICMP_ECHOREPLY
- && ricmp->icmp_id == ntohs(TT.ident)
- && ricmp->icmp_seq == ntohs(seq))
- icmp_res = ICMP_UNREACH_PORT;
- else if ((hip->ip_hl << 2) + ICMP_HD_SIZE4
- <= (rcv_len - (rcv_pkt->ip_hl << 2))
- && hip->ip_p == IPPROTO_ICMP
- && hicmp->icmp_id == htons(TT.ident)
- && hicmp->icmp_seq == htons(seq))
- icmp_res = (ricmp->icmp_type == ICMP_TIMXCEED ? -1 :
- ricmp->icmp_code);
- }
- }
- if (!icmp_res) continue;
- if (addrlen > 0) {
- if (memcmp(&((struct sockaddr_in *)&last_addr)->sin_addr,
- &((struct sockaddr_in *)&from)->sin_addr,
- sizeof(struct in_addr))) {
- if (!(toys.optflags & FLAG_n)) {
- char host[NI_MAXHOST];
- if (!getnameinfo((struct sockaddr *) &from,
- sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, 0))
- xprintf(" %s (", host);
- else xprintf(" %s (", inet_ntoa(
- ((struct sockaddr_in *)&from)->sin_addr));
- }
- xprintf(" %s", inet_ntoa(
- ((struct sockaddr_in *)&from)->sin_addr));
- if (!(toys.optflags & FLAG_n)) xprintf(")");
- memcpy(&last_addr, &from, sizeof(from));
- }
- xprintf(" %u.%03u ms", delta / 1000, delta % 1000);
- if (toys.optflags & FLAG_l) xprintf(" (%d)", rcv_pkt->ip_ttl);
- if (toys.optflags & FLAG_v) {
- xprintf(" %d bytes from %s : icmp type %d code %d\t",
- rcv_len, inet_ntoa(((struct sockaddr_in *)&from)->sin_addr),
- ricmp->icmp_type, ricmp->icmp_code);
- }
- } else xprintf("\t!H");
- switch (icmp_res) {
- case ICMP_UNREACH_PORT:
- if (rcv_pkt->ip_ttl <= 1) xprintf(" !");
- dest_reach = 1;
- break;
- case ICMP_UNREACH_NET:
- xprintf(" !N");
- ++fexit;
- break;
- case ICMP_UNREACH_HOST:
- xprintf(" !H");
- ++fexit;
- break;
- case ICMP_UNREACH_PROTOCOL:
- xprintf(" !P");
- dest_reach = 1;
- break;
- case ICMP_UNREACH_NEEDFRAG:
- xprintf(" !F-%d", pmtu);
- ++fexit;
- break;
- case ICMP_UNREACH_SRCFAIL:
- xprintf(" !S");
- ++fexit;
- break;
- case ICMP_UNREACH_FILTER_PROHIB:
- case ICMP_UNREACH_NET_PROHIB:
- xprintf(" !A");
- ++fexit;
- break;
- case ICMP_UNREACH_HOST_PROHIB:
- xprintf(" !C");
- ++fexit;
- break;
- case ICMP_UNREACH_HOST_PRECEDENCE:
- xprintf(" !V");
- ++fexit;
- break;
- case ICMP_UNREACH_PRECEDENCE_CUTOFF:
- xprintf(" !C");
- ++fexit;
- break;
- case ICMP_UNREACH_NET_UNKNOWN:
- case ICMP_UNREACH_HOST_UNKNOWN:
- xprintf(" !U");
- ++fexit;
- break;
- case ICMP_UNREACH_ISOLATED:
- xprintf(" !I");
- ++fexit;
- break;
- case ICMP_UNREACH_TOSNET:
- case ICMP_UNREACH_TOSHOST:
- xprintf(" !T");
- ++fexit;
- break;
- default:
- break;
- }
- break;
- } else {
- struct icmp6_hdr *ricmp = (struct icmp6_hdr *) toybuf;
- if ((ricmp->icmp6_type == ICMP6_TIME_EXCEEDED
- && ricmp->icmp6_code == ICMP6_TIME_EXCEED_TRANSIT)
- || ricmp->icmp6_type == ICMP6_DST_UNREACH
- || ricmp->icmp6_type == ICMP6_ECHO_REPLY) {
- struct ip6_hdr *hip;
- struct udphdr *hudp;
- int hdr_next;
- hip = (struct ip6_hdr *)(ricmp + 1);
- hudp = (struct udphdr*) (hip + 1);
- hdr_next = hip->ip6_nxt;
- if (hdr_next == IPPROTO_FRAGMENT) {
- hdr_next = *(unsigned char*)hudp;
- hudp++;
- }
- if (hdr_next == IPPROTO_UDP) {
- struct payload_s *pkt = (struct payload_s*)(hudp + 1);
- if ((pkt->ident == TT.ident) && (pkt->seq == seq))
- icmp_res = (ricmp->icmp6_type == ICMP6_TIME_EXCEEDED) ? -1 :
- ricmp->icmp6_code;
- }
- }
- if (!icmp_res) continue;
- if (addrlen > 0) {
- if (memcmp(&((struct sockaddr_in6 *)&last_addr)->sin6_addr,
- &((struct sockaddr_in6 *)&from)->sin6_addr,
- sizeof(struct in6_addr))) {
- if (!(toys.optflags & FLAG_n)) {
- char host[NI_MAXHOST];
- if (!getnameinfo((struct sockaddr *) &from,
- sizeof(from), host, sizeof(host), NULL, 0, 0))
- xprintf(" %s (", host);
- }
- memset(addr_str, '\0', INET6_ADDRSTRLEN);
- inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&from)->sin6_addr,
- addr_str, INET6_ADDRSTRLEN);
- xprintf(" %s", addr_str);
- if (!(toys.optflags & FLAG_n)) xprintf(")");
- memcpy(&last_addr,&from,sizeof(from));
- }
- if (toys.optflags & FLAG_v) {
- if(print_verbose){
- memset(addr_str, '\0', INET6_ADDRSTRLEN);
- inet_ntop(AF_INET6, &((struct sockaddr_in6 *)
- &from)->sin6_addr, addr_str, INET6_ADDRSTRLEN);
- rcv_len -= sizeof(struct ip6_hdr);
- xprintf(" %d bytes to %s ", rcv_len, addr_str);
- }
- }
- xprintf(" %u.%03u ms", delta / 1000, delta % 1000);
- delta = 0;
- } else xprintf("\t!H");
- switch (icmp_res) {
- case ICMP6_DST_UNREACH_NOPORT:
- ++fexit;
- dest_reach = 1;
- break;
- case ICMP6_DST_UNREACH_NOROUTE:
- xprintf(" !N");
- ++fexit;
- break;
- case ICMP6_DST_UNREACH_ADDR:
- xprintf(" !H");
- ++fexit;
- break;
- case ICMP6_DST_UNREACH_ADMIN:
- xprintf(" !S");
- ++fexit;
- break;
- default:
- break;
- }
- break;
- }
- } //revents
- }
- print_verbose = 0;
- }
- xputc('\n');
- if(!TT.istraceroute6) {
- if (!memcmp(&((struct sockaddr_in *)&from)->sin_addr,
- &((struct sockaddr_in *)&dest)->sin_addr, sizeof(struct in_addr))
- || dest_reach || (fexit && fexit >= TT.ttl_probes -1))
- break;
- } else if (dest_reach || (fexit > 0 && fexit >= TT.ttl_probes -1)) break;
- }
- }
- void traceroute_main(void)
- {
- unsigned pack_size = 0, tyser = 0;
- int lsrr = 0, set = 1;
-
- if(!(toys.optflags & FLAG_4) &&
- (inet_pton(AF_INET6, toys.optargs[0], &dest)))
- toys.optflags |= FLAG_6;
- memset(&dest, 0, sizeof(dest));
- if (toys.optflags & FLAG_6) TT.istraceroute6 = 1;
- else TT.istraceroute6 = toys.which->name[10] == '6';
- if(!TT.istraceroute6 && (toys.optflags & FLAG_g)) {
- struct arg_list *node;
- for (node = TT.loose_source; node; node = node->next, lsrr++) {
- struct sockaddr_in sin;
- memset( &sin, 0, sizeof(sin));
- if (lsrr >= 8) error_exit("no more than 8 gateways"); // NGATEWAYS
- resolve_addr(node->arg, AF_INET, SOCK_STREAM, 0, &sin);
- TT.gw_list[lsrr] = sin.sin_addr.s_addr;
- }
- } else TT.first_ttl = 1;
- TT.msg_len = pack_size = ICMP_HD_SIZE4; //udp payload is also 8bytes
- if (toys.optargs[1])
- TT.msg_len = atolx_range(toys.optargs[1], pack_size, 32768);//max packet size
- TT.recv_sock = xsocket((TT.istraceroute6 ? AF_INET6 : AF_INET), SOCK_RAW,
- (TT.istraceroute6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP));
- if (TT.istraceroute6) {
- int two = 2;
- #ifdef IPV6_RECVPKTINFO
- setsockopt(TT.recv_sock, SOL_IPV6, IPV6_RECVPKTINFO, &set,
- sizeof(set));
- setsockopt(TT.recv_sock, SOL_IPV6, IPV6_2292PKTINFO, &set,
- sizeof(set));
- #else
- setsockopt(TT.recv_sock, SOL_IPV6, IPV6_PKTINFO, &set, sizeof(set));
- #endif
- if (setsockopt(TT.recv_sock, SOL_RAW, IPV6_CHECKSUM, &two,
- sizeof(two)) < 0) perror_exit("setsockopt RAW_CHECKSUM");
- }
- set_flag_dr(TT.recv_sock);
- if (!TT.istraceroute6) {
- if (toys.optflags & FLAG_U)
- TT.snd_sock = xsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- else TT.snd_sock = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (toys.optflags & FLAG_i) bind_to_interface(TT.snd_sock);
- resolve_addr(toys.optargs[0], AF_INET, ((toys.optflags & FLAG_U) ?
- SOCK_DGRAM : SOCK_RAW), ((toys.optflags & FLAG_U) ? IPPROTO_UDP :
- IPPROTO_ICMP), &dest);
- if (lsrr > 0) {
- unsigned char optlist[MAX_IPOPTLEN];
- unsigned size;
- TT.gw_list[lsrr] = ((struct sockaddr_in *)&dest)->sin_addr.s_addr;
- ++lsrr;
- optlist[0] = IPOPT_NOP;
- optlist[1] = IPOPT_LSRR;// loose source route option
- size = lsrr * sizeof(TT.gw_list[0]);
- optlist[2] = size + 3;
- optlist[3] = IPOPT_MINOFF;
- memcpy(optlist + 4, TT.gw_list, size);
- if (setsockopt(TT.snd_sock, IPPROTO_IP, IP_OPTIONS,
- (char *)optlist, size + sizeof(TT.gw_list[0])) < 0)
- perror_exit("LSRR IP_OPTIONS");
- }
- } else TT.snd_sock = xsocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
- if (setsockopt(TT.snd_sock, SOL_SOCKET, SO_SNDBUF, &TT.msg_len,
- sizeof(TT.msg_len)) < 0) perror_exit("SO_SNDBUF failed ");
- if (!TT.istraceroute6) {
- if ((toys.optflags & FLAG_t) &&
- setsockopt(TT.snd_sock, IPPROTO_IP, IP_TOS, &tyser, sizeof(tyser)) < 0)
- perror_exit("IP_TOS %ld failed ", TT.tos);
- #ifdef IP_DONTFRAG
- if ((toys.optflags & FLAG_F) &&
- (setsockopt(TT.snd_sock, IPPROTO_IP, IP_DONTFRAG, &set,
- sizeof(set)) < 0)) perror_exit("IP_DONTFRAG failed ");
- #endif
- } else if (setsockopt(TT.snd_sock, IPPROTO_IPV6, IPV6_TCLASS, &TT.tos,
- sizeof(TT.tos)) < 0) perror_exit("IPV6_TCLASS %ld failed ", TT.tos);
- set_flag_dr(TT.snd_sock);
- TT.packet = xzalloc(TT.msg_len);
- TT.ident = getpid();
- if (!TT.istraceroute6) {
- if (!(toys.optflags & FLAG_U)) TT.ident |= 0x8000;
- if (toys.optflags & FLAG_s) {
- struct sockaddr_in source;
- memset(&source, 0, sizeof(source));
- if (!inet_aton(TT.src_ip, &(source.sin_addr)))
- error_exit("bad address: %s", TT.src_ip);
- if (setsockopt(TT.snd_sock, IPPROTO_IP, IP_MULTICAST_IF,
- (struct sockaddr*)&source, sizeof(struct sockaddr_in)))
- perror_exit("can't set multicast source interface");
- xbind(TT.snd_sock,(struct sockaddr*)&source, sizeof(struct sockaddr_in));
- }
- if(TT.first_ttl > TT.max_ttl)
- error_exit("ERROR :Range for -f is 1 to %ld (max ttl)", TT.max_ttl);
- xprintf("traceroute to %s(%s)", toys.optargs[0],
- inet_ntoa(((struct sockaddr_in *)&dest)->sin_addr));
- } else {
- if (toys.optflags & FLAG_i) bind_to_interface(TT.snd_sock);
- resolve_addr(toys.optargs[0], AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &dest);
- if (toys.optflags & FLAG_s) {
- struct sockaddr_in6 source;
- memset(&source, 0, sizeof(source));
- if(inet_pton(AF_INET6, TT.src_ip, &(source.sin6_addr)) <= 0)
- error_exit("bad address: %s", TT.src_ip);
- xbind(TT.snd_sock,(struct sockaddr*)&source, sizeof(struct sockaddr_in6));
- } else {
- struct sockaddr_in6 prb;
- socklen_t len = sizeof(prb);
- int p_fd = xsocket(AF_INET6, SOCK_DGRAM, 0);
- if (toys.optflags & FLAG_i) bind_to_interface(p_fd);
- ((struct sockaddr_in6 *)&dest)->sin6_port = htons(1025);
- xconnect(p_fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_in6));
- if(getsockname(p_fd, (struct sockaddr *)&prb, &len))
- error_exit("probe addr failed");
- close(p_fd);
- prb.sin6_port = 0;
- xbind(TT.snd_sock, (struct sockaddr*)&prb, sizeof(struct sockaddr_in6));
- xbind(TT.recv_sock, (struct sockaddr*)&prb, sizeof(struct sockaddr_in6));
- }
- inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&dest)->sin6_addr,
- addr_str, INET6_ADDRSTRLEN);
- xprintf("traceroute6 to %s(%s)", toys.optargs[0], addr_str);
- }
- if (toys.optflags & FLAG_s) xprintf(" from %s",TT.src_ip);
- xprintf(", %ld hops max, %u byte packets\n", TT.max_ttl, TT.msg_len);
- do_trace();
- }
|