1*cf5a6c84SAndroid Build Coastguard Worker /* traceroute - trace the route to "host".
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Madhur Verma <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Bilal Qureshi <[email protected]>
6*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Ashwini Kumar <[email protected]>
7*cf5a6c84SAndroid Build Coastguard Worker *
8*cf5a6c84SAndroid Build Coastguard Worker * No Standard
9*cf5a6c84SAndroid Build Coastguard Worker
10*cf5a6c84SAndroid Build Coastguard Worker 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))
11*cf5a6c84SAndroid Build Coastguard Worker USE_TRACEROUTE(OLDTOY(traceroute6,traceroute, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
12*cf5a6c84SAndroid Build Coastguard Worker config TRACEROUTE
13*cf5a6c84SAndroid Build Coastguard Worker bool "traceroute"
14*cf5a6c84SAndroid Build Coastguard Worker default n
15*cf5a6c84SAndroid Build Coastguard Worker help
16*cf5a6c84SAndroid Build Coastguard Worker usage: traceroute [-46FUIldnvr] [-f 1ST_TTL] [-m MAXTTL] [-p PORT] [-q PROBES]
17*cf5a6c84SAndroid Build Coastguard Worker [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-g GATEWAY] [-i IFACE] [-z PAUSE_MSEC] HOST [BYTES]
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker traceroute6 [-dnrv] [-m MAXTTL] [-p PORT] [-q PROBES][-s SRC_IP] [-t TOS] [-w WAIT_SEC]
20*cf5a6c84SAndroid Build Coastguard Worker [-i IFACE] HOST [BYTES]
21*cf5a6c84SAndroid Build Coastguard Worker
22*cf5a6c84SAndroid Build Coastguard Worker Trace the route to HOST
23*cf5a6c84SAndroid Build Coastguard Worker
24*cf5a6c84SAndroid Build Coastguard Worker -4,-6 Force IP or IPv6 name resolution
25*cf5a6c84SAndroid Build Coastguard Worker -F Set the don't fragment bit (supports IPV4 only)
26*cf5a6c84SAndroid Build Coastguard Worker -U Use UDP datagrams instead of ICMP ECHO (supports IPV4 only)
27*cf5a6c84SAndroid Build Coastguard Worker -I Use ICMP ECHO instead of UDP datagrams (supports IPV4 only)
28*cf5a6c84SAndroid Build Coastguard Worker -l Display the TTL value of the returned packet (supports IPV4 only)
29*cf5a6c84SAndroid Build Coastguard Worker -d Set SO_DEBUG options to socket
30*cf5a6c84SAndroid Build Coastguard Worker -n Print numeric addresses
31*cf5a6c84SAndroid Build Coastguard Worker -v verbose
32*cf5a6c84SAndroid Build Coastguard Worker -r Bypass routing tables, send directly to HOST
33*cf5a6c84SAndroid Build Coastguard Worker -m Max time-to-live (max number of hops)(RANGE 1 to 255)
34*cf5a6c84SAndroid Build Coastguard Worker -p Base UDP port number used in probes(default 33434)(RANGE 1 to 65535)
35*cf5a6c84SAndroid Build Coastguard Worker -q Number of probes per TTL (default 3)(RANGE 1 to 255)
36*cf5a6c84SAndroid Build Coastguard Worker -s IP address to use as the source address
37*cf5a6c84SAndroid Build Coastguard Worker -t Type-of-service in probe packets (default 0)(RANGE 0 to 255)
38*cf5a6c84SAndroid Build Coastguard Worker -w Time in seconds to wait for a response (default 3)(RANGE 0 to 86400)
39*cf5a6c84SAndroid Build Coastguard Worker -g Loose source route gateway (8 max) (supports IPV4 only)
40*cf5a6c84SAndroid Build Coastguard Worker -z Pause Time in ms (default 0)(RANGE 0 to 86400) (supports IPV4 only)
41*cf5a6c84SAndroid Build Coastguard Worker -f Start from the 1ST_TTL hop (instead from 1)(RANGE 1 to 255) (supports IPV4 only)
42*cf5a6c84SAndroid Build Coastguard Worker -i Specify a network interface to operate with
43*cf5a6c84SAndroid Build Coastguard Worker */
44*cf5a6c84SAndroid Build Coastguard Worker #define FOR_traceroute
45*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
46*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/udp.h>
47*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/ip_icmp.h>
48*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/ip6.h>
49*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/icmp6.h>
50*cf5a6c84SAndroid Build Coastguard Worker
51*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
52*cf5a6c84SAndroid Build Coastguard Worker long max_ttl;
53*cf5a6c84SAndroid Build Coastguard Worker long port;
54*cf5a6c84SAndroid Build Coastguard Worker long ttl_probes;
55*cf5a6c84SAndroid Build Coastguard Worker char *src_ip;
56*cf5a6c84SAndroid Build Coastguard Worker long tos;
57*cf5a6c84SAndroid Build Coastguard Worker long wait_time;
58*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *loose_source;
59*cf5a6c84SAndroid Build Coastguard Worker long pause_time;
60*cf5a6c84SAndroid Build Coastguard Worker long first_ttl;
61*cf5a6c84SAndroid Build Coastguard Worker char *iface;
62*cf5a6c84SAndroid Build Coastguard Worker
63*cf5a6c84SAndroid Build Coastguard Worker uint32_t gw_list[9];
64*cf5a6c84SAndroid Build Coastguard Worker int recv_sock;
65*cf5a6c84SAndroid Build Coastguard Worker int snd_sock;
66*cf5a6c84SAndroid Build Coastguard Worker unsigned msg_len;
67*cf5a6c84SAndroid Build Coastguard Worker char *packet;
68*cf5a6c84SAndroid Build Coastguard Worker uint32_t ident;
69*cf5a6c84SAndroid Build Coastguard Worker int istraceroute6;
70*cf5a6c84SAndroid Build Coastguard Worker )
71*cf5a6c84SAndroid Build Coastguard Worker
72*cf5a6c84SAndroid Build Coastguard Worker #ifndef SOL_IPV6
73*cf5a6c84SAndroid Build Coastguard Worker # define SOL_IPV6 IPPROTO_IPV6
74*cf5a6c84SAndroid Build Coastguard Worker #endif
75*cf5a6c84SAndroid Build Coastguard Worker
76*cf5a6c84SAndroid Build Coastguard Worker #define ICMP_HD_SIZE4 8
77*cf5a6c84SAndroid Build Coastguard Worker #define USEC 1000000ULL
78*cf5a6c84SAndroid Build Coastguard Worker
79*cf5a6c84SAndroid Build Coastguard Worker struct payload_s {
80*cf5a6c84SAndroid Build Coastguard Worker uint32_t seq;
81*cf5a6c84SAndroid Build Coastguard Worker uint32_t ident;
82*cf5a6c84SAndroid Build Coastguard Worker };
83*cf5a6c84SAndroid Build Coastguard Worker
84*cf5a6c84SAndroid Build Coastguard Worker char addr_str[INET6_ADDRSTRLEN];
85*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_storage dest;
86*cf5a6c84SAndroid Build Coastguard Worker
87*cf5a6c84SAndroid Build Coastguard Worker //Compute checksum SUM of buffer P of length LEN
in_cksum(u_int16_t * p,u_int len)88*cf5a6c84SAndroid Build Coastguard Worker static u_int16_t in_cksum(u_int16_t *p, u_int len)
89*cf5a6c84SAndroid Build Coastguard Worker {
90*cf5a6c84SAndroid Build Coastguard Worker u_int32_t sum = 0;
91*cf5a6c84SAndroid Build Coastguard Worker int nwords = len >> 1;
92*cf5a6c84SAndroid Build Coastguard Worker
93*cf5a6c84SAndroid Build Coastguard Worker while (nwords-- != 0) sum += *p++;
94*cf5a6c84SAndroid Build Coastguard Worker if (len & 1) {
95*cf5a6c84SAndroid Build Coastguard Worker union {
96*cf5a6c84SAndroid Build Coastguard Worker u_int16_t w;
97*cf5a6c84SAndroid Build Coastguard Worker u_int8_t c[2];
98*cf5a6c84SAndroid Build Coastguard Worker } u;
99*cf5a6c84SAndroid Build Coastguard Worker u.c[0] = *(u_char *) p;
100*cf5a6c84SAndroid Build Coastguard Worker u.c[1] = 0;
101*cf5a6c84SAndroid Build Coastguard Worker sum += u.w;
102*cf5a6c84SAndroid Build Coastguard Worker }
103*cf5a6c84SAndroid Build Coastguard Worker // end-around-carry
104*cf5a6c84SAndroid Build Coastguard Worker sum = (sum >> 16) + (sum & 0xffff);
105*cf5a6c84SAndroid Build Coastguard Worker sum += (sum >> 16);
106*cf5a6c84SAndroid Build Coastguard Worker return (~sum);
107*cf5a6c84SAndroid Build Coastguard Worker }
108*cf5a6c84SAndroid Build Coastguard Worker
109*cf5a6c84SAndroid Build Coastguard Worker //sends a single probe packet with sequence(SEQ) and time-to-live(TTL)
send_probe4(int seq,int ttl)110*cf5a6c84SAndroid Build Coastguard Worker static void send_probe4(int seq, int ttl)
111*cf5a6c84SAndroid Build Coastguard Worker {
112*cf5a6c84SAndroid Build Coastguard Worker int res, len;
113*cf5a6c84SAndroid Build Coastguard Worker void *out;
114*cf5a6c84SAndroid Build Coastguard Worker struct payload_s *send_data4 = (struct payload_s *)(TT.packet);
115*cf5a6c84SAndroid Build Coastguard Worker struct icmp *send_icmp4 = (struct icmp *)(TT.packet);
116*cf5a6c84SAndroid Build Coastguard Worker
117*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_U) {
118*cf5a6c84SAndroid Build Coastguard Worker send_data4->seq = seq;
119*cf5a6c84SAndroid Build Coastguard Worker send_data4->ident = TT.ident;
120*cf5a6c84SAndroid Build Coastguard Worker ((struct sockaddr_in *)&dest)->sin_port = TT.port + seq;
121*cf5a6c84SAndroid Build Coastguard Worker out = send_data4;
122*cf5a6c84SAndroid Build Coastguard Worker } else {
123*cf5a6c84SAndroid Build Coastguard Worker send_icmp4->icmp_type = ICMP_ECHO;
124*cf5a6c84SAndroid Build Coastguard Worker send_icmp4->icmp_id = htons(TT.ident);
125*cf5a6c84SAndroid Build Coastguard Worker send_icmp4->icmp_seq = htons(seq);
126*cf5a6c84SAndroid Build Coastguard Worker send_icmp4->icmp_cksum = 0;
127*cf5a6c84SAndroid Build Coastguard Worker send_icmp4->icmp_cksum = in_cksum((uint16_t *) send_icmp4, TT.msg_len);
128*cf5a6c84SAndroid Build Coastguard Worker if (send_icmp4->icmp_cksum == 0) send_icmp4->icmp_cksum = 0xffff;
129*cf5a6c84SAndroid Build Coastguard Worker out = send_icmp4;
130*cf5a6c84SAndroid Build Coastguard Worker }
131*cf5a6c84SAndroid Build Coastguard Worker
132*cf5a6c84SAndroid Build Coastguard Worker res = setsockopt(TT.snd_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
133*cf5a6c84SAndroid Build Coastguard Worker if (res < 0) perror_exit("setsockopt ttl %d", ttl);
134*cf5a6c84SAndroid Build Coastguard Worker
135*cf5a6c84SAndroid Build Coastguard Worker len = TT.msg_len;
136*cf5a6c84SAndroid Build Coastguard Worker res = sendto(TT.snd_sock, out, len, 0, (struct sockaddr *) &dest,
137*cf5a6c84SAndroid Build Coastguard Worker sizeof(struct sockaddr_in));
138*cf5a6c84SAndroid Build Coastguard Worker if (res != len) perror_exit(" sendto");
139*cf5a6c84SAndroid Build Coastguard Worker }
140*cf5a6c84SAndroid Build Coastguard Worker
141*cf5a6c84SAndroid Build Coastguard Worker //sends a single probe packet with sequence(SEQ) and time-to-live(TTL)
send_probe6(int seq,int ttl)142*cf5a6c84SAndroid Build Coastguard Worker static void send_probe6(int seq, int ttl)
143*cf5a6c84SAndroid Build Coastguard Worker {
144*cf5a6c84SAndroid Build Coastguard Worker void *out;
145*cf5a6c84SAndroid Build Coastguard Worker struct payload_s *send_data6 = (struct payload_s *) (TT.packet);
146*cf5a6c84SAndroid Build Coastguard Worker
147*cf5a6c84SAndroid Build Coastguard Worker send_data6->seq = seq;
148*cf5a6c84SAndroid Build Coastguard Worker send_data6->ident = TT.ident;
149*cf5a6c84SAndroid Build Coastguard Worker ((struct sockaddr_in6 *)&dest)->sin6_port = TT.port;
150*cf5a6c84SAndroid Build Coastguard Worker
151*cf5a6c84SAndroid Build Coastguard Worker if (setsockopt(TT.snd_sock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl,
152*cf5a6c84SAndroid Build Coastguard Worker sizeof(ttl)) < 0) error_exit("setsockopt ttl %d", ttl);
153*cf5a6c84SAndroid Build Coastguard Worker
154*cf5a6c84SAndroid Build Coastguard Worker out = send_data6;
155*cf5a6c84SAndroid Build Coastguard Worker
156*cf5a6c84SAndroid Build Coastguard Worker if (sendto(TT.snd_sock, out, TT.msg_len, 0,
157*cf5a6c84SAndroid Build Coastguard Worker (struct sockaddr *) &dest, sizeof(struct sockaddr_in6)) < 0)
158*cf5a6c84SAndroid Build Coastguard Worker perror_exit("sendto");
159*cf5a6c84SAndroid Build Coastguard Worker }
160*cf5a6c84SAndroid Build Coastguard Worker
set_flag_dr(int sock)161*cf5a6c84SAndroid Build Coastguard Worker static void set_flag_dr(int sock)
162*cf5a6c84SAndroid Build Coastguard Worker {
163*cf5a6c84SAndroid Build Coastguard Worker int set = 1;
164*cf5a6c84SAndroid Build Coastguard Worker if ((toys.optflags & FLAG_d) && (setsockopt(sock,SOL_SOCKET, SO_DEBUG,
165*cf5a6c84SAndroid Build Coastguard Worker &set, sizeof(set)) < 0)) perror_exit("SO_DEBUG failed ");
166*cf5a6c84SAndroid Build Coastguard Worker
167*cf5a6c84SAndroid Build Coastguard Worker if ((toys.optflags & FLAG_r) && (setsockopt(sock, SOL_SOCKET, SO_DONTROUTE,
168*cf5a6c84SAndroid Build Coastguard Worker &set, sizeof(set)) < 0)) perror_exit("SO_DONTROUTE failed ");
169*cf5a6c84SAndroid Build Coastguard Worker }
170*cf5a6c84SAndroid Build Coastguard Worker
bind_to_interface(int sock)171*cf5a6c84SAndroid Build Coastguard Worker static void bind_to_interface(int sock)
172*cf5a6c84SAndroid Build Coastguard Worker {
173*cf5a6c84SAndroid Build Coastguard Worker struct ifreq ifr;
174*cf5a6c84SAndroid Build Coastguard Worker
175*cf5a6c84SAndroid Build Coastguard Worker snprintf(ifr.ifr_name, IFNAMSIZ, "%s", TT.iface);
176*cf5a6c84SAndroid Build Coastguard Worker if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)))
177*cf5a6c84SAndroid Build Coastguard Worker perror_msg("can't bind to interface %s", TT.iface);
178*cf5a6c84SAndroid Build Coastguard Worker }
179*cf5a6c84SAndroid Build Coastguard Worker
resolve_addr(char * host,int family,int type,int proto,void * sock)180*cf5a6c84SAndroid Build Coastguard Worker static void resolve_addr(char *host, int family, int type, int proto, void *sock)
181*cf5a6c84SAndroid Build Coastguard Worker {
182*cf5a6c84SAndroid Build Coastguard Worker struct addrinfo *info, hint;
183*cf5a6c84SAndroid Build Coastguard Worker int ret;
184*cf5a6c84SAndroid Build Coastguard Worker
185*cf5a6c84SAndroid Build Coastguard Worker memset(&hint, 0, sizeof(hint));
186*cf5a6c84SAndroid Build Coastguard Worker hint.ai_family = family;
187*cf5a6c84SAndroid Build Coastguard Worker hint.ai_socktype = type;
188*cf5a6c84SAndroid Build Coastguard Worker hint.ai_protocol = proto;
189*cf5a6c84SAndroid Build Coastguard Worker
190*cf5a6c84SAndroid Build Coastguard Worker ret = getaddrinfo(host, NULL, &hint, &info);
191*cf5a6c84SAndroid Build Coastguard Worker if (ret || !info) error_exit("bad address: %s ", host);
192*cf5a6c84SAndroid Build Coastguard Worker
193*cf5a6c84SAndroid Build Coastguard Worker memcpy(sock, info->ai_addr, info->ai_addrlen);
194*cf5a6c84SAndroid Build Coastguard Worker freeaddrinfo(info);
195*cf5a6c84SAndroid Build Coastguard Worker }
196*cf5a6c84SAndroid Build Coastguard Worker
do_trace()197*cf5a6c84SAndroid Build Coastguard Worker static void do_trace()
198*cf5a6c84SAndroid Build Coastguard Worker {
199*cf5a6c84SAndroid Build Coastguard Worker int seq, fexit, ttl, tv = TT.wait_time * 1000;
200*cf5a6c84SAndroid Build Coastguard Worker struct pollfd pfd[1];
201*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_storage from;
202*cf5a6c84SAndroid Build Coastguard Worker
203*cf5a6c84SAndroid Build Coastguard Worker memset(&from, 0, sizeof(from));
204*cf5a6c84SAndroid Build Coastguard Worker pfd[0].fd = TT.recv_sock;
205*cf5a6c84SAndroid Build Coastguard Worker pfd[0].events = POLLIN;
206*cf5a6c84SAndroid Build Coastguard Worker
207*cf5a6c84SAndroid Build Coastguard Worker for (ttl = TT.first_ttl; ttl <= TT.max_ttl; ++ttl) {
208*cf5a6c84SAndroid Build Coastguard Worker int probe, dest_reach = 0, print_verbose = 1;
209*cf5a6c84SAndroid Build Coastguard Worker struct timeval t1, t2;
210*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_storage last_addr;
211*cf5a6c84SAndroid Build Coastguard Worker
212*cf5a6c84SAndroid Build Coastguard Worker memset(&last_addr, 0, sizeof(last_addr));
213*cf5a6c84SAndroid Build Coastguard Worker fexit = 0;
214*cf5a6c84SAndroid Build Coastguard Worker xprintf("%2d", ttl);
215*cf5a6c84SAndroid Build Coastguard Worker
216*cf5a6c84SAndroid Build Coastguard Worker for (probe = 0, seq = 0; probe < TT.ttl_probes; ++probe) {
217*cf5a6c84SAndroid Build Coastguard Worker int res = 0, tleft;
218*cf5a6c84SAndroid Build Coastguard Worker
219*cf5a6c84SAndroid Build Coastguard Worker fflush(NULL);
220*cf5a6c84SAndroid Build Coastguard Worker if (!TT.istraceroute6)
221*cf5a6c84SAndroid Build Coastguard Worker if (probe && (toys.optflags & FLAG_z)) msleep(TT.pause_time);
222*cf5a6c84SAndroid Build Coastguard Worker
223*cf5a6c84SAndroid Build Coastguard Worker if (!TT.istraceroute6) send_probe4(++seq, ttl);
224*cf5a6c84SAndroid Build Coastguard Worker else send_probe6(++seq, ttl);
225*cf5a6c84SAndroid Build Coastguard Worker gettimeofday(&t1, NULL);
226*cf5a6c84SAndroid Build Coastguard Worker t2 = t1;
227*cf5a6c84SAndroid Build Coastguard Worker
228*cf5a6c84SAndroid Build Coastguard Worker while ((tleft = (int)(tv - ((unsigned long long)(t2.tv_sec * 1000ULL
229*cf5a6c84SAndroid Build Coastguard Worker + t2.tv_usec/1000) - (unsigned long long)(t1.tv_sec * 1000ULL
230*cf5a6c84SAndroid Build Coastguard Worker + t1.tv_usec/1000)))) >= 0) {
231*cf5a6c84SAndroid Build Coastguard Worker unsigned delta = 0;
232*cf5a6c84SAndroid Build Coastguard Worker if (!(res = poll(pfd, 1, tleft))) {
233*cf5a6c84SAndroid Build Coastguard Worker xprintf(" *");
234*cf5a6c84SAndroid Build Coastguard Worker break;
235*cf5a6c84SAndroid Build Coastguard Worker }
236*cf5a6c84SAndroid Build Coastguard Worker gettimeofday(&t2, NULL);
237*cf5a6c84SAndroid Build Coastguard Worker if (res < 0) {
238*cf5a6c84SAndroid Build Coastguard Worker if (errno != EINTR) perror_exit("poll");
239*cf5a6c84SAndroid Build Coastguard Worker continue;
240*cf5a6c84SAndroid Build Coastguard Worker }
241*cf5a6c84SAndroid Build Coastguard Worker delta = (t2.tv_sec * USEC + t2.tv_usec)
242*cf5a6c84SAndroid Build Coastguard Worker - (t1.tv_sec * USEC + t1.tv_usec);
243*cf5a6c84SAndroid Build Coastguard Worker
244*cf5a6c84SAndroid Build Coastguard Worker if (pfd[0].revents) {
245*cf5a6c84SAndroid Build Coastguard Worker socklen_t addrlen = sizeof(struct sockaddr_storage);
246*cf5a6c84SAndroid Build Coastguard Worker int rcv_len, icmp_res = 0;
247*cf5a6c84SAndroid Build Coastguard Worker
248*cf5a6c84SAndroid Build Coastguard Worker rcv_len = recvfrom(TT.recv_sock, toybuf, sizeof(toybuf),
249*cf5a6c84SAndroid Build Coastguard Worker MSG_DONTWAIT, (struct sockaddr *) &from, &addrlen);
250*cf5a6c84SAndroid Build Coastguard Worker if (rcv_len <= 0) continue;
251*cf5a6c84SAndroid Build Coastguard Worker
252*cf5a6c84SAndroid Build Coastguard Worker if (!TT.istraceroute6) {
253*cf5a6c84SAndroid Build Coastguard Worker int pmtu = 0;
254*cf5a6c84SAndroid Build Coastguard Worker struct ip *rcv_pkt = (struct ip*) toybuf;
255*cf5a6c84SAndroid Build Coastguard Worker struct icmp *ricmp;
256*cf5a6c84SAndroid Build Coastguard Worker
257*cf5a6c84SAndroid Build Coastguard Worker ricmp = (struct icmp *) ((char*)rcv_pkt + (rcv_pkt->ip_hl << 2));
258*cf5a6c84SAndroid Build Coastguard Worker if (ricmp->icmp_code == ICMP_UNREACH_NEEDFRAG)
259*cf5a6c84SAndroid Build Coastguard Worker pmtu = ntohs(ricmp->icmp_nextmtu);
260*cf5a6c84SAndroid Build Coastguard Worker
261*cf5a6c84SAndroid Build Coastguard Worker if ((ricmp->icmp_type == ICMP_TIMXCEED
262*cf5a6c84SAndroid Build Coastguard Worker && ricmp->icmp_code == ICMP_TIMXCEED_INTRANS)
263*cf5a6c84SAndroid Build Coastguard Worker || ricmp->icmp_type == ICMP_UNREACH
264*cf5a6c84SAndroid Build Coastguard Worker || ricmp->icmp_type == ICMP_ECHOREPLY) {
265*cf5a6c84SAndroid Build Coastguard Worker
266*cf5a6c84SAndroid Build Coastguard Worker struct udphdr *hudp;
267*cf5a6c84SAndroid Build Coastguard Worker struct icmp *hicmp;
268*cf5a6c84SAndroid Build Coastguard Worker struct ip *hip = &ricmp->icmp_ip;
269*cf5a6c84SAndroid Build Coastguard Worker
270*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_U) {
271*cf5a6c84SAndroid Build Coastguard Worker hudp = (struct udphdr*) ((char*)hip + (hip->ip_hl << 2));
272*cf5a6c84SAndroid Build Coastguard Worker if ((hip->ip_hl << 2) + 12 <=(rcv_len - (rcv_pkt->ip_hl << 2))
273*cf5a6c84SAndroid Build Coastguard Worker && hip->ip_p == IPPROTO_UDP
274*cf5a6c84SAndroid Build Coastguard Worker && hudp->dest == (TT.port + seq))
275*cf5a6c84SAndroid Build Coastguard Worker icmp_res = (ricmp->icmp_type == ICMP_TIMXCEED ? -1 :
276*cf5a6c84SAndroid Build Coastguard Worker ricmp->icmp_code);
277*cf5a6c84SAndroid Build Coastguard Worker } else {
278*cf5a6c84SAndroid Build Coastguard Worker hicmp = (struct icmp *) ((char*)hip + (hip->ip_hl << 2));
279*cf5a6c84SAndroid Build Coastguard Worker if (ricmp->icmp_type == ICMP_ECHOREPLY
280*cf5a6c84SAndroid Build Coastguard Worker && ricmp->icmp_id == ntohs(TT.ident)
281*cf5a6c84SAndroid Build Coastguard Worker && ricmp->icmp_seq == ntohs(seq))
282*cf5a6c84SAndroid Build Coastguard Worker icmp_res = ICMP_UNREACH_PORT;
283*cf5a6c84SAndroid Build Coastguard Worker else if ((hip->ip_hl << 2) + ICMP_HD_SIZE4
284*cf5a6c84SAndroid Build Coastguard Worker <= (rcv_len - (rcv_pkt->ip_hl << 2))
285*cf5a6c84SAndroid Build Coastguard Worker && hip->ip_p == IPPROTO_ICMP
286*cf5a6c84SAndroid Build Coastguard Worker && hicmp->icmp_id == htons(TT.ident)
287*cf5a6c84SAndroid Build Coastguard Worker && hicmp->icmp_seq == htons(seq))
288*cf5a6c84SAndroid Build Coastguard Worker icmp_res = (ricmp->icmp_type == ICMP_TIMXCEED ? -1 :
289*cf5a6c84SAndroid Build Coastguard Worker ricmp->icmp_code);
290*cf5a6c84SAndroid Build Coastguard Worker }
291*cf5a6c84SAndroid Build Coastguard Worker }
292*cf5a6c84SAndroid Build Coastguard Worker if (!icmp_res) continue;
293*cf5a6c84SAndroid Build Coastguard Worker
294*cf5a6c84SAndroid Build Coastguard Worker if (addrlen > 0) {
295*cf5a6c84SAndroid Build Coastguard Worker if (memcmp(&((struct sockaddr_in *)&last_addr)->sin_addr,
296*cf5a6c84SAndroid Build Coastguard Worker &((struct sockaddr_in *)&from)->sin_addr,
297*cf5a6c84SAndroid Build Coastguard Worker sizeof(struct in_addr))) {
298*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_n)) {
299*cf5a6c84SAndroid Build Coastguard Worker char host[NI_MAXHOST];
300*cf5a6c84SAndroid Build Coastguard Worker if (!getnameinfo((struct sockaddr *) &from,
301*cf5a6c84SAndroid Build Coastguard Worker sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, 0))
302*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %s (", host);
303*cf5a6c84SAndroid Build Coastguard Worker else xprintf(" %s (", inet_ntoa(
304*cf5a6c84SAndroid Build Coastguard Worker ((struct sockaddr_in *)&from)->sin_addr));
305*cf5a6c84SAndroid Build Coastguard Worker }
306*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %s", inet_ntoa(
307*cf5a6c84SAndroid Build Coastguard Worker ((struct sockaddr_in *)&from)->sin_addr));
308*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_n)) xprintf(")");
309*cf5a6c84SAndroid Build Coastguard Worker memcpy(&last_addr, &from, sizeof(from));
310*cf5a6c84SAndroid Build Coastguard Worker }
311*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %u.%03u ms", delta / 1000, delta % 1000);
312*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_l) xprintf(" (%d)", rcv_pkt->ip_ttl);
313*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_v) {
314*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %d bytes from %s : icmp type %d code %d\t",
315*cf5a6c84SAndroid Build Coastguard Worker rcv_len, inet_ntoa(((struct sockaddr_in *)&from)->sin_addr),
316*cf5a6c84SAndroid Build Coastguard Worker ricmp->icmp_type, ricmp->icmp_code);
317*cf5a6c84SAndroid Build Coastguard Worker }
318*cf5a6c84SAndroid Build Coastguard Worker } else xprintf("\t!H");
319*cf5a6c84SAndroid Build Coastguard Worker
320*cf5a6c84SAndroid Build Coastguard Worker switch (icmp_res) {
321*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_PORT:
322*cf5a6c84SAndroid Build Coastguard Worker if (rcv_pkt->ip_ttl <= 1) xprintf(" !");
323*cf5a6c84SAndroid Build Coastguard Worker dest_reach = 1;
324*cf5a6c84SAndroid Build Coastguard Worker break;
325*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_NET:
326*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !N");
327*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
328*cf5a6c84SAndroid Build Coastguard Worker break;
329*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_HOST:
330*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !H");
331*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
332*cf5a6c84SAndroid Build Coastguard Worker break;
333*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_PROTOCOL:
334*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !P");
335*cf5a6c84SAndroid Build Coastguard Worker dest_reach = 1;
336*cf5a6c84SAndroid Build Coastguard Worker break;
337*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_NEEDFRAG:
338*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !F-%d", pmtu);
339*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
340*cf5a6c84SAndroid Build Coastguard Worker break;
341*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_SRCFAIL:
342*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !S");
343*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
344*cf5a6c84SAndroid Build Coastguard Worker break;
345*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_FILTER_PROHIB:
346*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_NET_PROHIB:
347*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !A");
348*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
349*cf5a6c84SAndroid Build Coastguard Worker break;
350*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_HOST_PROHIB:
351*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !C");
352*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
353*cf5a6c84SAndroid Build Coastguard Worker break;
354*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_HOST_PRECEDENCE:
355*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !V");
356*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
357*cf5a6c84SAndroid Build Coastguard Worker break;
358*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_PRECEDENCE_CUTOFF:
359*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !C");
360*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
361*cf5a6c84SAndroid Build Coastguard Worker break;
362*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_NET_UNKNOWN:
363*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_HOST_UNKNOWN:
364*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !U");
365*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
366*cf5a6c84SAndroid Build Coastguard Worker break;
367*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_ISOLATED:
368*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !I");
369*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
370*cf5a6c84SAndroid Build Coastguard Worker break;
371*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_TOSNET:
372*cf5a6c84SAndroid Build Coastguard Worker case ICMP_UNREACH_TOSHOST:
373*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !T");
374*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
375*cf5a6c84SAndroid Build Coastguard Worker break;
376*cf5a6c84SAndroid Build Coastguard Worker default:
377*cf5a6c84SAndroid Build Coastguard Worker break;
378*cf5a6c84SAndroid Build Coastguard Worker }
379*cf5a6c84SAndroid Build Coastguard Worker break;
380*cf5a6c84SAndroid Build Coastguard Worker } else {
381*cf5a6c84SAndroid Build Coastguard Worker struct icmp6_hdr *ricmp = (struct icmp6_hdr *) toybuf;
382*cf5a6c84SAndroid Build Coastguard Worker
383*cf5a6c84SAndroid Build Coastguard Worker if ((ricmp->icmp6_type == ICMP6_TIME_EXCEEDED
384*cf5a6c84SAndroid Build Coastguard Worker && ricmp->icmp6_code == ICMP6_TIME_EXCEED_TRANSIT)
385*cf5a6c84SAndroid Build Coastguard Worker || ricmp->icmp6_type == ICMP6_DST_UNREACH
386*cf5a6c84SAndroid Build Coastguard Worker || ricmp->icmp6_type == ICMP6_ECHO_REPLY) {
387*cf5a6c84SAndroid Build Coastguard Worker
388*cf5a6c84SAndroid Build Coastguard Worker struct ip6_hdr *hip;
389*cf5a6c84SAndroid Build Coastguard Worker struct udphdr *hudp;
390*cf5a6c84SAndroid Build Coastguard Worker int hdr_next;
391*cf5a6c84SAndroid Build Coastguard Worker
392*cf5a6c84SAndroid Build Coastguard Worker hip = (struct ip6_hdr *)(ricmp + 1);
393*cf5a6c84SAndroid Build Coastguard Worker hudp = (struct udphdr*) (hip + 1);
394*cf5a6c84SAndroid Build Coastguard Worker hdr_next = hip->ip6_nxt;
395*cf5a6c84SAndroid Build Coastguard Worker if (hdr_next == IPPROTO_FRAGMENT) {
396*cf5a6c84SAndroid Build Coastguard Worker hdr_next = *(unsigned char*)hudp;
397*cf5a6c84SAndroid Build Coastguard Worker hudp++;
398*cf5a6c84SAndroid Build Coastguard Worker }
399*cf5a6c84SAndroid Build Coastguard Worker
400*cf5a6c84SAndroid Build Coastguard Worker if (hdr_next == IPPROTO_UDP) {
401*cf5a6c84SAndroid Build Coastguard Worker struct payload_s *pkt = (struct payload_s*)(hudp + 1);
402*cf5a6c84SAndroid Build Coastguard Worker if ((pkt->ident == TT.ident) && (pkt->seq == seq))
403*cf5a6c84SAndroid Build Coastguard Worker icmp_res = (ricmp->icmp6_type == ICMP6_TIME_EXCEEDED) ? -1 :
404*cf5a6c84SAndroid Build Coastguard Worker ricmp->icmp6_code;
405*cf5a6c84SAndroid Build Coastguard Worker }
406*cf5a6c84SAndroid Build Coastguard Worker }
407*cf5a6c84SAndroid Build Coastguard Worker
408*cf5a6c84SAndroid Build Coastguard Worker if (!icmp_res) continue;
409*cf5a6c84SAndroid Build Coastguard Worker if (addrlen > 0) {
410*cf5a6c84SAndroid Build Coastguard Worker if (memcmp(&((struct sockaddr_in6 *)&last_addr)->sin6_addr,
411*cf5a6c84SAndroid Build Coastguard Worker &((struct sockaddr_in6 *)&from)->sin6_addr,
412*cf5a6c84SAndroid Build Coastguard Worker sizeof(struct in6_addr))) {
413*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_n)) {
414*cf5a6c84SAndroid Build Coastguard Worker char host[NI_MAXHOST];
415*cf5a6c84SAndroid Build Coastguard Worker if (!getnameinfo((struct sockaddr *) &from,
416*cf5a6c84SAndroid Build Coastguard Worker sizeof(from), host, sizeof(host), NULL, 0, 0))
417*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %s (", host);
418*cf5a6c84SAndroid Build Coastguard Worker }
419*cf5a6c84SAndroid Build Coastguard Worker memset(addr_str, '\0', INET6_ADDRSTRLEN);
420*cf5a6c84SAndroid Build Coastguard Worker inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&from)->sin6_addr,
421*cf5a6c84SAndroid Build Coastguard Worker addr_str, INET6_ADDRSTRLEN);
422*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %s", addr_str);
423*cf5a6c84SAndroid Build Coastguard Worker
424*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_n)) xprintf(")");
425*cf5a6c84SAndroid Build Coastguard Worker memcpy(&last_addr,&from,sizeof(from));
426*cf5a6c84SAndroid Build Coastguard Worker }
427*cf5a6c84SAndroid Build Coastguard Worker
428*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_v) {
429*cf5a6c84SAndroid Build Coastguard Worker if(print_verbose){
430*cf5a6c84SAndroid Build Coastguard Worker memset(addr_str, '\0', INET6_ADDRSTRLEN);
431*cf5a6c84SAndroid Build Coastguard Worker inet_ntop(AF_INET6, &((struct sockaddr_in6 *)
432*cf5a6c84SAndroid Build Coastguard Worker &from)->sin6_addr, addr_str, INET6_ADDRSTRLEN);
433*cf5a6c84SAndroid Build Coastguard Worker rcv_len -= sizeof(struct ip6_hdr);
434*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %d bytes to %s ", rcv_len, addr_str);
435*cf5a6c84SAndroid Build Coastguard Worker }
436*cf5a6c84SAndroid Build Coastguard Worker }
437*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %u.%03u ms", delta / 1000, delta % 1000);
438*cf5a6c84SAndroid Build Coastguard Worker delta = 0;
439*cf5a6c84SAndroid Build Coastguard Worker
440*cf5a6c84SAndroid Build Coastguard Worker } else xprintf("\t!H");
441*cf5a6c84SAndroid Build Coastguard Worker
442*cf5a6c84SAndroid Build Coastguard Worker switch (icmp_res) {
443*cf5a6c84SAndroid Build Coastguard Worker case ICMP6_DST_UNREACH_NOPORT:
444*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
445*cf5a6c84SAndroid Build Coastguard Worker dest_reach = 1;
446*cf5a6c84SAndroid Build Coastguard Worker break;
447*cf5a6c84SAndroid Build Coastguard Worker case ICMP6_DST_UNREACH_NOROUTE:
448*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !N");
449*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
450*cf5a6c84SAndroid Build Coastguard Worker break;
451*cf5a6c84SAndroid Build Coastguard Worker case ICMP6_DST_UNREACH_ADDR:
452*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !H");
453*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
454*cf5a6c84SAndroid Build Coastguard Worker break;
455*cf5a6c84SAndroid Build Coastguard Worker case ICMP6_DST_UNREACH_ADMIN:
456*cf5a6c84SAndroid Build Coastguard Worker xprintf(" !S");
457*cf5a6c84SAndroid Build Coastguard Worker ++fexit;
458*cf5a6c84SAndroid Build Coastguard Worker break;
459*cf5a6c84SAndroid Build Coastguard Worker default:
460*cf5a6c84SAndroid Build Coastguard Worker break;
461*cf5a6c84SAndroid Build Coastguard Worker }
462*cf5a6c84SAndroid Build Coastguard Worker break;
463*cf5a6c84SAndroid Build Coastguard Worker }
464*cf5a6c84SAndroid Build Coastguard Worker } //revents
465*cf5a6c84SAndroid Build Coastguard Worker }
466*cf5a6c84SAndroid Build Coastguard Worker print_verbose = 0;
467*cf5a6c84SAndroid Build Coastguard Worker }
468*cf5a6c84SAndroid Build Coastguard Worker xputc('\n');
469*cf5a6c84SAndroid Build Coastguard Worker if(!TT.istraceroute6) {
470*cf5a6c84SAndroid Build Coastguard Worker if (!memcmp(&((struct sockaddr_in *)&from)->sin_addr,
471*cf5a6c84SAndroid Build Coastguard Worker &((struct sockaddr_in *)&dest)->sin_addr, sizeof(struct in_addr))
472*cf5a6c84SAndroid Build Coastguard Worker || dest_reach || (fexit && fexit >= TT.ttl_probes -1))
473*cf5a6c84SAndroid Build Coastguard Worker break;
474*cf5a6c84SAndroid Build Coastguard Worker } else if (dest_reach || (fexit > 0 && fexit >= TT.ttl_probes -1)) break;
475*cf5a6c84SAndroid Build Coastguard Worker }
476*cf5a6c84SAndroid Build Coastguard Worker }
477*cf5a6c84SAndroid Build Coastguard Worker
traceroute_main(void)478*cf5a6c84SAndroid Build Coastguard Worker void traceroute_main(void)
479*cf5a6c84SAndroid Build Coastguard Worker {
480*cf5a6c84SAndroid Build Coastguard Worker unsigned pack_size = 0, tyser = 0;
481*cf5a6c84SAndroid Build Coastguard Worker int lsrr = 0, set = 1;
482*cf5a6c84SAndroid Build Coastguard Worker
483*cf5a6c84SAndroid Build Coastguard Worker if(!(toys.optflags & FLAG_4) &&
484*cf5a6c84SAndroid Build Coastguard Worker (inet_pton(AF_INET6, toys.optargs[0], &dest)))
485*cf5a6c84SAndroid Build Coastguard Worker toys.optflags |= FLAG_6;
486*cf5a6c84SAndroid Build Coastguard Worker
487*cf5a6c84SAndroid Build Coastguard Worker memset(&dest, 0, sizeof(dest));
488*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_6) TT.istraceroute6 = 1;
489*cf5a6c84SAndroid Build Coastguard Worker else TT.istraceroute6 = toys.which->name[10] == '6';
490*cf5a6c84SAndroid Build Coastguard Worker
491*cf5a6c84SAndroid Build Coastguard Worker if(!TT.istraceroute6 && (toys.optflags & FLAG_g)) {
492*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *node;
493*cf5a6c84SAndroid Build Coastguard Worker
494*cf5a6c84SAndroid Build Coastguard Worker for (node = TT.loose_source; node; node = node->next, lsrr++) {
495*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_in sin;
496*cf5a6c84SAndroid Build Coastguard Worker
497*cf5a6c84SAndroid Build Coastguard Worker memset( &sin, 0, sizeof(sin));
498*cf5a6c84SAndroid Build Coastguard Worker if (lsrr >= 8) error_exit("no more than 8 gateways"); // NGATEWAYS
499*cf5a6c84SAndroid Build Coastguard Worker resolve_addr(node->arg, AF_INET, SOCK_STREAM, 0, &sin);
500*cf5a6c84SAndroid Build Coastguard Worker TT.gw_list[lsrr] = sin.sin_addr.s_addr;
501*cf5a6c84SAndroid Build Coastguard Worker }
502*cf5a6c84SAndroid Build Coastguard Worker } else TT.first_ttl = 1;
503*cf5a6c84SAndroid Build Coastguard Worker
504*cf5a6c84SAndroid Build Coastguard Worker TT.msg_len = pack_size = ICMP_HD_SIZE4; //udp payload is also 8bytes
505*cf5a6c84SAndroid Build Coastguard Worker if (toys.optargs[1])
506*cf5a6c84SAndroid Build Coastguard Worker TT.msg_len = atolx_range(toys.optargs[1], pack_size, 32768);//max packet size
507*cf5a6c84SAndroid Build Coastguard Worker
508*cf5a6c84SAndroid Build Coastguard Worker TT.recv_sock = xsocket((TT.istraceroute6 ? AF_INET6 : AF_INET), SOCK_RAW,
509*cf5a6c84SAndroid Build Coastguard Worker (TT.istraceroute6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP));
510*cf5a6c84SAndroid Build Coastguard Worker
511*cf5a6c84SAndroid Build Coastguard Worker if (TT.istraceroute6) {
512*cf5a6c84SAndroid Build Coastguard Worker int two = 2;
513*cf5a6c84SAndroid Build Coastguard Worker #ifdef IPV6_RECVPKTINFO
514*cf5a6c84SAndroid Build Coastguard Worker setsockopt(TT.recv_sock, SOL_IPV6, IPV6_RECVPKTINFO, &set,
515*cf5a6c84SAndroid Build Coastguard Worker sizeof(set));
516*cf5a6c84SAndroid Build Coastguard Worker setsockopt(TT.recv_sock, SOL_IPV6, IPV6_2292PKTINFO, &set,
517*cf5a6c84SAndroid Build Coastguard Worker sizeof(set));
518*cf5a6c84SAndroid Build Coastguard Worker #else
519*cf5a6c84SAndroid Build Coastguard Worker setsockopt(TT.recv_sock, SOL_IPV6, IPV6_PKTINFO, &set, sizeof(set));
520*cf5a6c84SAndroid Build Coastguard Worker #endif
521*cf5a6c84SAndroid Build Coastguard Worker
522*cf5a6c84SAndroid Build Coastguard Worker if (setsockopt(TT.recv_sock, SOL_RAW, IPV6_CHECKSUM, &two,
523*cf5a6c84SAndroid Build Coastguard Worker sizeof(two)) < 0) perror_exit("setsockopt RAW_CHECKSUM");
524*cf5a6c84SAndroid Build Coastguard Worker }
525*cf5a6c84SAndroid Build Coastguard Worker
526*cf5a6c84SAndroid Build Coastguard Worker set_flag_dr(TT.recv_sock);
527*cf5a6c84SAndroid Build Coastguard Worker
528*cf5a6c84SAndroid Build Coastguard Worker if (!TT.istraceroute6) {
529*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_U)
530*cf5a6c84SAndroid Build Coastguard Worker TT.snd_sock = xsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
531*cf5a6c84SAndroid Build Coastguard Worker else TT.snd_sock = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
532*cf5a6c84SAndroid Build Coastguard Worker
533*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_i) bind_to_interface(TT.snd_sock);
534*cf5a6c84SAndroid Build Coastguard Worker
535*cf5a6c84SAndroid Build Coastguard Worker resolve_addr(toys.optargs[0], AF_INET, ((toys.optflags & FLAG_U) ?
536*cf5a6c84SAndroid Build Coastguard Worker SOCK_DGRAM : SOCK_RAW), ((toys.optflags & FLAG_U) ? IPPROTO_UDP :
537*cf5a6c84SAndroid Build Coastguard Worker IPPROTO_ICMP), &dest);
538*cf5a6c84SAndroid Build Coastguard Worker if (lsrr > 0) {
539*cf5a6c84SAndroid Build Coastguard Worker unsigned char optlist[MAX_IPOPTLEN];
540*cf5a6c84SAndroid Build Coastguard Worker unsigned size;
541*cf5a6c84SAndroid Build Coastguard Worker
542*cf5a6c84SAndroid Build Coastguard Worker TT.gw_list[lsrr] = ((struct sockaddr_in *)&dest)->sin_addr.s_addr;
543*cf5a6c84SAndroid Build Coastguard Worker ++lsrr;
544*cf5a6c84SAndroid Build Coastguard Worker
545*cf5a6c84SAndroid Build Coastguard Worker optlist[0] = IPOPT_NOP;
546*cf5a6c84SAndroid Build Coastguard Worker optlist[1] = IPOPT_LSRR;// loose source route option
547*cf5a6c84SAndroid Build Coastguard Worker size = lsrr * sizeof(TT.gw_list[0]);
548*cf5a6c84SAndroid Build Coastguard Worker optlist[2] = size + 3;
549*cf5a6c84SAndroid Build Coastguard Worker optlist[3] = IPOPT_MINOFF;
550*cf5a6c84SAndroid Build Coastguard Worker memcpy(optlist + 4, TT.gw_list, size);
551*cf5a6c84SAndroid Build Coastguard Worker
552*cf5a6c84SAndroid Build Coastguard Worker if (setsockopt(TT.snd_sock, IPPROTO_IP, IP_OPTIONS,
553*cf5a6c84SAndroid Build Coastguard Worker (char *)optlist, size + sizeof(TT.gw_list[0])) < 0)
554*cf5a6c84SAndroid Build Coastguard Worker perror_exit("LSRR IP_OPTIONS");
555*cf5a6c84SAndroid Build Coastguard Worker }
556*cf5a6c84SAndroid Build Coastguard Worker } else TT.snd_sock = xsocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
557*cf5a6c84SAndroid Build Coastguard Worker
558*cf5a6c84SAndroid Build Coastguard Worker if (setsockopt(TT.snd_sock, SOL_SOCKET, SO_SNDBUF, &TT.msg_len,
559*cf5a6c84SAndroid Build Coastguard Worker sizeof(TT.msg_len)) < 0) perror_exit("SO_SNDBUF failed ");
560*cf5a6c84SAndroid Build Coastguard Worker
561*cf5a6c84SAndroid Build Coastguard Worker if (!TT.istraceroute6) {
562*cf5a6c84SAndroid Build Coastguard Worker if ((toys.optflags & FLAG_t) &&
563*cf5a6c84SAndroid Build Coastguard Worker setsockopt(TT.snd_sock, IPPROTO_IP, IP_TOS, &tyser, sizeof(tyser)) < 0)
564*cf5a6c84SAndroid Build Coastguard Worker perror_exit("IP_TOS %ld failed ", TT.tos);
565*cf5a6c84SAndroid Build Coastguard Worker
566*cf5a6c84SAndroid Build Coastguard Worker #ifdef IP_DONTFRAG
567*cf5a6c84SAndroid Build Coastguard Worker if ((toys.optflags & FLAG_F) &&
568*cf5a6c84SAndroid Build Coastguard Worker (setsockopt(TT.snd_sock, IPPROTO_IP, IP_DONTFRAG, &set,
569*cf5a6c84SAndroid Build Coastguard Worker sizeof(set)) < 0)) perror_exit("IP_DONTFRAG failed ");
570*cf5a6c84SAndroid Build Coastguard Worker #endif
571*cf5a6c84SAndroid Build Coastguard Worker } else if (setsockopt(TT.snd_sock, IPPROTO_IPV6, IPV6_TCLASS, &TT.tos,
572*cf5a6c84SAndroid Build Coastguard Worker sizeof(TT.tos)) < 0) perror_exit("IPV6_TCLASS %ld failed ", TT.tos);
573*cf5a6c84SAndroid Build Coastguard Worker
574*cf5a6c84SAndroid Build Coastguard Worker set_flag_dr(TT.snd_sock);
575*cf5a6c84SAndroid Build Coastguard Worker TT.packet = xzalloc(TT.msg_len);
576*cf5a6c84SAndroid Build Coastguard Worker TT.ident = getpid();
577*cf5a6c84SAndroid Build Coastguard Worker
578*cf5a6c84SAndroid Build Coastguard Worker if (!TT.istraceroute6) {
579*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_U)) TT.ident |= 0x8000;
580*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_s) {
581*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_in source;
582*cf5a6c84SAndroid Build Coastguard Worker
583*cf5a6c84SAndroid Build Coastguard Worker memset(&source, 0, sizeof(source));
584*cf5a6c84SAndroid Build Coastguard Worker if (!inet_aton(TT.src_ip, &(source.sin_addr)))
585*cf5a6c84SAndroid Build Coastguard Worker error_exit("bad address: %s", TT.src_ip);
586*cf5a6c84SAndroid Build Coastguard Worker if (setsockopt(TT.snd_sock, IPPROTO_IP, IP_MULTICAST_IF,
587*cf5a6c84SAndroid Build Coastguard Worker (struct sockaddr*)&source, sizeof(struct sockaddr_in)))
588*cf5a6c84SAndroid Build Coastguard Worker perror_exit("can't set multicast source interface");
589*cf5a6c84SAndroid Build Coastguard Worker xbind(TT.snd_sock,(struct sockaddr*)&source, sizeof(struct sockaddr_in));
590*cf5a6c84SAndroid Build Coastguard Worker }
591*cf5a6c84SAndroid Build Coastguard Worker
592*cf5a6c84SAndroid Build Coastguard Worker if(TT.first_ttl > TT.max_ttl)
593*cf5a6c84SAndroid Build Coastguard Worker error_exit("ERROR :Range for -f is 1 to %ld (max ttl)", TT.max_ttl);
594*cf5a6c84SAndroid Build Coastguard Worker
595*cf5a6c84SAndroid Build Coastguard Worker xprintf("traceroute to %s(%s)", toys.optargs[0],
596*cf5a6c84SAndroid Build Coastguard Worker inet_ntoa(((struct sockaddr_in *)&dest)->sin_addr));
597*cf5a6c84SAndroid Build Coastguard Worker } else {
598*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_i) bind_to_interface(TT.snd_sock);
599*cf5a6c84SAndroid Build Coastguard Worker
600*cf5a6c84SAndroid Build Coastguard Worker resolve_addr(toys.optargs[0], AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &dest);
601*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_s) {
602*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_in6 source;
603*cf5a6c84SAndroid Build Coastguard Worker
604*cf5a6c84SAndroid Build Coastguard Worker memset(&source, 0, sizeof(source));
605*cf5a6c84SAndroid Build Coastguard Worker if(inet_pton(AF_INET6, TT.src_ip, &(source.sin6_addr)) <= 0)
606*cf5a6c84SAndroid Build Coastguard Worker error_exit("bad address: %s", TT.src_ip);
607*cf5a6c84SAndroid Build Coastguard Worker
608*cf5a6c84SAndroid Build Coastguard Worker xbind(TT.snd_sock,(struct sockaddr*)&source, sizeof(struct sockaddr_in6));
609*cf5a6c84SAndroid Build Coastguard Worker } else {
610*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_in6 prb;
611*cf5a6c84SAndroid Build Coastguard Worker socklen_t len = sizeof(prb);
612*cf5a6c84SAndroid Build Coastguard Worker int p_fd = xsocket(AF_INET6, SOCK_DGRAM, 0);
613*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_i) bind_to_interface(p_fd);
614*cf5a6c84SAndroid Build Coastguard Worker
615*cf5a6c84SAndroid Build Coastguard Worker ((struct sockaddr_in6 *)&dest)->sin6_port = htons(1025);
616*cf5a6c84SAndroid Build Coastguard Worker xconnect(p_fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_in6));
617*cf5a6c84SAndroid Build Coastguard Worker if(getsockname(p_fd, (struct sockaddr *)&prb, &len))
618*cf5a6c84SAndroid Build Coastguard Worker error_exit("probe addr failed");
619*cf5a6c84SAndroid Build Coastguard Worker close(p_fd);
620*cf5a6c84SAndroid Build Coastguard Worker prb.sin6_port = 0;
621*cf5a6c84SAndroid Build Coastguard Worker xbind(TT.snd_sock, (struct sockaddr*)&prb, sizeof(struct sockaddr_in6));
622*cf5a6c84SAndroid Build Coastguard Worker xbind(TT.recv_sock, (struct sockaddr*)&prb, sizeof(struct sockaddr_in6));
623*cf5a6c84SAndroid Build Coastguard Worker }
624*cf5a6c84SAndroid Build Coastguard Worker
625*cf5a6c84SAndroid Build Coastguard Worker inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&dest)->sin6_addr,
626*cf5a6c84SAndroid Build Coastguard Worker addr_str, INET6_ADDRSTRLEN);
627*cf5a6c84SAndroid Build Coastguard Worker xprintf("traceroute6 to %s(%s)", toys.optargs[0], addr_str);
628*cf5a6c84SAndroid Build Coastguard Worker }
629*cf5a6c84SAndroid Build Coastguard Worker
630*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_s) xprintf(" from %s",TT.src_ip);
631*cf5a6c84SAndroid Build Coastguard Worker xprintf(", %ld hops max, %u byte packets\n", TT.max_ttl, TT.msg_len);
632*cf5a6c84SAndroid Build Coastguard Worker
633*cf5a6c84SAndroid Build Coastguard Worker do_trace();
634*cf5a6c84SAndroid Build Coastguard Worker }
635