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