1 /* $NetBSD: traceroute.c,v 1.46 2002/05/26 14:45:43 itojun Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24 #include <sys/cdefs.h> 25 #ifndef lint 26 #if 0 27 static const char rcsid[] = 28 "@(#)Header: traceroute.c,v 1.49 97/06/13 02:30:23 leres Exp (LBL)"; 29 #else 30 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997\n\ 31 The Regents of the University of California. All rights reserved.\n"); 32 __RCSID("$NetBSD: traceroute.c,v 1.46 2002/05/26 14:45:43 itojun Exp $"); 33 #endif 34 #endif 35 36 /* 37 * traceroute host - trace the route ip packets follow going to "host". 38 * 39 * Attempt to trace the route an ip packet would follow to some 40 * internet host. We find out intermediate hops by launching probe 41 * packets with a small ttl (time to live) then listening for an 42 * icmp "time exceeded" reply from a gateway. We start our probes 43 * with a ttl of one and increase by one until we get an icmp "port 44 * unreachable" (which means we got to "host") or hit a max (which 45 * defaults to 30 hops & can be changed with the -m flag). Three 46 * probes (change with -q flag) are sent at each ttl setting and a 47 * line is printed showing the ttl, address of the gateway and 48 * round trip time of each probe. If the probe answers come from 49 * different gateways, the address of each responding system will 50 * be printed. If there is no response within a 5 sec. timeout 51 * interval (changed with the -w flag), a "*" is printed for that 52 * probe. 53 * 54 * Probe packets are UDP format. We don't want the destination 55 * host to process them so the destination port is set to an 56 * unlikely value (if some clod on the destination is using that 57 * value, it can be changed with the -p flag). 58 * 59 * A sample use might be: 60 * 61 * [yak 71]% traceroute nis.nsf.net. 62 * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet 63 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms 64 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 65 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 66 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms 67 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms 68 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms 69 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms 70 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms 71 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms 72 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms 73 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms 74 * 75 * Note that lines 2 & 3 are the same. This is due to a buggy 76 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards 77 * packets with a zero ttl. 78 * 79 * A more interesting example is: 80 * 81 * [yak 72]% traceroute allspice.lcs.mit.edu. 82 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max 83 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 84 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms 85 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms 86 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms 87 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms 88 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms 89 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms 90 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms 91 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms 92 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms 93 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms 94 * 12 * * * 95 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms 96 * 14 * * * 97 * 15 * * * 98 * 16 * * * 99 * 17 * * * 100 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms 101 * 102 * (I start to see why I'm having so much trouble with mail to 103 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away 104 * either don't send ICMP "time exceeded" messages or send them 105 * with a ttl too small to reach us. 14 - 17 are running the 106 * MIT C Gateway code that doesn't send "time exceeded"s. God 107 * only knows what's going on with 12. 108 * 109 * The silent gateway 12 in the above may be the result of a bug in 110 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) 111 * sends an unreachable message using whatever ttl remains in the 112 * original datagram. Since, for gateways, the remaining ttl is 113 * zero, the icmp "time exceeded" is guaranteed to not make it back 114 * to us. The behavior of this bug is slightly more interesting 115 * when it appears on the destination system: 116 * 117 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 118 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms 119 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms 120 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms 121 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms 122 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms 123 * 7 * * * 124 * 8 * * * 125 * 9 * * * 126 * 10 * * * 127 * 11 * * * 128 * 12 * * * 129 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! 130 * 131 * Notice that there are 12 "gateways" (13 is the final 132 * destination) and exactly the last half of them are "missing". 133 * What's really happening is that rip (a Sun-3 running Sun OS3.5) 134 * is using the ttl from our arriving datagram as the ttl in its 135 * icmp reply. So, the reply will time out on the return path 136 * (with no notice sent to anyone since icmp's aren't sent for 137 * icmp's) until we probe with a ttl that's at least twice the path 138 * length. I.e., rip is really only 7 hops away. A reply that 139 * returns with a ttl of 1 is a clue this problem exists. 140 * Traceroute prints a "!" after the time if the ttl is <= 1. 141 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or 142 * non-standard (HPUX) software, expect to see this problem 143 * frequently and/or take care picking the target host of your 144 * probes. 145 * 146 * Other possible annotations after the time are !H, !N, !P (got a host, 147 * network or protocol unreachable, respectively), !S or !F (source 148 * route failed or fragmentation needed -- neither of these should 149 * ever occur and the associated gateway is busted if you see one). If 150 * almost all the probes result in some kind of unreachable, traceroute 151 * will give up and exit. 152 * 153 * Notes 154 * ----- 155 * This program must be run by root or be setuid. (I suggest that 156 * you *don't* make it setuid -- casual use could result in a lot 157 * of unnecessary traffic on our poor, congested nets.) 158 * 159 * This program requires a kernel mod that does not appear in any 160 * system available from Berkeley: A raw ip socket using proto 161 * IPPROTO_RAW must interpret the data sent as an ip datagram (as 162 * opposed to data to be wrapped in a ip datagram). See the README 163 * file that came with the source to this program for a description 164 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may 165 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE 166 * MODIFIED TO RUN THIS PROGRAM. 167 * 168 * The udp port usage may appear bizarre (well, ok, it is bizarre). 169 * The problem is that an icmp message only contains 8 bytes of 170 * data from the original datagram. 8 bytes is the size of a udp 171 * header so, if we want to associate replies with the original 172 * datagram, the necessary information must be encoded into the 173 * udp header (the ip id could be used but there's no way to 174 * interlock with the kernel's assignment of ip id's and, anyway, 175 * it would have taken a lot more kernel hacking to allow this 176 * code to set the ip id). So, to allow two or more users to 177 * use traceroute simultaneously, we use this task's pid as the 178 * source port (the high bit is set to move the port number out 179 * of the "likely" range). To keep track of which probe is being 180 * replied to (so times and/or hop counts don't get confused by a 181 * reply that was delayed in transit), we increment the destination 182 * port number before each probe. 183 * 184 * Don't use this as a coding example. I was trying to find a 185 * routing problem and this code sort-of popped out after 48 hours 186 * without sleep. I was amazed it ever compiled, much less ran. 187 * 188 * I stole the idea for this program from Steve Deering. Since 189 * the first release, I've learned that had I attended the right 190 * IETF working group meetings, I also could have stolen it from Guy 191 * Almes or Matt Mathis. I don't know (or care) who came up with 192 * the idea first. I envy the originators' perspicacity and I'm 193 * glad they didn't keep the idea a secret. 194 * 195 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or 196 * enhancements to the original distribution. 197 * 198 * I've hacked up a round-trip-route version of this that works by 199 * sending a loose-source-routed udp datagram through the destination 200 * back to yourself. Unfortunately, SO many gateways botch source 201 * routing, the thing is almost worthless. Maybe one day... 202 * 203 * -- Van Jacobson (van@ee.lbl.gov) 204 * Tue Dec 20 03:50:13 PST 1988 205 */ 206 207 #include <sys/param.h> 208 #include <sys/file.h> 209 #include <sys/ioctl.h> 210 #ifdef HAVE_SYS_SELECT_H 211 #include <sys/select.h> 212 #endif 213 #include <sys/socket.h> 214 #include <sys/time.h> 215 #include <sys/sysctl.h> 216 217 #include <netinet/in_systm.h> 218 #include <netinet/in.h> 219 #include <netinet/ip.h> 220 #include <netinet/ip_var.h> 221 #include <netinet/ip_icmp.h> 222 #include <netinet/udp.h> 223 #include <netinet/udp_var.h> 224 225 #include <arpa/inet.h> 226 227 #include <ctype.h> 228 #include <errno.h> 229 #ifdef HAVE_MALLOC_H 230 #include <malloc.h> 231 #endif 232 #include <memory.h> 233 #include <netdb.h> 234 #include <stdio.h> 235 #include <stdlib.h> 236 #include <string.h> 237 #include <unistd.h> 238 #ifdef IPSEC 239 #include <net/route.h> 240 #include <netinet6/ipsec.h> 241 #endif 242 243 #include "gnuc.h" 244 #ifdef HAVE_OS_PROTO_H 245 #include "os-proto.h" 246 #endif 247 248 #include "ifaddrlist.h" 249 #include "savestr.h" 250 #include "as.h" 251 252 /* Maximum number of gateways (include room for one noop) */ 253 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t))) 254 255 #ifndef MAXHOSTNAMELEN 256 #define MAXHOSTNAMELEN 64 257 #endif 258 259 #define Fprintf (void)fprintf 260 #define Printf (void)printf 261 262 /* Host name and address list */ 263 struct hostinfo { 264 char *name; 265 int n; 266 u_int32_t *addrs; 267 }; 268 269 /* Data section of the probe packet */ 270 struct outdata { 271 u_char seq; /* sequence number of this packet */ 272 u_char ttl; /* ttl packet left with */ 273 struct timeval tv; /* time packet left */ 274 }; 275 276 u_char packet[512]; /* last inbound (icmp) packet */ 277 278 struct ip *outip; /* last output (udp) packet */ 279 struct udphdr *outudp; /* last output (udp) packet */ 280 void *outmark; /* packed location of struct outdata */ 281 struct outdata outsetup; /* setup and copy for alignment */ 282 283 struct icmp *outicmp; /* last output (icmp) packet */ 284 285 /* loose source route gateway list (including room for final destination) */ 286 u_int32_t gwlist[NGATEWAYS + 1]; 287 288 int s; /* receive (icmp) socket file descriptor */ 289 int sndsock; /* send (udp/icmp) socket file descriptor */ 290 291 struct sockaddr whereto; /* Who to try to reach */ 292 struct sockaddr_in wherefrom; /* Who we are */ 293 int packlen; /* total length of packet */ 294 int minpacket; /* min ip packet size */ 295 int maxpacket = 32 * 1024; /* max ip packet size */ 296 int printed_ttl = 0; 297 298 char *prog; 299 char *source; 300 char *hostname; 301 char *device; 302 303 int nprobes = 3; 304 int max_ttl = 30; 305 int first_ttl = 1; 306 u_short ident; 307 u_short port = 32768 + 666; /* start udp dest port # for probe packets */ 308 309 int options; /* socket options */ 310 int verbose; 311 int waittime = 5; /* time to wait for response (in seconds) */ 312 int nflag; /* print addresses numerically */ 313 int dump; 314 int as_path; /* print as numbers for each hop */ 315 char *as_server = NULL; 316 void *asn; 317 int useicmp; /* use icmp echo instead of udp packets */ 318 #ifdef CANT_HACK_CKSUM 319 int docksum = 0; /* don't calculate checksums */ 320 #else 321 int docksum = 1; /* calculate checksums */ 322 #endif 323 int optlen; /* length of ip options */ 324 325 int mtus[] = { 326 17914, 327 8166, 328 4464, 329 4352, 330 2048, 331 2002, 332 1536, 333 1500, 334 1492, 335 1480, 336 1280, 337 1006, 338 576, 339 552, 340 544, 341 512, 342 508, 343 296, 344 68, 345 0 346 }; 347 int *mtuptr = &mtus[0]; 348 int mtudisc = 0; 349 int nextmtu; /* from ICMP error, set by packet_ok(), might be 0 */ 350 351 extern int optind; 352 extern int opterr; 353 extern char *optarg; 354 355 /* Forwards */ 356 double deltaT(struct timeval *, struct timeval *); 357 void freehostinfo(struct hostinfo *); 358 void getaddr(u_int32_t *, char *); 359 struct hostinfo *gethostinfo(char *); 360 u_short in_cksum(u_short *, int); 361 u_short in_cksum2(u_short, u_short *, int); 362 char *inetname(struct in_addr); 363 int main(int, char **); 364 int packet_ok(u_char *, int, struct sockaddr_in *, int); 365 char *pr_type(u_char); 366 void print(u_char *, int, struct sockaddr_in *); 367 void resize_packet(void); 368 void dump_packet(void); 369 void send_probe(int, int, struct timeval *); 370 void setsin(struct sockaddr_in *, u_int32_t); 371 int str2val(const char *, const char *, int, int); 372 void tvsub(struct timeval *, struct timeval *); 373 __dead void usage(void); 374 int wait_for_reply(int, struct sockaddr_in *, struct timeval *); 375 void frag_err(void); 376 int find_local_ip(struct sockaddr_in *, struct sockaddr_in *); 377 #ifdef IPSEC 378 #ifdef IPSEC_POLICY_IPSEC 379 int setpolicy(int so, char *policy); 380 #endif 381 #endif 382 383 int 384 main(int argc, char **argv) 385 { 386 register int op, code, n; 387 register char *cp; 388 register u_char *outp; 389 register u_int32_t *ap; 390 register struct sockaddr_in *from = &wherefrom; 391 register struct sockaddr_in *to = (struct sockaddr_in *)&whereto; 392 register struct hostinfo *hi; 393 int on = 1; 394 register struct protoent *pe; 395 register int ttl, probe, i; 396 register int seq = 0; 397 int tos = 0, settos = 0, ttl_flag = 0; 398 register int lsrr = 0; 399 register u_short off = 0; 400 struct ifaddrlist *al, *al2; 401 char errbuf[132]; 402 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; 403 size_t size = sizeof(max_ttl); 404 405 (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size, 406 NULL, 0); 407 408 if ((cp = strrchr(argv[0], '/')) != NULL) 409 prog = cp + 1; 410 else 411 prog = argv[0]; 412 413 opterr = 0; 414 while ((op = getopt(argc, argv, "aA:dDFPInlrvxf:g:i:m:p:q:s:t:w:")) != -1) 415 switch (op) { 416 417 case 'a': 418 as_path = 1; 419 break; 420 421 case 'A': 422 as_path = 1; 423 as_server = optarg; 424 break; 425 426 case 'd': 427 options |= SO_DEBUG; 428 break; 429 430 case 'D': 431 dump = 1; 432 break; 433 434 case 'f': 435 first_ttl = str2val(optarg, "first ttl", 1, 255); 436 break; 437 438 case 'F': 439 off = IP_DF; 440 break; 441 442 case 'g': 443 if (lsrr >= NGATEWAYS) { 444 Fprintf(stderr, 445 "%s: No more than %d gateways\n", 446 prog, NGATEWAYS); 447 exit(1); 448 } 449 getaddr(gwlist + lsrr, optarg); 450 ++lsrr; 451 break; 452 453 case 'i': 454 device = optarg; 455 break; 456 457 case 'I': 458 ++useicmp; 459 break; 460 461 case 'l': 462 ++ttl_flag; 463 break; 464 465 case 'm': 466 max_ttl = str2val(optarg, "max ttl", 1, 255); 467 break; 468 469 case 'n': 470 ++nflag; 471 break; 472 473 case 'p': 474 port = str2val(optarg, "port", 1, -1); 475 break; 476 477 case 'q': 478 nprobes = str2val(optarg, "nprobes", 1, -1); 479 break; 480 481 case 'r': 482 options |= SO_DONTROUTE; 483 break; 484 485 case 's': 486 /* 487 * set the ip source address of the outbound 488 * probe (e.g., on a multi-homed host). 489 */ 490 source = optarg; 491 break; 492 493 case 't': 494 tos = str2val(optarg, "tos", 0, 255); 495 ++settos; 496 break; 497 498 case 'v': 499 ++verbose; 500 break; 501 502 case 'x': 503 docksum = (docksum == 0); 504 break; 505 506 case 'w': 507 waittime = str2val(optarg, "wait time", 2, 24 * 3600); 508 break; 509 510 case 'P': 511 off = IP_DF; 512 mtudisc = 1; 513 break; 514 515 default: 516 usage(); 517 } 518 519 if (first_ttl > max_ttl) { 520 Fprintf(stderr, 521 "%s: first ttl (%d) may not be greater than max ttl (%d)\n", 522 prog, first_ttl, max_ttl); 523 exit(1); 524 } 525 526 if (!docksum) 527 Fprintf(stderr, "%s: Warning: ckecksums disabled\n", prog); 528 529 if (lsrr > 0) 530 optlen = (lsrr + 1) * sizeof(gwlist[0]); 531 minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen; 532 if (useicmp) 533 minpacket += 8; /* XXX magic number */ 534 else 535 minpacket += sizeof(*outudp); 536 if (packlen == 0) 537 packlen = minpacket; /* minimum sized packet */ 538 else if (minpacket > packlen || packlen > maxpacket) { 539 Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n", 540 prog, minpacket, maxpacket); 541 exit(1); 542 } 543 544 if (mtudisc) 545 packlen = *mtuptr++; 546 547 /* Process destination and optional packet size */ 548 switch (argc - optind) { 549 550 case 2: 551 packlen = str2val(argv[optind + 1], 552 "packet length", minpacket, -1); 553 /* Fall through */ 554 555 case 1: 556 hostname = argv[optind]; 557 hi = gethostinfo(hostname); 558 setsin(to, hi->addrs[0]); 559 if (hi->n > 1) 560 Fprintf(stderr, 561 "%s: Warning: %s has multiple addresses; using %s\n", 562 prog, hostname, inet_ntoa(to->sin_addr)); 563 hostname = hi->name; 564 hi->name = NULL; 565 freehostinfo(hi); 566 break; 567 568 default: 569 usage(); 570 } 571 572 #ifdef HAVE_SETLINEBUF 573 setlinebuf (stdout); 574 #else 575 setvbuf(stdout, NULL, _IOLBF, 0); 576 #endif 577 578 outip = (struct ip *)malloc((unsigned)packlen); 579 if (outip == NULL) { 580 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno)); 581 exit(1); 582 } 583 memset((char *)outip, 0, packlen); 584 585 outip->ip_v = IPVERSION; 586 if (settos) 587 outip->ip_tos = tos; 588 #ifdef BYTESWAP_IP_LEN 589 outip->ip_len = htons(packlen); 590 #else 591 outip->ip_len = packlen; 592 #endif 593 outip->ip_off = off; 594 outp = (u_char *)(outip + 1); 595 #ifdef HAVE_RAW_OPTIONS 596 if (lsrr > 0) { 597 register u_char *optlist; 598 599 optlist = outp; 600 outp += optlen; 601 602 /* final hop */ 603 gwlist[lsrr] = to->sin_addr.s_addr; 604 605 outip->ip_dst.s_addr = gwlist[0]; 606 607 /* force 4 byte alignment */ 608 optlist[0] = IPOPT_NOP; 609 /* loose source route option */ 610 optlist[1] = IPOPT_LSRR; 611 i = lsrr * sizeof(gwlist[0]); 612 optlist[2] = i + 3; 613 /* Pointer to LSRR addresses */ 614 optlist[3] = IPOPT_MINOFF; 615 memcpy(optlist + 4, gwlist + 1, i); 616 } else 617 #endif 618 outip->ip_dst = to->sin_addr; 619 620 outip->ip_hl = (outp - (u_char *)outip) >> 2; 621 ident = (getpid() & 0xffff) | 0x8000; 622 if (useicmp) { 623 outip->ip_p = IPPROTO_ICMP; 624 625 outicmp = (struct icmp *)outp; 626 outicmp->icmp_type = ICMP_ECHO; 627 outicmp->icmp_id = htons(ident); 628 629 outmark = outp + 8; /* XXX magic number */ 630 } else { 631 outip->ip_p = IPPROTO_UDP; 632 633 outudp = (struct udphdr *)outp; 634 outudp->uh_sport = htons(ident); 635 outudp->uh_ulen = 636 htons((u_short)(packlen - (sizeof(*outip) + optlen))); 637 outmark = outudp + 1; 638 } 639 640 cp = "icmp"; 641 if ((pe = getprotobyname(cp)) == NULL) { 642 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 643 exit(1); 644 } 645 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) { 646 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno)); 647 exit(1); 648 } 649 if (options & SO_DEBUG) 650 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, 651 sizeof(on)); 652 if (options & SO_DONTROUTE) 653 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 654 sizeof(on)); 655 #ifdef IPSEC 656 #ifdef IPSEC_POLICY_IPSEC 657 /* 658 * do not raise error even if setsockopt fails, kernel may have ipsec 659 * turned off. 660 */ 661 if (setpolicy(s, "in bypass") < 0) 662 exit(1); 663 if (setpolicy(s, "out bypass") < 0) 664 exit(1); 665 #else 666 { 667 int level = IPSEC_LEVEL_AVAIL; 668 669 (void)setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level, 670 sizeof(level)); 671 (void)setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level, 672 sizeof(level)); 673 #ifdef IP_AUTH_TRANS_LEVEL 674 (void)setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level, 675 sizeof(level)); 676 #else 677 (void)setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level, 678 sizeof(level)); 679 #endif 680 #ifdef IP_AUTH_NETWORK_LEVEL 681 (void)setsockopt(s, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level, 682 sizeof(level)); 683 #endif 684 } 685 #endif /*IPSEC_POLICY_IPSEC*/ 686 #endif /*IPSEC*/ 687 688 #ifndef __hpux 689 sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 690 #else 691 sndsock = socket(AF_INET, SOCK_RAW, 692 useicmp ? IPPROTO_ICMP : IPPROTO_UDP); 693 #endif 694 if (sndsock < 0) { 695 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno)); 696 exit(1); 697 } 698 699 #ifdef IPSEC 700 #ifdef IPSEC_POLICY_IPSEC 701 /* 702 * do not raise error even if setsockopt fails, kernel may have ipsec 703 * turned off. 704 */ 705 if (setpolicy(sndsock, "in bypass") < 0) 706 exit(1); 707 if (setpolicy(sndsock, "out bypass") < 0) 708 exit(1); 709 #else 710 { 711 int level = IPSEC_LEVEL_BYPASS; 712 713 (void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level, 714 sizeof(level)); 715 (void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level, 716 sizeof(level)); 717 #ifdef IP_AUTH_TRANS_LEVEL 718 (void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level, 719 sizeof(level)); 720 #else 721 (void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level, 722 sizeof(level)); 723 #endif 724 #ifdef IP_AUTH_NETWORK_LEVEL 725 (void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level, 726 sizeof(level)); 727 #endif 728 } 729 #endif /*IPSEC_POLICY_IPSEC*/ 730 #endif /*IPSEC*/ 731 732 /* Revert to non-privileged user after opening sockets */ 733 setuid(getuid()); 734 735 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS) 736 if (lsrr > 0) { 737 u_char optlist[MAX_IPOPTLEN]; 738 739 cp = "ip"; 740 if ((pe = getprotobyname(cp)) == NULL) { 741 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 742 exit(1); 743 } 744 745 /* final hop */ 746 gwlist[lsrr] = to->sin_addr.s_addr; 747 ++lsrr; 748 749 /* force 4 byte alignment */ 750 optlist[0] = IPOPT_NOP; 751 /* loose source route option */ 752 optlist[1] = IPOPT_LSRR; 753 i = lsrr * sizeof(gwlist[0]); 754 optlist[2] = i + 3; 755 /* Pointer to LSRR addresses */ 756 optlist[3] = IPOPT_MINOFF; 757 memcpy(optlist + 4, gwlist, i); 758 759 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist, 760 i + sizeof(gwlist[0]))) < 0) { 761 Fprintf(stderr, "%s: IP_OPTIONS: %s\n", 762 prog, strerror(errno)); 763 exit(1); 764 } 765 } 766 #endif 767 768 #ifdef SO_SNDBUF 769 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen, 770 sizeof(packlen)) < 0) { 771 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno)); 772 exit(1); 773 } 774 #endif 775 #ifdef IP_HDRINCL 776 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, 777 sizeof(on)) < 0) { 778 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno)); 779 exit(1); 780 } 781 #else 782 #ifdef IP_TOS 783 if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS, 784 (char *)&tos, sizeof(tos)) < 0) { 785 Fprintf(stderr, "%s: setsockopt tos %d: %s\n", 786 prog, tos, strerror(errno)); 787 exit(1); 788 } 789 #endif 790 #endif 791 if (options & SO_DEBUG) 792 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, 793 sizeof(on)); 794 if (options & SO_DONTROUTE) 795 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 796 sizeof(on)); 797 798 /* Get the interface address list */ 799 n = ifaddrlist(&al, errbuf, sizeof errbuf); 800 al2 = al; 801 if (n < 0) { 802 Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf); 803 exit(1); 804 } 805 if (n == 0) { 806 Fprintf(stderr, 807 "%s: Can't find any network interfaces\n", prog); 808 exit(1); 809 } 810 811 /* Look for a specific device */ 812 if (device != NULL) { 813 for (i = n; i > 0; --i, ++al2) 814 if (strcmp(device, al2->device) == 0) 815 break; 816 if (i <= 0) { 817 Fprintf(stderr, "%s: Can't find interface %s\n", 818 prog, device); 819 exit(1); 820 } 821 } 822 823 /* Determine our source address */ 824 if (source == NULL) { 825 /* 826 * If a device was specified, use the interface address. 827 * Otherwise, use the first interface found. 828 * Warn if there are more than one. 829 */ 830 setsin(from, al2->addr); 831 if (n > 1 && device == NULL && !find_local_ip(from, to)) { 832 Fprintf(stderr, 833 "%s: Warning: Multiple interfaces found; using %s @ %s\n", 834 prog, inet_ntoa(from->sin_addr), al2->device); 835 } 836 } else { 837 hi = gethostinfo(source); 838 source = hi->name; 839 hi->name = NULL; 840 if (device == NULL) { 841 /* 842 * Use the first interface found. 843 * Warn if there are more than one. 844 */ 845 setsin(from, hi->addrs[0]); 846 if (hi->n > 1) 847 Fprintf(stderr, 848 "%s: Warning: %s has multiple addresses; using %s\n", 849 prog, source, inet_ntoa(from->sin_addr)); 850 } else { 851 /* 852 * Make sure the source specified matches the 853 * interface address. 854 */ 855 for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) 856 if (*ap == al2->addr) 857 break; 858 if (i <= 0) { 859 Fprintf(stderr, 860 "%s: %s is not on interface %s\n", 861 prog, source, device); 862 exit(1); 863 } 864 setsin(from, *ap); 865 } 866 freehostinfo(hi); 867 } 868 869 /* 870 * If not root, make sure source address matches a local interface. 871 * (The list of addresses produced by ifaddrlist() automatically 872 * excludes interfaces that are marked down and/or loopback.) 873 */ 874 if (getuid()) { 875 al2 = al; 876 for (i = n; i > 0; --i, ++al2) 877 if (from->sin_addr.s_addr == al2->addr) 878 break; 879 if (i <= 0) { 880 Fprintf(stderr, "%s: %s is not a valid local address " 881 "and you are not superuser.\n", prog, 882 inet_ntoa(from->sin_addr)); 883 exit(1); 884 } 885 } 886 887 outip->ip_src = from->sin_addr; 888 #ifndef IP_HDRINCL 889 if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) { 890 Fprintf(stderr, "%s: bind: %s\n", 891 prog, strerror(errno)); 892 exit (1); 893 } 894 #endif 895 896 if (as_path) { 897 asn = as_setup(as_server); 898 if (asn == NULL) { 899 Fprintf(stderr, "%s: as_setup failed, AS# lookups disabled\n", 900 prog); 901 (void)fflush(stderr); 902 as_path = 0; 903 } 904 } 905 906 setuid(getuid()); 907 Fprintf(stderr, "%s to %s (%s)", 908 prog, hostname, inet_ntoa(to->sin_addr)); 909 if (source) 910 Fprintf(stderr, " from %s", source); 911 Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen); 912 (void)fflush(stderr); 913 914 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { 915 u_int32_t lastaddr = 0; 916 int got_there = 0; 917 int unreachable = 0; 918 919 again: 920 printed_ttl = 0; 921 for (probe = 0; probe < nprobes; ++probe) { 922 register int cc; 923 struct timeval t1, t2; 924 struct timezone tz; 925 register struct ip *ip; 926 (void)gettimeofday(&t1, &tz); 927 send_probe(++seq, ttl, &t1); 928 while ((cc = wait_for_reply(s, from, &t1)) != 0) { 929 (void)gettimeofday(&t2, &tz); 930 /* 931 * Since we'll be receiving all ICMP 932 * messages to this host above, we may 933 * never end up with cc=0, so we need 934 * an additional termination check. 935 */ 936 if (t2.tv_sec - t1.tv_sec > waittime) { 937 cc = 0; 938 break; 939 } 940 i = packet_ok(packet, cc, from, seq); 941 /* Skip short packet */ 942 if (i == 0) 943 continue; 944 if (from->sin_addr.s_addr != lastaddr) { 945 print(packet, cc, from); 946 lastaddr = from->sin_addr.s_addr; 947 } 948 ip = (struct ip *)packet; 949 Printf(" %.3f ms", deltaT(&t1, &t2)); 950 if (ttl_flag) 951 Printf(" (ttl = %d)", ip->ip_ttl); 952 if (i == -2) { 953 #ifndef ARCHAIC 954 if (ip->ip_ttl <= 1) 955 Printf(" !"); 956 #endif 957 ++got_there; 958 break; 959 } 960 961 /* time exceeded in transit */ 962 if (i == -1) 963 break; 964 code = i - 1; 965 switch (code) { 966 967 case ICMP_UNREACH_PORT: 968 #ifndef ARCHAIC 969 if (ip->ip_ttl <= 1) 970 Printf(" !"); 971 #endif 972 ++got_there; 973 break; 974 975 case ICMP_UNREACH_NET: 976 ++unreachable; 977 Printf(" !N"); 978 break; 979 980 case ICMP_UNREACH_HOST: 981 ++unreachable; 982 Printf(" !H"); 983 break; 984 985 case ICMP_UNREACH_PROTOCOL: 986 ++got_there; 987 Printf(" !P"); 988 break; 989 990 case ICMP_UNREACH_NEEDFRAG: 991 if (mtudisc) { 992 frag_err(); 993 goto again; 994 } else { 995 ++unreachable; 996 Printf(" !F"); 997 } 998 break; 999 1000 case ICMP_UNREACH_SRCFAIL: 1001 ++unreachable; 1002 Printf(" !S"); 1003 break; 1004 1005 /* rfc1716 */ 1006 #ifndef ICMP_UNREACH_FILTER_PROHIB 1007 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ 1008 #endif 1009 case ICMP_UNREACH_FILTER_PROHIB: 1010 ++unreachable; 1011 Printf(" !X"); 1012 break; 1013 1014 default: 1015 ++unreachable; 1016 Printf(" !<%d>", code); 1017 break; 1018 } 1019 break; 1020 } 1021 if (cc == 0) 1022 Printf(" *"); 1023 (void)fflush(stdout); 1024 } 1025 putchar('\n'); 1026 if (got_there || 1027 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) 1028 break; 1029 } 1030 1031 if (as_path) 1032 as_shutdown(asn); 1033 1034 exit(0); 1035 } 1036 1037 int 1038 wait_for_reply(register int sock, register struct sockaddr_in *fromp, 1039 register struct timeval *tp) 1040 { 1041 fd_set *fdsp; 1042 size_t nfds; 1043 struct timeval now, wait; 1044 struct timezone tz; 1045 register int cc = 0; 1046 int fromlen = sizeof(*fromp); 1047 int retval; 1048 1049 nfds = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); 1050 if ((fdsp = malloc(nfds)) == NULL) { 1051 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno)); 1052 exit(1); 1053 } 1054 memset(fdsp, 0, nfds); 1055 FD_SET(sock, fdsp); 1056 1057 wait.tv_sec = tp->tv_sec + waittime; 1058 wait.tv_usec = tp->tv_usec; 1059 (void)gettimeofday(&now, &tz); 1060 tvsub(&wait, &now); 1061 1062 if (wait.tv_sec < 0) { 1063 wait.tv_sec = 0; 1064 wait.tv_usec = 0; 1065 } 1066 1067 retval = select(sock + 1, fdsp, NULL, NULL, &wait); 1068 free(fdsp); 1069 if (retval < 0) { 1070 /* If we continue, we probably just flood the remote host. */ 1071 Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno)); 1072 exit(1); 1073 } 1074 if (retval > 0) { 1075 cc = recvfrom(s, (char *)packet, sizeof(packet), 0, 1076 (struct sockaddr *)fromp, &fromlen); 1077 } 1078 1079 return(cc); 1080 } 1081 1082 void 1083 dump_packet() 1084 { 1085 u_char *p; 1086 int i; 1087 1088 Fprintf(stderr, "packet data:"); 1089 1090 #ifdef __hpux 1091 for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i < 1092 i < packlen - (sizeof(*outip) + optlen); i++) 1093 #else 1094 for (p = (u_char *)outip, i = 0; i < packlen; i++) 1095 #endif 1096 { 1097 if ((i % 24) == 0) 1098 Fprintf(stderr, "\n "); 1099 Fprintf(stderr, " %02x", *p++); 1100 } 1101 Fprintf(stderr, "\n"); 1102 } 1103 1104 void 1105 send_probe(register int seq, int ttl, register struct timeval *tp) 1106 { 1107 register int cc; 1108 register struct udpiphdr * ui; 1109 int oldmtu = packlen; 1110 1111 again: 1112 #ifdef BYTESWAP_IP_LEN 1113 outip->ip_len = htons(packlen); 1114 #else 1115 outip->ip_len = packlen; 1116 #endif 1117 outip->ip_ttl = ttl; 1118 #ifndef __hpux 1119 outip->ip_id = htons(ident + seq); 1120 #endif 1121 1122 /* 1123 * In most cases, the kernel will recalculate the ip checksum. 1124 * But we must do it anyway so that the udp checksum comes out 1125 * right. 1126 */ 1127 if (docksum) { 1128 outip->ip_sum = 1129 in_cksum((u_short *)outip, sizeof(*outip) + optlen); 1130 if (outip->ip_sum == 0) 1131 outip->ip_sum = 0xffff; 1132 } 1133 1134 /* Payload */ 1135 outsetup.seq = seq; 1136 outsetup.ttl = ttl; 1137 outsetup.tv = *tp; 1138 memcpy(outmark,&outsetup,sizeof(outsetup)); 1139 1140 if (useicmp) 1141 outicmp->icmp_seq = htons(seq); 1142 else 1143 outudp->uh_dport = htons(port + seq); 1144 1145 /* (We can only do the checksum if we know our ip address) */ 1146 if (docksum) { 1147 if (useicmp) { 1148 outicmp->icmp_cksum = 0; 1149 outicmp->icmp_cksum = in_cksum((u_short *)outicmp, 1150 packlen - (sizeof(*outip) + optlen)); 1151 if (outicmp->icmp_cksum == 0) 1152 outicmp->icmp_cksum = 0xffff; 1153 } else { 1154 u_short sum; 1155 struct { 1156 struct in_addr src; 1157 struct in_addr dst; 1158 u_int8_t zero; 1159 u_int8_t protocol; 1160 u_int16_t len; 1161 } __attribute__((__packed__)) phdr; 1162 1163 /* Checksum */ 1164 ui = (struct udpiphdr *)outip; 1165 memset(&phdr, 0, sizeof(phdr)); 1166 phdr.src = ui->ui_src; 1167 phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr; 1168 phdr.protocol = ui->ui_pr; 1169 phdr.len = outudp->uh_ulen; 1170 outudp->uh_sum = 0; 1171 sum = in_cksum2(0, (u_short *)&phdr, sizeof(phdr)); 1172 sum = in_cksum2(sum, (u_short *)outudp, ntohs(outudp->uh_ulen)); 1173 outudp->uh_sum = ~sum; 1174 if (outudp->uh_sum == 0) 1175 outudp->uh_sum = 0xffff; 1176 } 1177 } 1178 1179 /* XXX undocumented debugging hack */ 1180 if (verbose > 1) { 1181 register const u_short *sp; 1182 register int nshorts, i; 1183 1184 sp = (u_short *)outip; 1185 nshorts = (u_int)packlen / sizeof(u_short); 1186 i = 0; 1187 Printf("[ %d bytes", packlen); 1188 while (--nshorts >= 0) { 1189 if ((i++ % 8) == 0) 1190 Printf("\n\t"); 1191 Printf(" %04x", ntohs(*sp++)); 1192 } 1193 if (packlen & 1) { 1194 if ((i % 8) == 0) 1195 Printf("\n\t"); 1196 Printf(" %02x", *(u_char *)sp); 1197 } 1198 Printf("]\n"); 1199 } 1200 1201 #if !defined(IP_HDRINCL) && defined(IP_TTL) 1202 if (setsockopt(sndsock, IPPROTO_IP, IP_TTL, 1203 (char *)&ttl, sizeof(ttl)) < 0) { 1204 Fprintf(stderr, "%s: setsockopt ttl %d: %s\n", 1205 prog, ttl, strerror(errno)); 1206 exit(1); 1207 } 1208 #endif 1209 if (dump) 1210 dump_packet(); 1211 1212 #ifdef __hpux 1213 cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp, 1214 packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto)); 1215 if (cc > 0) 1216 cc += sizeof(*outip) + optlen; 1217 #else 1218 cc = sendto(sndsock, (char *)outip, 1219 packlen, 0, &whereto, sizeof(whereto)); 1220 #endif 1221 if (cc < 0 || cc != packlen) { 1222 if (cc < 0) { 1223 /* 1224 * An errno of EMSGSIZE means we're writing too big a 1225 * datagram for the interface. We have to just 1226 * decrease the packet size until we find one that 1227 * works. 1228 * 1229 * XXX maybe we should try to read the outgoing if's 1230 * mtu? 1231 */ 1232 if (errno == EMSGSIZE) { 1233 packlen = *mtuptr++; 1234 resize_packet(); 1235 goto again; 1236 } else 1237 Fprintf(stderr, "%s: sendto: %s\n", 1238 prog, strerror(errno)); 1239 } 1240 1241 Printf("%s: wrote %s %d chars, ret=%d\n", 1242 prog, hostname, packlen, cc); 1243 (void)fflush(stdout); 1244 } 1245 if (oldmtu != packlen) { 1246 Printf("message too big, " 1247 "trying new MTU = %d\n", packlen); 1248 printed_ttl = 0; 1249 } 1250 if (!printed_ttl) { 1251 Printf("%2d ", ttl); 1252 printed_ttl = 1; 1253 } 1254 1255 } 1256 1257 double 1258 deltaT(struct timeval *t1p, struct timeval *t2p) 1259 { 1260 register double dt; 1261 1262 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 1263 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 1264 return (dt); 1265 } 1266 1267 /* 1268 * Convert an ICMP "type" field to a printable string. 1269 */ 1270 char * 1271 pr_type(register u_char t) 1272 { 1273 static char *ttab[] = { 1274 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", 1275 "Source Quench", "Redirect", "ICMP 6", "ICMP 7", 1276 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", 1277 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", 1278 "Info Reply" 1279 }; 1280 1281 if (t > 16) 1282 return("OUT-OF-RANGE"); 1283 1284 return(ttab[t]); 1285 } 1286 1287 int 1288 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from, 1289 register int seq) 1290 { 1291 register struct icmp *icp; 1292 register u_char type, code; 1293 register int hlen; 1294 #ifndef ARCHAIC 1295 register struct ip *ip; 1296 1297 ip = (struct ip *) buf; 1298 hlen = ip->ip_hl << 2; 1299 if (cc < hlen + ICMP_MINLEN) { 1300 if (verbose) 1301 Printf("packet too short (%d bytes) from %s\n", cc, 1302 inet_ntoa(from->sin_addr)); 1303 return (0); 1304 } 1305 cc -= hlen; 1306 icp = (struct icmp *)(buf + hlen); 1307 #else 1308 icp = (struct icmp *)buf; 1309 #endif 1310 type = icp->icmp_type; 1311 code = icp->icmp_code; 1312 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 1313 type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { 1314 register struct ip *hip; 1315 register struct udphdr *up; 1316 register struct icmp *hicmp; 1317 1318 hip = &icp->icmp_ip; 1319 hlen = hip->ip_hl << 2; 1320 1321 nextmtu = ntohs(icp->icmp_nextmtu); /* for frag_err() */ 1322 1323 if (useicmp) { 1324 /* XXX */ 1325 if (type == ICMP_ECHOREPLY && 1326 icp->icmp_id == htons(ident) && 1327 icp->icmp_seq == htons(seq)) 1328 return (-2); 1329 1330 hicmp = (struct icmp *)((u_char *)hip + hlen); 1331 /* XXX 8 is a magic number */ 1332 if (hlen + 8 <= cc && 1333 hip->ip_p == IPPROTO_ICMP && 1334 hicmp->icmp_id == htons(ident) && 1335 hicmp->icmp_seq == htons(seq)) 1336 return (type == ICMP_TIMXCEED ? -1 : code + 1); 1337 } else { 1338 up = (struct udphdr *)((u_char *)hip + hlen); 1339 /* XXX 8 is a magic number */ 1340 if (hlen + 12 <= cc && 1341 hip->ip_p == IPPROTO_UDP && 1342 up->uh_sport == htons(ident) && 1343 up->uh_dport == htons(port + seq)) 1344 return (type == ICMP_TIMXCEED ? -1 : code + 1); 1345 } 1346 } 1347 #ifndef ARCHAIC 1348 if (verbose) { 1349 register int i; 1350 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip; 1351 1352 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr)); 1353 Printf("%s: icmp type %d (%s) code %d\n", 1354 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); 1355 for (i = 4; i < cc ; i += sizeof(*lp)) 1356 Printf("%2d: x%8.8x\n", i, *lp++); 1357 } 1358 #endif 1359 return(0); 1360 } 1361 1362 void resize_packet(void) 1363 { 1364 if (useicmp) { 1365 outicmp->icmp_cksum = 0; 1366 outicmp->icmp_cksum = in_cksum((u_short *)outicmp, 1367 packlen - (sizeof(*outip) + optlen)); 1368 if (outicmp->icmp_cksum == 0) 1369 outicmp->icmp_cksum = 0xffff; 1370 } else { 1371 outudp->uh_ulen = 1372 htons((u_short)(packlen - (sizeof(*outip) + optlen))); 1373 } 1374 } 1375 1376 void 1377 print(register u_char *buf, register int cc, register struct sockaddr_in *from) 1378 { 1379 register struct ip *ip; 1380 register int hlen; 1381 1382 ip = (struct ip *) buf; 1383 hlen = ip->ip_hl << 2; 1384 cc -= hlen; 1385 1386 if (as_path) 1387 Printf(" [AS%d]", as_lookup(asn, &from->sin_addr)); 1388 1389 if (nflag) 1390 Printf(" %s", inet_ntoa(from->sin_addr)); 1391 else 1392 Printf(" %s (%s)", inetname(from->sin_addr), 1393 inet_ntoa(from->sin_addr)); 1394 1395 if (verbose) 1396 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); 1397 } 1398 1399 u_short 1400 in_cksum(u_short *addr, int len) 1401 { 1402 1403 return ~in_cksum2(0, addr, len); 1404 } 1405 1406 /* 1407 * Checksum routine for Internet Protocol family headers (C Version) 1408 */ 1409 u_short 1410 in_cksum2(u_short seed, register u_short *addr, register int len) 1411 { 1412 register int nleft = len; 1413 register u_short *w = addr; 1414 register u_short answer; 1415 register int sum = seed; 1416 1417 /* 1418 * Our algorithm is simple, using a 32 bit accumulator (sum), 1419 * we add sequential 16 bit words to it, and at the end, fold 1420 * back all the carry bits from the top 16 bits into the lower 1421 * 16 bits. 1422 */ 1423 while (nleft > 1) { 1424 sum += *w++; 1425 nleft -= 2; 1426 } 1427 1428 /* mop up an odd byte, if necessary */ 1429 if (nleft == 1) 1430 sum += *(u_char *)w; 1431 1432 /* 1433 * add back carry outs from top 16 bits to low 16 bits 1434 */ 1435 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1436 sum += (sum >> 16); /* add carry */ 1437 answer = sum; /* truncate to 16 bits */ 1438 return (answer); 1439 } 1440 1441 /* 1442 * Subtract 2 timeval structs: out = out - in. 1443 * Out is assumed to be >= in. 1444 */ 1445 void 1446 tvsub(register struct timeval *out, register struct timeval *in) 1447 { 1448 1449 if ((out->tv_usec -= in->tv_usec) < 0) { 1450 --out->tv_sec; 1451 out->tv_usec += 1000000; 1452 } 1453 out->tv_sec -= in->tv_sec; 1454 } 1455 1456 /* 1457 * Construct an Internet address representation. 1458 * If the nflag has been supplied, give 1459 * numeric value, otherwise try for symbolic name. 1460 */ 1461 char * 1462 inetname(struct in_addr in) 1463 { 1464 register char *cp; 1465 register struct hostent *hp; 1466 static int first = 1; 1467 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1]; 1468 1469 if (first && !nflag) { 1470 int rv; 1471 1472 first = 0; 1473 rv = gethostname(domain, sizeof domain); 1474 domain[sizeof(domain) - 1] = '\0'; 1475 if (rv == 0 && (cp = strchr(domain, '.')) != NULL) { 1476 (void)strncpy(domain, cp + 1, sizeof(domain) - 1); 1477 } else 1478 domain[0] = '\0'; 1479 } 1480 if (!nflag && in.s_addr != INADDR_ANY) { 1481 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); 1482 if (hp != NULL) { 1483 if ((cp = strchr(hp->h_name, '.')) != NULL && 1484 strcmp(cp + 1, domain) == 0) 1485 *cp = '\0'; 1486 (void)strncpy(line, hp->h_name, sizeof(line) - 1); 1487 line[sizeof(line) - 1] = '\0'; 1488 return (line); 1489 } 1490 } 1491 return (inet_ntoa(in)); 1492 } 1493 1494 struct hostinfo * 1495 gethostinfo(register char *hostname) 1496 { 1497 register int n; 1498 register struct hostent *hp; 1499 register struct hostinfo *hi; 1500 register char **p; 1501 register u_int32_t *ap; 1502 struct in_addr addr; 1503 1504 hi = calloc(1, sizeof(*hi)); 1505 if (hi == NULL) { 1506 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno)); 1507 exit(1); 1508 } 1509 if (inet_aton(hostname, &addr) != 0) { 1510 hi->name = strdup(hostname); 1511 hi->n = 1; 1512 hi->addrs = calloc(1, sizeof(hi->addrs[0])); 1513 if (hi->addrs == NULL) { 1514 Fprintf(stderr, "%s: calloc %s\n", 1515 prog, strerror(errno)); 1516 exit(1); 1517 } 1518 hi->addrs[0] = addr.s_addr; 1519 return (hi); 1520 } 1521 1522 hp = gethostbyname(hostname); 1523 if (hp == NULL) { 1524 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname); 1525 exit(1); 1526 } 1527 if (hp->h_addrtype != AF_INET || hp->h_length != 4) { 1528 Fprintf(stderr, "%s: bad host %s\n", prog, hostname); 1529 exit(1); 1530 } 1531 hi->name = strdup(hp->h_name); 1532 for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p) 1533 continue; 1534 hi->n = n; 1535 hi->addrs = calloc(n, sizeof(hi->addrs[0])); 1536 if (hi->addrs == NULL) { 1537 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno)); 1538 exit(1); 1539 } 1540 for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p) 1541 memcpy(ap, *p, sizeof(*ap)); 1542 return (hi); 1543 } 1544 1545 void 1546 freehostinfo(register struct hostinfo *hi) 1547 { 1548 if (hi->name != NULL) { 1549 free(hi->name); 1550 hi->name = NULL; 1551 } 1552 free((char *)hi->addrs); 1553 free((char *)hi); 1554 } 1555 1556 void 1557 getaddr(register u_int32_t *ap, register char *hostname) 1558 { 1559 register struct hostinfo *hi; 1560 1561 hi = gethostinfo(hostname); 1562 *ap = hi->addrs[0]; 1563 freehostinfo(hi); 1564 } 1565 1566 void 1567 setsin(register struct sockaddr_in *sin, register u_int32_t addr) 1568 { 1569 1570 memset(sin, 0, sizeof(*sin)); 1571 #ifdef HAVE_SOCKADDR_SA_LEN 1572 sin->sin_len = sizeof(*sin); 1573 #endif 1574 sin->sin_family = AF_INET; 1575 sin->sin_addr.s_addr = addr; 1576 } 1577 1578 /* String to value with optional min and max. Handles decimal and hex. */ 1579 int 1580 str2val(register const char *str, register const char *what, 1581 register int mi, register int ma) 1582 { 1583 register const char *cp; 1584 register int val; 1585 char *ep; 1586 1587 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { 1588 cp = str + 2; 1589 val = (int)strtol(cp, &ep, 16); 1590 } else 1591 val = (int)strtol(str, &ep, 10); 1592 if (*ep != '\0') { 1593 Fprintf(stderr, "%s: \"%s\" bad value for %s \n", 1594 prog, str, what); 1595 exit(1); 1596 } 1597 if (val < mi && mi >= 0) { 1598 if (mi == 0) 1599 Fprintf(stderr, "%s: %s must be >= %d\n", 1600 prog, what, mi); 1601 else 1602 Fprintf(stderr, "%s: %s must be > %d\n", 1603 prog, what, mi - 1); 1604 exit(1); 1605 } 1606 if (val > ma && ma >= 0) { 1607 Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma); 1608 exit(1); 1609 } 1610 return (val); 1611 } 1612 1613 __dead void 1614 usage(void) 1615 { 1616 extern char version[]; 1617 1618 Fprintf(stderr, "Version %s\n", version); 1619 Fprintf(stderr, "Usage: %s [-adDFPIlnrvx] [-g gateway] [-i iface] \ 1620 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\ 1621 [-w waittime] [-A as_server] host [packetlen]\n", 1622 prog); 1623 exit(1); 1624 } 1625 1626 /* 1627 * Received ICMP unreachable (fragmentation required and DF set). 1628 * If the ICMP error was from a "new" router, it'll contain the next-hop 1629 * MTU that we should use next. Otherwise we'll just keep going in the 1630 * mtus[] table, trying until we hit a valid MTU. 1631 */ 1632 1633 1634 void 1635 frag_err() 1636 { 1637 int i; 1638 1639 if (nextmtu > 0 && nextmtu < packlen) { 1640 Printf("\nfragmentation required and DF set, " 1641 "next hop MTU = %d\n", 1642 nextmtu); 1643 packlen = nextmtu; 1644 for (i = 0; mtus[i] > 0; i++) { 1645 if (mtus[i] < nextmtu) { 1646 mtuptr = &mtus[i]; /* next one to try */ 1647 break; 1648 } 1649 } 1650 } else { 1651 Printf("\nfragmentation required and DF set. "); 1652 if (nextmtu) 1653 Printf("\nBogus next hop MTU = %d > last MTU = %d. ", 1654 nextmtu, packlen); 1655 packlen = *mtuptr++; 1656 Printf("Trying new MTU = %d\n", packlen); 1657 } 1658 resize_packet(); 1659 } 1660 1661 int 1662 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to) 1663 { 1664 int sock; 1665 struct sockaddr_in help; 1666 int help_len; 1667 1668 sock = socket(AF_INET, SOCK_DGRAM, 0); 1669 if (sock < 0) return (0); 1670 1671 help.sin_family = AF_INET; 1672 /* 1673 * At this point the port number doesn't matter 1674 * since it only has to be greater than zero. 1675 */ 1676 help.sin_port = 42; 1677 help.sin_addr.s_addr = to->sin_addr.s_addr; 1678 if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) { 1679 (void)close(sock); 1680 return (0); 1681 } 1682 1683 help_len = sizeof(help); 1684 if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 || 1685 help_len != sizeof(help) || 1686 help.sin_addr.s_addr == INADDR_ANY) { 1687 (void)close(sock); 1688 return (0); 1689 } 1690 1691 (void)close(sock); 1692 setsin(from, help.sin_addr.s_addr); 1693 return (1); 1694 } 1695 1696 #ifdef IPSEC 1697 #ifdef IPSEC_POLICY_IPSEC 1698 int 1699 setpolicy(so, policy) 1700 int so; 1701 char *policy; 1702 { 1703 char *buf; 1704 1705 buf = ipsec_set_policy(policy, strlen(policy)); 1706 if (buf == NULL) { 1707 Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror()); 1708 return -1; 1709 } 1710 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY, 1711 buf, ipsec_get_policylen(buf)); 1712 1713 free(buf); 1714 1715 return 0; 1716 } 1717 #endif 1718 #endif 1719 1720