1*bd1f8aebSAndroid Build Coastguard Worker /*
2*bd1f8aebSAndroid Build Coastguard Worker * tracepath6.c
3*bd1f8aebSAndroid Build Coastguard Worker *
4*bd1f8aebSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*bd1f8aebSAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*bd1f8aebSAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*bd1f8aebSAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*bd1f8aebSAndroid Build Coastguard Worker *
9*bd1f8aebSAndroid Build Coastguard Worker * Authors: Alexey Kuznetsov, <[email protected]>
10*bd1f8aebSAndroid Build Coastguard Worker */
11*bd1f8aebSAndroid Build Coastguard Worker
12*bd1f8aebSAndroid Build Coastguard Worker #include <stdio.h>
13*bd1f8aebSAndroid Build Coastguard Worker #include <stdlib.h>
14*bd1f8aebSAndroid Build Coastguard Worker #include <unistd.h>
15*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
16*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/in.h>
17*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/icmp6.h>
18*bd1f8aebSAndroid Build Coastguard Worker
19*bd1f8aebSAndroid Build Coastguard Worker #include <linux/types.h>
20*bd1f8aebSAndroid Build Coastguard Worker #include <linux/errqueue.h>
21*bd1f8aebSAndroid Build Coastguard Worker #include <errno.h>
22*bd1f8aebSAndroid Build Coastguard Worker #include <string.h>
23*bd1f8aebSAndroid Build Coastguard Worker #include <netdb.h>
24*bd1f8aebSAndroid Build Coastguard Worker #include <resolv.h>
25*bd1f8aebSAndroid Build Coastguard Worker #include <sys/time.h>
26*bd1f8aebSAndroid Build Coastguard Worker #include <sys/uio.h>
27*bd1f8aebSAndroid Build Coastguard Worker #include <arpa/inet.h>
28*bd1f8aebSAndroid Build Coastguard Worker
29*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
30*bd1f8aebSAndroid Build Coastguard Worker #include <idna.h>
31*bd1f8aebSAndroid Build Coastguard Worker #include <locale.h>
32*bd1f8aebSAndroid Build Coastguard Worker #endif
33*bd1f8aebSAndroid Build Coastguard Worker
34*bd1f8aebSAndroid Build Coastguard Worker #ifndef SOL_IPV6
35*bd1f8aebSAndroid Build Coastguard Worker #define SOL_IPV6 IPPROTO_IPV6
36*bd1f8aebSAndroid Build Coastguard Worker #endif
37*bd1f8aebSAndroid Build Coastguard Worker
38*bd1f8aebSAndroid Build Coastguard Worker #ifndef IP_PMTUDISC_DO
39*bd1f8aebSAndroid Build Coastguard Worker #define IP_PMTUDISC_DO 3
40*bd1f8aebSAndroid Build Coastguard Worker #endif
41*bd1f8aebSAndroid Build Coastguard Worker #ifndef IPV6_PMTUDISC_DO
42*bd1f8aebSAndroid Build Coastguard Worker #define IPV6_PMTUDISC_DO 3
43*bd1f8aebSAndroid Build Coastguard Worker #endif
44*bd1f8aebSAndroid Build Coastguard Worker
45*bd1f8aebSAndroid Build Coastguard Worker #define MAX_HOPS_LIMIT 255
46*bd1f8aebSAndroid Build Coastguard Worker #define MAX_HOPS_DEFAULT 30
47*bd1f8aebSAndroid Build Coastguard Worker
48*bd1f8aebSAndroid Build Coastguard Worker struct hhistory
49*bd1f8aebSAndroid Build Coastguard Worker {
50*bd1f8aebSAndroid Build Coastguard Worker int hops;
51*bd1f8aebSAndroid Build Coastguard Worker struct timeval sendtime;
52*bd1f8aebSAndroid Build Coastguard Worker };
53*bd1f8aebSAndroid Build Coastguard Worker
54*bd1f8aebSAndroid Build Coastguard Worker struct hhistory his[64];
55*bd1f8aebSAndroid Build Coastguard Worker int hisptr;
56*bd1f8aebSAndroid Build Coastguard Worker
57*bd1f8aebSAndroid Build Coastguard Worker sa_family_t family = AF_INET6;
58*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_storage target;
59*bd1f8aebSAndroid Build Coastguard Worker socklen_t targetlen;
60*bd1f8aebSAndroid Build Coastguard Worker __u16 base_port;
61*bd1f8aebSAndroid Build Coastguard Worker int max_hops = MAX_HOPS_DEFAULT;
62*bd1f8aebSAndroid Build Coastguard Worker
63*bd1f8aebSAndroid Build Coastguard Worker int overhead;
64*bd1f8aebSAndroid Build Coastguard Worker int mtu;
65*bd1f8aebSAndroid Build Coastguard Worker void *pktbuf;
66*bd1f8aebSAndroid Build Coastguard Worker int hops_to = -1;
67*bd1f8aebSAndroid Build Coastguard Worker int hops_from = -1;
68*bd1f8aebSAndroid Build Coastguard Worker int no_resolve = 0;
69*bd1f8aebSAndroid Build Coastguard Worker int show_both = 0;
70*bd1f8aebSAndroid Build Coastguard Worker int mapped;
71*bd1f8aebSAndroid Build Coastguard Worker
72*bd1f8aebSAndroid Build Coastguard Worker #define HOST_COLUMN_SIZE 52
73*bd1f8aebSAndroid Build Coastguard Worker
74*bd1f8aebSAndroid Build Coastguard Worker struct probehdr
75*bd1f8aebSAndroid Build Coastguard Worker {
76*bd1f8aebSAndroid Build Coastguard Worker __u32 ttl;
77*bd1f8aebSAndroid Build Coastguard Worker struct timeval tv;
78*bd1f8aebSAndroid Build Coastguard Worker };
79*bd1f8aebSAndroid Build Coastguard Worker
data_wait(int fd)80*bd1f8aebSAndroid Build Coastguard Worker void data_wait(int fd)
81*bd1f8aebSAndroid Build Coastguard Worker {
82*bd1f8aebSAndroid Build Coastguard Worker fd_set fds;
83*bd1f8aebSAndroid Build Coastguard Worker struct timeval tv;
84*bd1f8aebSAndroid Build Coastguard Worker FD_ZERO(&fds);
85*bd1f8aebSAndroid Build Coastguard Worker FD_SET(fd, &fds);
86*bd1f8aebSAndroid Build Coastguard Worker tv.tv_sec = 1;
87*bd1f8aebSAndroid Build Coastguard Worker tv.tv_usec = 0;
88*bd1f8aebSAndroid Build Coastguard Worker select(fd+1, &fds, NULL, NULL, &tv);
89*bd1f8aebSAndroid Build Coastguard Worker }
90*bd1f8aebSAndroid Build Coastguard Worker
print_host(const char * a,const char * b,int both)91*bd1f8aebSAndroid Build Coastguard Worker void print_host(const char *a, const char *b, int both)
92*bd1f8aebSAndroid Build Coastguard Worker {
93*bd1f8aebSAndroid Build Coastguard Worker int plen;
94*bd1f8aebSAndroid Build Coastguard Worker plen = printf("%s", a);
95*bd1f8aebSAndroid Build Coastguard Worker if (both)
96*bd1f8aebSAndroid Build Coastguard Worker plen += printf(" (%s)", b);
97*bd1f8aebSAndroid Build Coastguard Worker if (plen >= HOST_COLUMN_SIZE)
98*bd1f8aebSAndroid Build Coastguard Worker plen = HOST_COLUMN_SIZE - 1;
99*bd1f8aebSAndroid Build Coastguard Worker printf("%*s", HOST_COLUMN_SIZE - plen, "");
100*bd1f8aebSAndroid Build Coastguard Worker }
101*bd1f8aebSAndroid Build Coastguard Worker
recverr(int fd,int ttl)102*bd1f8aebSAndroid Build Coastguard Worker int recverr(int fd, int ttl)
103*bd1f8aebSAndroid Build Coastguard Worker {
104*bd1f8aebSAndroid Build Coastguard Worker int res;
105*bd1f8aebSAndroid Build Coastguard Worker struct probehdr rcvbuf;
106*bd1f8aebSAndroid Build Coastguard Worker char cbuf[512];
107*bd1f8aebSAndroid Build Coastguard Worker struct iovec iov;
108*bd1f8aebSAndroid Build Coastguard Worker struct msghdr msg;
109*bd1f8aebSAndroid Build Coastguard Worker struct cmsghdr *cmsg;
110*bd1f8aebSAndroid Build Coastguard Worker struct sock_extended_err *e;
111*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_storage addr;
112*bd1f8aebSAndroid Build Coastguard Worker struct timeval tv;
113*bd1f8aebSAndroid Build Coastguard Worker struct timeval *rettv;
114*bd1f8aebSAndroid Build Coastguard Worker int slot = 0;
115*bd1f8aebSAndroid Build Coastguard Worker int rethops;
116*bd1f8aebSAndroid Build Coastguard Worker int sndhops;
117*bd1f8aebSAndroid Build Coastguard Worker int progress = -1;
118*bd1f8aebSAndroid Build Coastguard Worker int broken_router;
119*bd1f8aebSAndroid Build Coastguard Worker
120*bd1f8aebSAndroid Build Coastguard Worker restart:
121*bd1f8aebSAndroid Build Coastguard Worker memset(&rcvbuf, -1, sizeof(rcvbuf));
122*bd1f8aebSAndroid Build Coastguard Worker iov.iov_base = &rcvbuf;
123*bd1f8aebSAndroid Build Coastguard Worker iov.iov_len = sizeof(rcvbuf);
124*bd1f8aebSAndroid Build Coastguard Worker msg.msg_name = (caddr_t)&addr;
125*bd1f8aebSAndroid Build Coastguard Worker msg.msg_namelen = sizeof(addr);
126*bd1f8aebSAndroid Build Coastguard Worker msg.msg_iov = &iov;
127*bd1f8aebSAndroid Build Coastguard Worker msg.msg_iovlen = 1;
128*bd1f8aebSAndroid Build Coastguard Worker msg.msg_flags = 0;
129*bd1f8aebSAndroid Build Coastguard Worker msg.msg_control = cbuf;
130*bd1f8aebSAndroid Build Coastguard Worker msg.msg_controllen = sizeof(cbuf);
131*bd1f8aebSAndroid Build Coastguard Worker
132*bd1f8aebSAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
133*bd1f8aebSAndroid Build Coastguard Worker res = recvmsg(fd, &msg, MSG_ERRQUEUE);
134*bd1f8aebSAndroid Build Coastguard Worker if (res < 0) {
135*bd1f8aebSAndroid Build Coastguard Worker if (errno == EAGAIN)
136*bd1f8aebSAndroid Build Coastguard Worker return progress;
137*bd1f8aebSAndroid Build Coastguard Worker goto restart;
138*bd1f8aebSAndroid Build Coastguard Worker }
139*bd1f8aebSAndroid Build Coastguard Worker
140*bd1f8aebSAndroid Build Coastguard Worker progress = mtu;
141*bd1f8aebSAndroid Build Coastguard Worker
142*bd1f8aebSAndroid Build Coastguard Worker rethops = -1;
143*bd1f8aebSAndroid Build Coastguard Worker sndhops = -1;
144*bd1f8aebSAndroid Build Coastguard Worker e = NULL;
145*bd1f8aebSAndroid Build Coastguard Worker rettv = NULL;
146*bd1f8aebSAndroid Build Coastguard Worker
147*bd1f8aebSAndroid Build Coastguard Worker slot = -base_port;
148*bd1f8aebSAndroid Build Coastguard Worker switch (family) {
149*bd1f8aebSAndroid Build Coastguard Worker case AF_INET6:
150*bd1f8aebSAndroid Build Coastguard Worker slot += ntohs(((struct sockaddr_in6 *)&addr)->sin6_port);
151*bd1f8aebSAndroid Build Coastguard Worker break;
152*bd1f8aebSAndroid Build Coastguard Worker case AF_INET:
153*bd1f8aebSAndroid Build Coastguard Worker slot += ntohs(((struct sockaddr_in *)&addr)->sin_port);
154*bd1f8aebSAndroid Build Coastguard Worker break;
155*bd1f8aebSAndroid Build Coastguard Worker }
156*bd1f8aebSAndroid Build Coastguard Worker
157*bd1f8aebSAndroid Build Coastguard Worker if (slot >= 0 && slot < 63 && his[slot].hops) {
158*bd1f8aebSAndroid Build Coastguard Worker sndhops = his[slot].hops;
159*bd1f8aebSAndroid Build Coastguard Worker rettv = &his[slot].sendtime;
160*bd1f8aebSAndroid Build Coastguard Worker his[slot].hops = 0;
161*bd1f8aebSAndroid Build Coastguard Worker }
162*bd1f8aebSAndroid Build Coastguard Worker broken_router = 0;
163*bd1f8aebSAndroid Build Coastguard Worker if (res == sizeof(rcvbuf)) {
164*bd1f8aebSAndroid Build Coastguard Worker if (rcvbuf.ttl == 0 || rcvbuf.tv.tv_sec == 0)
165*bd1f8aebSAndroid Build Coastguard Worker broken_router = 1;
166*bd1f8aebSAndroid Build Coastguard Worker else {
167*bd1f8aebSAndroid Build Coastguard Worker sndhops = rcvbuf.ttl;
168*bd1f8aebSAndroid Build Coastguard Worker rettv = &rcvbuf.tv;
169*bd1f8aebSAndroid Build Coastguard Worker }
170*bd1f8aebSAndroid Build Coastguard Worker }
171*bd1f8aebSAndroid Build Coastguard Worker
172*bd1f8aebSAndroid Build Coastguard Worker for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
173*bd1f8aebSAndroid Build Coastguard Worker switch (cmsg->cmsg_level) {
174*bd1f8aebSAndroid Build Coastguard Worker case SOL_IPV6:
175*bd1f8aebSAndroid Build Coastguard Worker switch(cmsg->cmsg_type) {
176*bd1f8aebSAndroid Build Coastguard Worker case IPV6_RECVERR:
177*bd1f8aebSAndroid Build Coastguard Worker e = (struct sock_extended_err *)CMSG_DATA(cmsg);
178*bd1f8aebSAndroid Build Coastguard Worker break;
179*bd1f8aebSAndroid Build Coastguard Worker case IPV6_HOPLIMIT:
180*bd1f8aebSAndroid Build Coastguard Worker #ifdef IPV6_2292HOPLIMIT
181*bd1f8aebSAndroid Build Coastguard Worker case IPV6_2292HOPLIMIT:
182*bd1f8aebSAndroid Build Coastguard Worker #endif
183*bd1f8aebSAndroid Build Coastguard Worker memcpy(&rethops, CMSG_DATA(cmsg), sizeof(rethops));
184*bd1f8aebSAndroid Build Coastguard Worker break;
185*bd1f8aebSAndroid Build Coastguard Worker default:
186*bd1f8aebSAndroid Build Coastguard Worker printf("cmsg6:%d\n ", cmsg->cmsg_type);
187*bd1f8aebSAndroid Build Coastguard Worker }
188*bd1f8aebSAndroid Build Coastguard Worker break;
189*bd1f8aebSAndroid Build Coastguard Worker case SOL_IP:
190*bd1f8aebSAndroid Build Coastguard Worker switch(cmsg->cmsg_type) {
191*bd1f8aebSAndroid Build Coastguard Worker case IP_RECVERR:
192*bd1f8aebSAndroid Build Coastguard Worker e = (struct sock_extended_err *)CMSG_DATA(cmsg);
193*bd1f8aebSAndroid Build Coastguard Worker break;
194*bd1f8aebSAndroid Build Coastguard Worker case IP_TTL:
195*bd1f8aebSAndroid Build Coastguard Worker rethops = *(__u8*)CMSG_DATA(cmsg);
196*bd1f8aebSAndroid Build Coastguard Worker break;
197*bd1f8aebSAndroid Build Coastguard Worker default:
198*bd1f8aebSAndroid Build Coastguard Worker printf("cmsg4:%d\n ", cmsg->cmsg_type);
199*bd1f8aebSAndroid Build Coastguard Worker }
200*bd1f8aebSAndroid Build Coastguard Worker }
201*bd1f8aebSAndroid Build Coastguard Worker }
202*bd1f8aebSAndroid Build Coastguard Worker if (e == NULL) {
203*bd1f8aebSAndroid Build Coastguard Worker printf("no info\n");
204*bd1f8aebSAndroid Build Coastguard Worker return 0;
205*bd1f8aebSAndroid Build Coastguard Worker }
206*bd1f8aebSAndroid Build Coastguard Worker if (e->ee_origin == SO_EE_ORIGIN_LOCAL)
207*bd1f8aebSAndroid Build Coastguard Worker printf("%2d?: %-32s ", ttl, "[LOCALHOST]");
208*bd1f8aebSAndroid Build Coastguard Worker else if (e->ee_origin == SO_EE_ORIGIN_ICMP6 ||
209*bd1f8aebSAndroid Build Coastguard Worker e->ee_origin == SO_EE_ORIGIN_ICMP) {
210*bd1f8aebSAndroid Build Coastguard Worker char abuf[NI_MAXHOST], hbuf[NI_MAXHOST];
211*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr *sa = (struct sockaddr *)(e + 1);
212*bd1f8aebSAndroid Build Coastguard Worker socklen_t salen;
213*bd1f8aebSAndroid Build Coastguard Worker
214*bd1f8aebSAndroid Build Coastguard Worker if (sndhops>0)
215*bd1f8aebSAndroid Build Coastguard Worker printf("%2d: ", sndhops);
216*bd1f8aebSAndroid Build Coastguard Worker else
217*bd1f8aebSAndroid Build Coastguard Worker printf("%2d?: ", ttl);
218*bd1f8aebSAndroid Build Coastguard Worker
219*bd1f8aebSAndroid Build Coastguard Worker switch (sa->sa_family) {
220*bd1f8aebSAndroid Build Coastguard Worker case AF_INET6:
221*bd1f8aebSAndroid Build Coastguard Worker salen = sizeof(struct sockaddr_in6);
222*bd1f8aebSAndroid Build Coastguard Worker break;
223*bd1f8aebSAndroid Build Coastguard Worker case AF_INET:
224*bd1f8aebSAndroid Build Coastguard Worker salen = sizeof(struct sockaddr_in);
225*bd1f8aebSAndroid Build Coastguard Worker break;
226*bd1f8aebSAndroid Build Coastguard Worker default:
227*bd1f8aebSAndroid Build Coastguard Worker salen = 0;
228*bd1f8aebSAndroid Build Coastguard Worker }
229*bd1f8aebSAndroid Build Coastguard Worker
230*bd1f8aebSAndroid Build Coastguard Worker if (no_resolve || show_both) {
231*bd1f8aebSAndroid Build Coastguard Worker if (getnameinfo(sa, salen,
232*bd1f8aebSAndroid Build Coastguard Worker abuf, sizeof(abuf), NULL, 0,
233*bd1f8aebSAndroid Build Coastguard Worker NI_NUMERICHOST))
234*bd1f8aebSAndroid Build Coastguard Worker strcpy(abuf, "???");
235*bd1f8aebSAndroid Build Coastguard Worker } else
236*bd1f8aebSAndroid Build Coastguard Worker abuf[0] = 0;
237*bd1f8aebSAndroid Build Coastguard Worker
238*bd1f8aebSAndroid Build Coastguard Worker if (!no_resolve || show_both) {
239*bd1f8aebSAndroid Build Coastguard Worker fflush(stdout);
240*bd1f8aebSAndroid Build Coastguard Worker if (getnameinfo(sa, salen,
241*bd1f8aebSAndroid Build Coastguard Worker hbuf, sizeof(hbuf), NULL, 0,
242*bd1f8aebSAndroid Build Coastguard Worker 0
243*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
244*bd1f8aebSAndroid Build Coastguard Worker | NI_IDN
245*bd1f8aebSAndroid Build Coastguard Worker #endif
246*bd1f8aebSAndroid Build Coastguard Worker ))
247*bd1f8aebSAndroid Build Coastguard Worker strcpy(hbuf, "???");
248*bd1f8aebSAndroid Build Coastguard Worker } else
249*bd1f8aebSAndroid Build Coastguard Worker hbuf[0] = 0;
250*bd1f8aebSAndroid Build Coastguard Worker
251*bd1f8aebSAndroid Build Coastguard Worker if (no_resolve)
252*bd1f8aebSAndroid Build Coastguard Worker print_host(abuf, hbuf, show_both);
253*bd1f8aebSAndroid Build Coastguard Worker else
254*bd1f8aebSAndroid Build Coastguard Worker print_host(hbuf, abuf, show_both);
255*bd1f8aebSAndroid Build Coastguard Worker }
256*bd1f8aebSAndroid Build Coastguard Worker
257*bd1f8aebSAndroid Build Coastguard Worker if (rettv) {
258*bd1f8aebSAndroid Build Coastguard Worker int diff = (tv.tv_sec-rettv->tv_sec)*1000000+(tv.tv_usec-rettv->tv_usec);
259*bd1f8aebSAndroid Build Coastguard Worker printf("%3d.%03dms ", diff/1000, diff%1000);
260*bd1f8aebSAndroid Build Coastguard Worker if (broken_router)
261*bd1f8aebSAndroid Build Coastguard Worker printf("(This broken router returned corrupted payload) ");
262*bd1f8aebSAndroid Build Coastguard Worker }
263*bd1f8aebSAndroid Build Coastguard Worker
264*bd1f8aebSAndroid Build Coastguard Worker switch (e->ee_errno) {
265*bd1f8aebSAndroid Build Coastguard Worker case ETIMEDOUT:
266*bd1f8aebSAndroid Build Coastguard Worker printf("\n");
267*bd1f8aebSAndroid Build Coastguard Worker break;
268*bd1f8aebSAndroid Build Coastguard Worker case EMSGSIZE:
269*bd1f8aebSAndroid Build Coastguard Worker printf("pmtu %d\n", e->ee_info);
270*bd1f8aebSAndroid Build Coastguard Worker mtu = e->ee_info;
271*bd1f8aebSAndroid Build Coastguard Worker progress = mtu;
272*bd1f8aebSAndroid Build Coastguard Worker break;
273*bd1f8aebSAndroid Build Coastguard Worker case ECONNREFUSED:
274*bd1f8aebSAndroid Build Coastguard Worker printf("reached\n");
275*bd1f8aebSAndroid Build Coastguard Worker hops_to = sndhops<0 ? ttl : sndhops;
276*bd1f8aebSAndroid Build Coastguard Worker hops_from = rethops;
277*bd1f8aebSAndroid Build Coastguard Worker return 0;
278*bd1f8aebSAndroid Build Coastguard Worker case EPROTO:
279*bd1f8aebSAndroid Build Coastguard Worker printf("!P\n");
280*bd1f8aebSAndroid Build Coastguard Worker return 0;
281*bd1f8aebSAndroid Build Coastguard Worker case EHOSTUNREACH:
282*bd1f8aebSAndroid Build Coastguard Worker if ((e->ee_origin == SO_EE_ORIGIN_ICMP &&
283*bd1f8aebSAndroid Build Coastguard Worker e->ee_type == 11 &&
284*bd1f8aebSAndroid Build Coastguard Worker e->ee_code == 0) ||
285*bd1f8aebSAndroid Build Coastguard Worker (e->ee_origin == SO_EE_ORIGIN_ICMP6 &&
286*bd1f8aebSAndroid Build Coastguard Worker e->ee_type == 3 &&
287*bd1f8aebSAndroid Build Coastguard Worker e->ee_code == 0)) {
288*bd1f8aebSAndroid Build Coastguard Worker if (rethops>=0) {
289*bd1f8aebSAndroid Build Coastguard Worker if (rethops<=64)
290*bd1f8aebSAndroid Build Coastguard Worker rethops = 65-rethops;
291*bd1f8aebSAndroid Build Coastguard Worker else if (rethops<=128)
292*bd1f8aebSAndroid Build Coastguard Worker rethops = 129-rethops;
293*bd1f8aebSAndroid Build Coastguard Worker else
294*bd1f8aebSAndroid Build Coastguard Worker rethops = 256-rethops;
295*bd1f8aebSAndroid Build Coastguard Worker if (sndhops>=0 && rethops != sndhops)
296*bd1f8aebSAndroid Build Coastguard Worker printf("asymm %2d ", rethops);
297*bd1f8aebSAndroid Build Coastguard Worker else if (sndhops<0 && rethops != ttl)
298*bd1f8aebSAndroid Build Coastguard Worker printf("asymm %2d ", rethops);
299*bd1f8aebSAndroid Build Coastguard Worker }
300*bd1f8aebSAndroid Build Coastguard Worker printf("\n");
301*bd1f8aebSAndroid Build Coastguard Worker break;
302*bd1f8aebSAndroid Build Coastguard Worker }
303*bd1f8aebSAndroid Build Coastguard Worker printf("!H\n");
304*bd1f8aebSAndroid Build Coastguard Worker return 0;
305*bd1f8aebSAndroid Build Coastguard Worker case ENETUNREACH:
306*bd1f8aebSAndroid Build Coastguard Worker printf("!N\n");
307*bd1f8aebSAndroid Build Coastguard Worker return 0;
308*bd1f8aebSAndroid Build Coastguard Worker case EACCES:
309*bd1f8aebSAndroid Build Coastguard Worker printf("!A\n");
310*bd1f8aebSAndroid Build Coastguard Worker return 0;
311*bd1f8aebSAndroid Build Coastguard Worker default:
312*bd1f8aebSAndroid Build Coastguard Worker printf("\n");
313*bd1f8aebSAndroid Build Coastguard Worker errno = e->ee_errno;
314*bd1f8aebSAndroid Build Coastguard Worker perror("NET ERROR");
315*bd1f8aebSAndroid Build Coastguard Worker return 0;
316*bd1f8aebSAndroid Build Coastguard Worker }
317*bd1f8aebSAndroid Build Coastguard Worker goto restart;
318*bd1f8aebSAndroid Build Coastguard Worker }
319*bd1f8aebSAndroid Build Coastguard Worker
probe_ttl(int fd,int ttl)320*bd1f8aebSAndroid Build Coastguard Worker int probe_ttl(int fd, int ttl)
321*bd1f8aebSAndroid Build Coastguard Worker {
322*bd1f8aebSAndroid Build Coastguard Worker int i;
323*bd1f8aebSAndroid Build Coastguard Worker struct probehdr *hdr = pktbuf;
324*bd1f8aebSAndroid Build Coastguard Worker
325*bd1f8aebSAndroid Build Coastguard Worker memset(pktbuf, 0, mtu);
326*bd1f8aebSAndroid Build Coastguard Worker restart:
327*bd1f8aebSAndroid Build Coastguard Worker
328*bd1f8aebSAndroid Build Coastguard Worker for (i=0; i<10; i++) {
329*bd1f8aebSAndroid Build Coastguard Worker int res;
330*bd1f8aebSAndroid Build Coastguard Worker
331*bd1f8aebSAndroid Build Coastguard Worker hdr->ttl = ttl;
332*bd1f8aebSAndroid Build Coastguard Worker switch (family) {
333*bd1f8aebSAndroid Build Coastguard Worker case AF_INET6:
334*bd1f8aebSAndroid Build Coastguard Worker ((struct sockaddr_in6 *)&target)->sin6_port = htons(base_port + hisptr);
335*bd1f8aebSAndroid Build Coastguard Worker break;
336*bd1f8aebSAndroid Build Coastguard Worker case AF_INET:
337*bd1f8aebSAndroid Build Coastguard Worker ((struct sockaddr_in *)&target)->sin_port = htons(base_port + hisptr);
338*bd1f8aebSAndroid Build Coastguard Worker break;
339*bd1f8aebSAndroid Build Coastguard Worker }
340*bd1f8aebSAndroid Build Coastguard Worker gettimeofday(&hdr->tv, NULL);
341*bd1f8aebSAndroid Build Coastguard Worker his[hisptr].hops = ttl;
342*bd1f8aebSAndroid Build Coastguard Worker his[hisptr].sendtime = hdr->tv;
343*bd1f8aebSAndroid Build Coastguard Worker if (sendto(fd, pktbuf, mtu-overhead, 0, (struct sockaddr *)&target, targetlen) > 0)
344*bd1f8aebSAndroid Build Coastguard Worker break;
345*bd1f8aebSAndroid Build Coastguard Worker res = recverr(fd, ttl);
346*bd1f8aebSAndroid Build Coastguard Worker his[hisptr].hops = 0;
347*bd1f8aebSAndroid Build Coastguard Worker if (res==0)
348*bd1f8aebSAndroid Build Coastguard Worker return 0;
349*bd1f8aebSAndroid Build Coastguard Worker if (res > 0)
350*bd1f8aebSAndroid Build Coastguard Worker goto restart;
351*bd1f8aebSAndroid Build Coastguard Worker }
352*bd1f8aebSAndroid Build Coastguard Worker hisptr = (hisptr + 1) & 63;
353*bd1f8aebSAndroid Build Coastguard Worker
354*bd1f8aebSAndroid Build Coastguard Worker if (i<10) {
355*bd1f8aebSAndroid Build Coastguard Worker data_wait(fd);
356*bd1f8aebSAndroid Build Coastguard Worker if (recv(fd, pktbuf, mtu, MSG_DONTWAIT) > 0) {
357*bd1f8aebSAndroid Build Coastguard Worker printf("%2d?: reply received 8)\n", ttl);
358*bd1f8aebSAndroid Build Coastguard Worker return 0;
359*bd1f8aebSAndroid Build Coastguard Worker }
360*bd1f8aebSAndroid Build Coastguard Worker return recverr(fd, ttl);
361*bd1f8aebSAndroid Build Coastguard Worker }
362*bd1f8aebSAndroid Build Coastguard Worker
363*bd1f8aebSAndroid Build Coastguard Worker printf("%2d: send failed\n", ttl);
364*bd1f8aebSAndroid Build Coastguard Worker return 0;
365*bd1f8aebSAndroid Build Coastguard Worker }
366*bd1f8aebSAndroid Build Coastguard Worker
367*bd1f8aebSAndroid Build Coastguard Worker static void usage(void) __attribute((noreturn));
368*bd1f8aebSAndroid Build Coastguard Worker
usage(void)369*bd1f8aebSAndroid Build Coastguard Worker static void usage(void)
370*bd1f8aebSAndroid Build Coastguard Worker {
371*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "Usage: tracepath6 [-n] [-b] [-l <len>] [-p port] <destination>\n");
372*bd1f8aebSAndroid Build Coastguard Worker exit(-1);
373*bd1f8aebSAndroid Build Coastguard Worker }
374*bd1f8aebSAndroid Build Coastguard Worker
375*bd1f8aebSAndroid Build Coastguard Worker
main(int argc,char ** argv)376*bd1f8aebSAndroid Build Coastguard Worker int main(int argc, char **argv)
377*bd1f8aebSAndroid Build Coastguard Worker {
378*bd1f8aebSAndroid Build Coastguard Worker int fd;
379*bd1f8aebSAndroid Build Coastguard Worker int on;
380*bd1f8aebSAndroid Build Coastguard Worker int ttl;
381*bd1f8aebSAndroid Build Coastguard Worker char *p;
382*bd1f8aebSAndroid Build Coastguard Worker struct addrinfo hints, *ai, *ai0;
383*bd1f8aebSAndroid Build Coastguard Worker int ch;
384*bd1f8aebSAndroid Build Coastguard Worker int gai;
385*bd1f8aebSAndroid Build Coastguard Worker char pbuf[NI_MAXSERV];
386*bd1f8aebSAndroid Build Coastguard Worker
387*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
388*bd1f8aebSAndroid Build Coastguard Worker setlocale(LC_ALL, "");
389*bd1f8aebSAndroid Build Coastguard Worker #endif
390*bd1f8aebSAndroid Build Coastguard Worker
391*bd1f8aebSAndroid Build Coastguard Worker while ((ch = getopt(argc, argv, "nbh?l:m:p:")) != EOF) {
392*bd1f8aebSAndroid Build Coastguard Worker switch(ch) {
393*bd1f8aebSAndroid Build Coastguard Worker case 'n':
394*bd1f8aebSAndroid Build Coastguard Worker no_resolve = 1;
395*bd1f8aebSAndroid Build Coastguard Worker break;
396*bd1f8aebSAndroid Build Coastguard Worker case 'b':
397*bd1f8aebSAndroid Build Coastguard Worker show_both = 1;
398*bd1f8aebSAndroid Build Coastguard Worker break;
399*bd1f8aebSAndroid Build Coastguard Worker case 'l':
400*bd1f8aebSAndroid Build Coastguard Worker mtu = atoi(optarg);
401*bd1f8aebSAndroid Build Coastguard Worker break;
402*bd1f8aebSAndroid Build Coastguard Worker case 'm':
403*bd1f8aebSAndroid Build Coastguard Worker max_hops = atoi(optarg);
404*bd1f8aebSAndroid Build Coastguard Worker if (max_hops < 0 || max_hops > MAX_HOPS_LIMIT) {
405*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr,
406*bd1f8aebSAndroid Build Coastguard Worker "Error: max hops must be 0 .. %d (inclusive).\n",
407*bd1f8aebSAndroid Build Coastguard Worker MAX_HOPS_LIMIT);
408*bd1f8aebSAndroid Build Coastguard Worker }
409*bd1f8aebSAndroid Build Coastguard Worker break;
410*bd1f8aebSAndroid Build Coastguard Worker case 'p':
411*bd1f8aebSAndroid Build Coastguard Worker base_port = atoi(optarg);
412*bd1f8aebSAndroid Build Coastguard Worker break;
413*bd1f8aebSAndroid Build Coastguard Worker default:
414*bd1f8aebSAndroid Build Coastguard Worker usage();
415*bd1f8aebSAndroid Build Coastguard Worker }
416*bd1f8aebSAndroid Build Coastguard Worker }
417*bd1f8aebSAndroid Build Coastguard Worker
418*bd1f8aebSAndroid Build Coastguard Worker argc -= optind;
419*bd1f8aebSAndroid Build Coastguard Worker argv += optind;
420*bd1f8aebSAndroid Build Coastguard Worker
421*bd1f8aebSAndroid Build Coastguard Worker if (argc != 1)
422*bd1f8aebSAndroid Build Coastguard Worker usage();
423*bd1f8aebSAndroid Build Coastguard Worker
424*bd1f8aebSAndroid Build Coastguard Worker /* Backward compatiblity */
425*bd1f8aebSAndroid Build Coastguard Worker if (!base_port) {
426*bd1f8aebSAndroid Build Coastguard Worker p = strchr(argv[0], '/');
427*bd1f8aebSAndroid Build Coastguard Worker if (p) {
428*bd1f8aebSAndroid Build Coastguard Worker *p = 0;
429*bd1f8aebSAndroid Build Coastguard Worker base_port = (unsigned)atoi(p+1);
430*bd1f8aebSAndroid Build Coastguard Worker } else {
431*bd1f8aebSAndroid Build Coastguard Worker base_port = 44444;
432*bd1f8aebSAndroid Build Coastguard Worker }
433*bd1f8aebSAndroid Build Coastguard Worker }
434*bd1f8aebSAndroid Build Coastguard Worker sprintf(pbuf, "%u", base_port);
435*bd1f8aebSAndroid Build Coastguard Worker
436*bd1f8aebSAndroid Build Coastguard Worker memset(&hints, 0, sizeof(hints));
437*bd1f8aebSAndroid Build Coastguard Worker hints.ai_family = family;
438*bd1f8aebSAndroid Build Coastguard Worker hints.ai_socktype = SOCK_DGRAM;
439*bd1f8aebSAndroid Build Coastguard Worker hints.ai_protocol = IPPROTO_UDP;
440*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
441*bd1f8aebSAndroid Build Coastguard Worker hints.ai_flags = AI_IDN;
442*bd1f8aebSAndroid Build Coastguard Worker #endif
443*bd1f8aebSAndroid Build Coastguard Worker gai = getaddrinfo(argv[0], pbuf, &hints, &ai0);
444*bd1f8aebSAndroid Build Coastguard Worker if (gai) {
445*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai));
446*bd1f8aebSAndroid Build Coastguard Worker exit(1);
447*bd1f8aebSAndroid Build Coastguard Worker }
448*bd1f8aebSAndroid Build Coastguard Worker
449*bd1f8aebSAndroid Build Coastguard Worker fd = -1;
450*bd1f8aebSAndroid Build Coastguard Worker for (ai = ai0; ai; ai = ai->ai_next) {
451*bd1f8aebSAndroid Build Coastguard Worker /* sanity check */
452*bd1f8aebSAndroid Build Coastguard Worker if (family && ai->ai_family != family)
453*bd1f8aebSAndroid Build Coastguard Worker continue;
454*bd1f8aebSAndroid Build Coastguard Worker if (ai->ai_family != AF_INET6 &&
455*bd1f8aebSAndroid Build Coastguard Worker ai->ai_family != AF_INET)
456*bd1f8aebSAndroid Build Coastguard Worker continue;
457*bd1f8aebSAndroid Build Coastguard Worker family = ai->ai_family;
458*bd1f8aebSAndroid Build Coastguard Worker fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
459*bd1f8aebSAndroid Build Coastguard Worker if (fd < 0)
460*bd1f8aebSAndroid Build Coastguard Worker continue;
461*bd1f8aebSAndroid Build Coastguard Worker memcpy(&target, ai->ai_addr, sizeof(target));
462*bd1f8aebSAndroid Build Coastguard Worker targetlen = ai->ai_addrlen;
463*bd1f8aebSAndroid Build Coastguard Worker break;
464*bd1f8aebSAndroid Build Coastguard Worker }
465*bd1f8aebSAndroid Build Coastguard Worker if (fd < 0) {
466*bd1f8aebSAndroid Build Coastguard Worker perror("socket/connect");
467*bd1f8aebSAndroid Build Coastguard Worker exit(1);
468*bd1f8aebSAndroid Build Coastguard Worker }
469*bd1f8aebSAndroid Build Coastguard Worker freeaddrinfo(ai0);
470*bd1f8aebSAndroid Build Coastguard Worker
471*bd1f8aebSAndroid Build Coastguard Worker switch (family) {
472*bd1f8aebSAndroid Build Coastguard Worker case AF_INET6:
473*bd1f8aebSAndroid Build Coastguard Worker overhead = 48;
474*bd1f8aebSAndroid Build Coastguard Worker if (!mtu)
475*bd1f8aebSAndroid Build Coastguard Worker mtu = 128000;
476*bd1f8aebSAndroid Build Coastguard Worker if (mtu <= overhead)
477*bd1f8aebSAndroid Build Coastguard Worker goto pktlen_error;
478*bd1f8aebSAndroid Build Coastguard Worker
479*bd1f8aebSAndroid Build Coastguard Worker on = IPV6_PMTUDISC_DO;
480*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)) &&
481*bd1f8aebSAndroid Build Coastguard Worker (on = IPV6_PMTUDISC_DO,
482*bd1f8aebSAndroid Build Coastguard Worker setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on)))) {
483*bd1f8aebSAndroid Build Coastguard Worker perror("IPV6_MTU_DISCOVER");
484*bd1f8aebSAndroid Build Coastguard Worker exit(1);
485*bd1f8aebSAndroid Build Coastguard Worker }
486*bd1f8aebSAndroid Build Coastguard Worker on = 1;
487*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_IPV6, IPV6_RECVERR, &on, sizeof(on))) {
488*bd1f8aebSAndroid Build Coastguard Worker perror("IPV6_RECVERR");
489*bd1f8aebSAndroid Build Coastguard Worker exit(1);
490*bd1f8aebSAndroid Build Coastguard Worker }
491*bd1f8aebSAndroid Build Coastguard Worker if (
492*bd1f8aebSAndroid Build Coastguard Worker #ifdef IPV6_RECVHOPLIMIT
493*bd1f8aebSAndroid Build Coastguard Worker setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)) &&
494*bd1f8aebSAndroid Build Coastguard Worker setsockopt(fd, SOL_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on))
495*bd1f8aebSAndroid Build Coastguard Worker #else
496*bd1f8aebSAndroid Build Coastguard Worker setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on))
497*bd1f8aebSAndroid Build Coastguard Worker #endif
498*bd1f8aebSAndroid Build Coastguard Worker ) {
499*bd1f8aebSAndroid Build Coastguard Worker perror("IPV6_HOPLIMIT");
500*bd1f8aebSAndroid Build Coastguard Worker exit(1);
501*bd1f8aebSAndroid Build Coastguard Worker }
502*bd1f8aebSAndroid Build Coastguard Worker if (!IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *)&target)->sin6_addr)))
503*bd1f8aebSAndroid Build Coastguard Worker break;
504*bd1f8aebSAndroid Build Coastguard Worker mapped = 1;
505*bd1f8aebSAndroid Build Coastguard Worker /*FALLTHROUGH*/
506*bd1f8aebSAndroid Build Coastguard Worker case AF_INET:
507*bd1f8aebSAndroid Build Coastguard Worker overhead = 28;
508*bd1f8aebSAndroid Build Coastguard Worker if (!mtu)
509*bd1f8aebSAndroid Build Coastguard Worker mtu = 65535;
510*bd1f8aebSAndroid Build Coastguard Worker if (mtu <= overhead)
511*bd1f8aebSAndroid Build Coastguard Worker goto pktlen_error;
512*bd1f8aebSAndroid Build Coastguard Worker
513*bd1f8aebSAndroid Build Coastguard Worker on = IP_PMTUDISC_DO;
514*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on))) {
515*bd1f8aebSAndroid Build Coastguard Worker perror("IP_MTU_DISCOVER");
516*bd1f8aebSAndroid Build Coastguard Worker exit(1);
517*bd1f8aebSAndroid Build Coastguard Worker }
518*bd1f8aebSAndroid Build Coastguard Worker on = 1;
519*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) {
520*bd1f8aebSAndroid Build Coastguard Worker perror("IP_RECVERR");
521*bd1f8aebSAndroid Build Coastguard Worker exit(1);
522*bd1f8aebSAndroid Build Coastguard Worker }
523*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) {
524*bd1f8aebSAndroid Build Coastguard Worker perror("IP_RECVTTL");
525*bd1f8aebSAndroid Build Coastguard Worker exit(1);
526*bd1f8aebSAndroid Build Coastguard Worker }
527*bd1f8aebSAndroid Build Coastguard Worker }
528*bd1f8aebSAndroid Build Coastguard Worker
529*bd1f8aebSAndroid Build Coastguard Worker pktbuf = malloc(mtu);
530*bd1f8aebSAndroid Build Coastguard Worker if (!pktbuf) {
531*bd1f8aebSAndroid Build Coastguard Worker perror("malloc");
532*bd1f8aebSAndroid Build Coastguard Worker exit(1);
533*bd1f8aebSAndroid Build Coastguard Worker }
534*bd1f8aebSAndroid Build Coastguard Worker
535*bd1f8aebSAndroid Build Coastguard Worker for (ttl = 1; ttl <= max_hops; ttl++) {
536*bd1f8aebSAndroid Build Coastguard Worker int res;
537*bd1f8aebSAndroid Build Coastguard Worker int i;
538*bd1f8aebSAndroid Build Coastguard Worker
539*bd1f8aebSAndroid Build Coastguard Worker on = ttl;
540*bd1f8aebSAndroid Build Coastguard Worker switch (family) {
541*bd1f8aebSAndroid Build Coastguard Worker case AF_INET6:
542*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &on, sizeof(on))) {
543*bd1f8aebSAndroid Build Coastguard Worker perror("IPV6_UNICAST_HOPS");
544*bd1f8aebSAndroid Build Coastguard Worker exit(1);
545*bd1f8aebSAndroid Build Coastguard Worker }
546*bd1f8aebSAndroid Build Coastguard Worker if (!mapped)
547*bd1f8aebSAndroid Build Coastguard Worker break;
548*bd1f8aebSAndroid Build Coastguard Worker /*FALLTHROUGH*/
549*bd1f8aebSAndroid Build Coastguard Worker case AF_INET:
550*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) {
551*bd1f8aebSAndroid Build Coastguard Worker perror("IP_TTL");
552*bd1f8aebSAndroid Build Coastguard Worker exit(1);
553*bd1f8aebSAndroid Build Coastguard Worker }
554*bd1f8aebSAndroid Build Coastguard Worker }
555*bd1f8aebSAndroid Build Coastguard Worker
556*bd1f8aebSAndroid Build Coastguard Worker restart:
557*bd1f8aebSAndroid Build Coastguard Worker for (i=0; i<3; i++) {
558*bd1f8aebSAndroid Build Coastguard Worker int old_mtu;
559*bd1f8aebSAndroid Build Coastguard Worker
560*bd1f8aebSAndroid Build Coastguard Worker old_mtu = mtu;
561*bd1f8aebSAndroid Build Coastguard Worker res = probe_ttl(fd, ttl);
562*bd1f8aebSAndroid Build Coastguard Worker if (mtu != old_mtu)
563*bd1f8aebSAndroid Build Coastguard Worker goto restart;
564*bd1f8aebSAndroid Build Coastguard Worker if (res == 0)
565*bd1f8aebSAndroid Build Coastguard Worker goto done;
566*bd1f8aebSAndroid Build Coastguard Worker if (res > 0)
567*bd1f8aebSAndroid Build Coastguard Worker break;
568*bd1f8aebSAndroid Build Coastguard Worker }
569*bd1f8aebSAndroid Build Coastguard Worker
570*bd1f8aebSAndroid Build Coastguard Worker if (res < 0)
571*bd1f8aebSAndroid Build Coastguard Worker printf("%2d: no reply\n", ttl);
572*bd1f8aebSAndroid Build Coastguard Worker }
573*bd1f8aebSAndroid Build Coastguard Worker printf(" Too many hops: pmtu %d\n", mtu);
574*bd1f8aebSAndroid Build Coastguard Worker
575*bd1f8aebSAndroid Build Coastguard Worker done:
576*bd1f8aebSAndroid Build Coastguard Worker printf(" Resume: pmtu %d ", mtu);
577*bd1f8aebSAndroid Build Coastguard Worker if (hops_to>=0)
578*bd1f8aebSAndroid Build Coastguard Worker printf("hops %d ", hops_to);
579*bd1f8aebSAndroid Build Coastguard Worker if (hops_from>=0)
580*bd1f8aebSAndroid Build Coastguard Worker printf("back %d ", hops_from);
581*bd1f8aebSAndroid Build Coastguard Worker printf("\n");
582*bd1f8aebSAndroid Build Coastguard Worker exit(0);
583*bd1f8aebSAndroid Build Coastguard Worker
584*bd1f8aebSAndroid Build Coastguard Worker pktlen_error:
585*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "Error: pktlen must be > %d and <= %d\n",
586*bd1f8aebSAndroid Build Coastguard Worker overhead, INT_MAX);
587*bd1f8aebSAndroid Build Coastguard Worker exit(1);
588*bd1f8aebSAndroid Build Coastguard Worker }
589