traceroute.c 21 KB

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