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