traceroute.c revision 283958
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: stable/10/contrib/traceroute/traceroute.c 283958 2015-06-03 17:45:45Z tuexen $"; 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/sctp.h> 223#include <netinet/udp.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/* rfc1716 */ 249#ifndef ICMP_UNREACH_FILTER_PROHIB 250#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ 251#endif 252#ifndef ICMP_UNREACH_HOST_PRECEDENCE 253#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */ 254#endif 255#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF 256#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ 257#endif 258 259#include "findsaddr.h" 260#include "ifaddrlist.h" 261#include "as.h" 262#include "traceroute.h" 263 264/* Maximum number of gateways (include room for one noop) */ 265#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t))) 266 267#ifndef MAXHOSTNAMELEN 268#define MAXHOSTNAMELEN 64 269#endif 270 271#define Fprintf (void)fprintf 272#define Printf (void)printf 273 274/* What a GRE packet header looks like */ 275struct grehdr { 276 u_int16_t flags; 277 u_int16_t proto; 278 u_int16_t length; /* PPTP version of these fields */ 279 u_int16_t callId; 280}; 281#ifndef IPPROTO_GRE 282#define IPPROTO_GRE 47 283#endif 284 285/* For GRE, we prepare what looks like a PPTP packet */ 286#define GRE_PPTP_PROTO 0x880b 287 288/* Host name and address list */ 289struct hostinfo { 290 char *name; 291 int n; 292 u_int32_t *addrs; 293}; 294 295/* Data section of the probe packet */ 296struct outdata { 297 u_char seq; /* sequence number of this packet */ 298 u_char ttl; /* ttl packet left with */ 299 struct timeval tv; /* time packet left */ 300}; 301 302#ifndef HAVE_ICMP_NEXTMTU 303/* Path MTU Discovery (RFC1191) */ 304struct my_pmtu { 305 u_short ipm_void; 306 u_short ipm_nextmtu; 307}; 308#endif 309 310u_char packet[512]; /* last inbound (icmp) packet */ 311 312struct ip *outip; /* last output ip packet */ 313u_char *outp; /* last output inner protocol packet */ 314 315struct ip *hip = NULL; /* Quoted IP header */ 316int hiplen = 0; 317 318/* loose source route gateway list (including room for final destination) */ 319u_int32_t gwlist[NGATEWAYS + 1]; 320 321int s; /* receive (icmp) socket file descriptor */ 322int sndsock; /* send (udp) socket file descriptor */ 323 324struct sockaddr whereto; /* Who to try to reach */ 325struct sockaddr wherefrom; /* Who we are */ 326int packlen; /* total length of packet */ 327int protlen; /* length of protocol part of packet */ 328int minpacket; /* min ip packet size */ 329int maxpacket = 32 * 1024; /* max ip packet size */ 330int pmtu; /* Path MTU Discovery (RFC1191) */ 331u_int pausemsecs; 332 333char *prog; 334char *source; 335char *hostname; 336char *device; 337static const char devnull[] = "/dev/null"; 338 339int nprobes = -1; 340int max_ttl; 341int first_ttl = 1; 342u_short ident; 343u_short port; /* protocol specific base "port" */ 344 345int options; /* socket options */ 346int verbose; 347int waittime = 5; /* time to wait for response (in seconds) */ 348int nflag; /* print addresses numerically */ 349int as_path; /* print as numbers for each hop */ 350char *as_server = NULL; 351void *asn; 352#ifdef CANT_HACK_IPCKSUM 353int doipcksum = 0; /* don't calculate ip checksums by default */ 354#else 355int doipcksum = 1; /* calculate ip checksums by default */ 356#endif 357int optlen; /* length of ip options */ 358int fixedPort = 0; /* Use fixed destination port for TCP and UDP */ 359int printdiff = 0; /* Print the difference between sent and quoted */ 360 361extern int optind; 362extern int opterr; 363extern char *optarg; 364 365/* Forwards */ 366double deltaT(struct timeval *, struct timeval *); 367void freehostinfo(struct hostinfo *); 368void getaddr(u_int32_t *, char *); 369struct hostinfo *gethostinfo(char *); 370u_short in_cksum(u_short *, int); 371u_int32_t sctp_crc32c(const void *, u_int32_t); 372char *inetname(struct in_addr); 373int main(int, char **); 374u_short p_cksum(struct ip *, u_short *, int, int); 375int packet_ok(u_char *, int, struct sockaddr_in *, int); 376char *pr_type(u_char); 377void print(u_char *, int, struct sockaddr_in *); 378#ifdef IPSEC 379int setpolicy __P((int so, char *policy)); 380#endif 381void send_probe(int, int); 382struct outproto *setproto(char *); 383int str2val(const char *, const char *, int, int); 384void tvsub(struct timeval *, struct timeval *); 385void usage(void); 386int wait_for_reply(int, struct sockaddr_in *, const struct timeval *); 387void pkt_compare(const u_char *, int, const u_char *, int); 388#ifndef HAVE_USLEEP 389int usleep(u_int); 390#endif 391 392void udp_prep(struct outdata *); 393int udp_check(const u_char *, int); 394void udplite_prep(struct outdata *); 395int udplite_check(const u_char *, int); 396void tcp_prep(struct outdata *); 397int tcp_check(const u_char *, int); 398void sctp_prep(struct outdata *); 399int sctp_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 "udplite", 434 "spt dpt cov sum", 435 IPPROTO_UDPLITE, 436 sizeof(struct udphdr), 437 32768 + 666, 438 udplite_prep, 439 udplite_check 440 }, 441 { 442 "tcp", 443 "spt dpt seq ack xxflwin sum urp", 444 IPPROTO_TCP, 445 sizeof(struct tcphdr), 446 32768 + 666, 447 tcp_prep, 448 tcp_check 449 }, 450 { 451 "sctp", 452 "spt dpt vtag crc tyfllen tyfllen ", 453 IPPROTO_SCTP, 454 sizeof(struct sctphdr), 455 32768 + 666, 456 sctp_prep, 457 sctp_check 458 }, 459 { 460 "gre", 461 "flg pro len clid", 462 IPPROTO_GRE, 463 sizeof(struct grehdr), 464 GRE_PPTP_PROTO, 465 gre_prep, 466 gre_check 467 }, 468 { 469 "icmp", 470 "typ cod sum ", 471 IPPROTO_ICMP, 472 sizeof(struct icmp), 473 0, 474 icmp_prep, 475 icmp_check 476 }, 477 { 478 NULL, 479 "", 480 0, 481 2 * sizeof(u_short), 482 0, 483 gen_prep, 484 gen_check 485 }, 486}; 487struct outproto *proto = &protos[0]; 488 489const char *ip_hdr_key = "vhtslen id off tlprsum srcip dstip opts"; 490 491int 492main(int argc, char **argv) 493{ 494 register int op, code, n; 495 register char *cp; 496 register const char *err; 497 register u_int32_t *ap; 498 register struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom; 499 register struct sockaddr_in *to = (struct sockaddr_in *)&whereto; 500 register struct hostinfo *hi; 501 int on = 1; 502 register struct protoent *pe; 503 register int ttl, probe, i; 504 register int seq = 0; 505 int tos = 0, settos = 0; 506 register int lsrr = 0; 507 register u_short off = 0; 508 struct ifaddrlist *al; 509 char errbuf[132]; 510 int requestPort = -1; 511 int sump = 0; 512 int sockerrno; 513 514 /* Insure the socket fds won't be 0, 1 or 2 */ 515 if (open(devnull, O_RDONLY) < 0 || 516 open(devnull, O_RDONLY) < 0 || 517 open(devnull, O_RDONLY) < 0) { 518 Fprintf(stderr, "%s: open \"%s\": %s\n", 519 prog, devnull, strerror(errno)); 520 exit(1); 521 } 522 /* 523 * Do the setuid-required stuff first, then lose priveleges ASAP. 524 * Do error checking for these two calls where they appeared in 525 * the original code. 526 */ 527 cp = "icmp"; 528 pe = getprotobyname(cp); 529 if (pe) { 530 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) 531 sockerrno = errno; 532 else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 533 sockerrno = errno; 534 } 535 536 if (setuid(getuid()) != 0) { 537 perror("setuid()"); 538 exit(1); 539 } 540 541#ifdef IPCTL_DEFTTL 542 { 543 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; 544 size_t sz = sizeof(max_ttl); 545 546 if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) { 547 perror("sysctl(net.inet.ip.ttl)"); 548 exit(1); 549 } 550 } 551#else 552 max_ttl = 30; 553#endif 554 555 if (argv[0] == NULL) 556 prog = "traceroute"; 557 else if ((cp = strrchr(argv[0], '/')) != NULL) 558 prog = cp + 1; 559 else 560 prog = argv[0]; 561 562 opterr = 0; 563 while ((op = getopt(argc, argv, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) 564 switch (op) { 565 case 'a': 566 as_path = 1; 567 break; 568 569 case 'A': 570 as_path = 1; 571 as_server = optarg; 572 break; 573 574 case 'd': 575 options |= SO_DEBUG; 576 break; 577 578 case 'D': 579 printdiff = 1; 580 break; 581 582 case 'e': 583 fixedPort = 1; 584 break; 585 586 case 'f': 587 case 'M': /* FreeBSD compat. */ 588 first_ttl = str2val(optarg, "first ttl", 1, 255); 589 break; 590 591 case 'F': 592 off = IP_DF; 593 break; 594 595 case 'g': 596 if (lsrr >= NGATEWAYS) { 597 Fprintf(stderr, 598 "%s: No more than %d gateways\n", 599 prog, NGATEWAYS); 600 exit(1); 601 } 602 getaddr(gwlist + lsrr, optarg); 603 ++lsrr; 604 break; 605 606 case 'i': 607 device = optarg; 608 break; 609 610 case 'I': 611 proto = setproto("icmp"); 612 break; 613 614 case 'm': 615 max_ttl = str2val(optarg, "max ttl", 1, 255); 616 break; 617 618 case 'n': 619 ++nflag; 620 break; 621 622 case 'P': 623 proto = setproto(optarg); 624 break; 625 626 case 'p': 627 requestPort = (u_short)str2val(optarg, "port", 628 1, (1 << 16) - 1); 629 break; 630 631 case 'q': 632 nprobes = str2val(optarg, "nprobes", 1, -1); 633 break; 634 635 case 'r': 636 options |= SO_DONTROUTE; 637 break; 638 639 case 's': 640 /* 641 * set the ip source address of the outbound 642 * probe (e.g., on a multi-homed host). 643 */ 644 source = optarg; 645 break; 646 647 case 'S': 648 sump = 1; 649 break; 650 651 case 't': 652 tos = str2val(optarg, "tos", 0, 255); 653 ++settos; 654 break; 655 656 case 'v': 657 ++verbose; 658 break; 659 660 case 'x': 661 doipcksum = (doipcksum == 0); 662 break; 663 664 case 'w': 665 waittime = str2val(optarg, "wait time", 666 1, 24 * 60 * 60); 667 break; 668 669 case 'z': 670 pausemsecs = str2val(optarg, "pause msecs", 671 0, 60 * 60 * 1000); 672 break; 673 674 default: 675 usage(); 676 } 677 678 /* Set requested port, if any, else default for this protocol */ 679 port = (requestPort != -1) ? requestPort : proto->port; 680 681 if (nprobes == -1) 682 nprobes = printdiff ? 1 : 3; 683 684 if (first_ttl > max_ttl) { 685 Fprintf(stderr, 686 "%s: first ttl (%d) may not be greater than max ttl (%d)\n", 687 prog, first_ttl, max_ttl); 688 exit(1); 689 } 690 691 if (!doipcksum) 692 Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog); 693 694 if (lsrr > 0) 695 optlen = (lsrr + 1) * sizeof(gwlist[0]); 696 minpacket = sizeof(*outip) + proto->hdrlen + optlen; 697 if (minpacket > 40) 698 packlen = minpacket; 699 else 700 packlen = 40; 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 if ((proto->num == IPPROTO_SCTP) && (packlen & 3)) { 735 Fprintf(stderr, "%s: packet length must be a multiple of 4\n", 736 prog); 737 exit(1); 738 } 739 740 outip = (struct ip *)malloc((unsigned)packlen); 741 if (outip == NULL) { 742 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno)); 743 exit(1); 744 } 745 memset((char *)outip, 0, packlen); 746 747 outip->ip_v = IPVERSION; 748 if (settos) 749 outip->ip_tos = tos; 750#ifdef BYTESWAP_IP_HDR 751 outip->ip_len = htons(packlen); 752 outip->ip_off = htons(off); 753#else 754 outip->ip_len = packlen; 755 outip->ip_off = off; 756#endif 757 outip->ip_p = proto->num; 758 outp = (u_char *)(outip + 1); 759#ifdef HAVE_RAW_OPTIONS 760 if (lsrr > 0) { 761 register u_char *optlist; 762 763 optlist = outp; 764 outp += optlen; 765 766 /* final hop */ 767 gwlist[lsrr] = to->sin_addr.s_addr; 768 769 outip->ip_dst.s_addr = gwlist[0]; 770 771 /* force 4 byte alignment */ 772 optlist[0] = IPOPT_NOP; 773 /* loose source route option */ 774 optlist[1] = IPOPT_LSRR; 775 i = lsrr * sizeof(gwlist[0]); 776 optlist[2] = i + 3; 777 /* Pointer to LSRR addresses */ 778 optlist[3] = IPOPT_MINOFF; 779 memcpy(optlist + 4, gwlist + 1, i); 780 } else 781#endif 782 outip->ip_dst = to->sin_addr; 783 784 outip->ip_hl = (outp - (u_char *)outip) >> 2; 785 ident = (getpid() & 0xffff) | 0x8000; 786 787 if (pe == NULL) { 788 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 789 exit(1); 790 } 791 if (s < 0) { 792 errno = sockerrno; 793 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno)); 794 exit(1); 795 } 796 if (options & SO_DEBUG) 797 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, 798 sizeof(on)); 799 if (options & SO_DONTROUTE) 800 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 801 sizeof(on)); 802 803#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 804 if (setpolicy(s, "in bypass") < 0) 805 errx(1, "%s", ipsec_strerror()); 806 807 if (setpolicy(s, "out bypass") < 0) 808 errx(1, "%s", ipsec_strerror()); 809#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */ 810 811 if (sndsock < 0) { 812 errno = sockerrno; 813 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno)); 814 exit(1); 815 } 816 817#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS) 818 if (lsrr > 0) { 819 u_char optlist[MAX_IPOPTLEN]; 820 821 cp = "ip"; 822 if ((pe = getprotobyname(cp)) == NULL) { 823 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 824 exit(1); 825 } 826 827 /* final hop */ 828 gwlist[lsrr] = to->sin_addr.s_addr; 829 ++lsrr; 830 831 /* force 4 byte alignment */ 832 optlist[0] = IPOPT_NOP; 833 /* loose source route option */ 834 optlist[1] = IPOPT_LSRR; 835 i = lsrr * sizeof(gwlist[0]); 836 optlist[2] = i + 3; 837 /* Pointer to LSRR addresses */ 838 optlist[3] = IPOPT_MINOFF; 839 memcpy(optlist + 4, gwlist, i); 840 841 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, 842 (char *)optlist, i + sizeof(gwlist[0]))) < 0) { 843 Fprintf(stderr, "%s: IP_OPTIONS: %s\n", 844 prog, strerror(errno)); 845 exit(1); 846 } 847 } 848#endif 849 850#ifdef SO_SNDBUF 851 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen, 852 sizeof(packlen)) < 0) { 853 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno)); 854 exit(1); 855 } 856#endif 857#ifdef IP_HDRINCL 858 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, 859 sizeof(on)) < 0) { 860 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno)); 861 exit(1); 862 } 863#else 864#ifdef IP_TOS 865 if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS, 866 (char *)&tos, sizeof(tos)) < 0) { 867 Fprintf(stderr, "%s: setsockopt tos %d: %s\n", 868 prog, tos, strerror(errno)); 869 exit(1); 870 } 871#endif 872#endif 873 if (options & SO_DEBUG) 874 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, 875 sizeof(on)); 876 if (options & SO_DONTROUTE) 877 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 878 sizeof(on)); 879 880 /* Get the interface address list */ 881 n = ifaddrlist(&al, errbuf); 882 if (n < 0) { 883 Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf); 884 exit(1); 885 } 886 if (n == 0) { 887 Fprintf(stderr, 888 "%s: Can't find any network interfaces\n", prog); 889 exit(1); 890 } 891 892 /* Look for a specific device */ 893 if (device != NULL) { 894 for (i = n; i > 0; --i, ++al) 895 if (strcmp(device, al->device) == 0) 896 break; 897 if (i <= 0) { 898 Fprintf(stderr, "%s: Can't find interface %.32s\n", 899 prog, device); 900 exit(1); 901 } 902 } 903 904 /* Determine our source address */ 905 if (source == NULL) { 906 /* 907 * If a device was specified, use the interface address. 908 * Otherwise, try to determine our source address. 909 */ 910 if (device != NULL) 911 setsin(from, al->addr); 912 else if ((err = findsaddr(to, from)) != NULL) { 913 Fprintf(stderr, "%s: findsaddr: %s\n", 914 prog, err); 915 exit(1); 916 } 917 } else { 918 hi = gethostinfo(source); 919 source = hi->name; 920 hi->name = NULL; 921 /* 922 * If the device was specified make sure it 923 * corresponds to the source address specified. 924 * Otherwise, use the first address (and warn if 925 * there are more than one). 926 */ 927 if (device != NULL) { 928 for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) 929 if (*ap == al->addr) 930 break; 931 if (i <= 0) { 932 Fprintf(stderr, 933 "%s: %s is not on interface %.32s\n", 934 prog, source, device); 935 exit(1); 936 } 937 setsin(from, *ap); 938 } else { 939 setsin(from, hi->addrs[0]); 940 if (hi->n > 1) 941 Fprintf(stderr, 942 "%s: Warning: %s has multiple addresses; using %s\n", 943 prog, source, inet_ntoa(from->sin_addr)); 944 } 945 freehostinfo(hi); 946 } 947 948 outip->ip_src = from->sin_addr; 949 950 /* Check the source address (-s), if any, is valid */ 951 if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) { 952 Fprintf(stderr, "%s: bind: %s\n", 953 prog, strerror(errno)); 954 exit (1); 955 } 956 957 if (as_path) { 958 asn = as_setup(as_server); 959 if (asn == NULL) { 960 Fprintf(stderr, "%s: as_setup failed, AS# lookups" 961 " disabled\n", prog); 962 (void)fflush(stderr); 963 as_path = 0; 964 } 965 } 966 967#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 968 if (setpolicy(sndsock, "in bypass") < 0) 969 errx(1, "%s", ipsec_strerror()); 970 971 if (setpolicy(sndsock, "out bypass") < 0) 972 errx(1, "%s", ipsec_strerror()); 973#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */ 974 975 Fprintf(stderr, "%s to %s (%s)", 976 prog, hostname, inet_ntoa(to->sin_addr)); 977 if (source) 978 Fprintf(stderr, " from %s", source); 979 Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen); 980 (void)fflush(stderr); 981 982 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { 983 u_int32_t lastaddr = 0; 984 int gotlastaddr = 0; 985 int got_there = 0; 986 int unreachable = 0; 987 int sentfirst = 0; 988 int loss; 989 990 Printf("%2d ", ttl); 991 for (probe = 0, loss = 0; probe < nprobes; ++probe) { 992 register int cc; 993 struct timeval t1, t2; 994 register struct ip *ip; 995 struct outdata outdata; 996 997 if (sentfirst && pausemsecs > 0) 998 usleep(pausemsecs * 1000); 999 /* Prepare outgoing data */ 1000 outdata.seq = ++seq; 1001 outdata.ttl = ttl; 1002 1003 /* Avoid alignment problems by copying bytewise: */ 1004 (void)gettimeofday(&t1, NULL); 1005 memcpy(&outdata.tv, &t1, sizeof(outdata.tv)); 1006 1007 /* Finalize and send packet */ 1008 (*proto->prepare)(&outdata); 1009 send_probe(seq, ttl); 1010 ++sentfirst; 1011 1012 /* Wait for a reply */ 1013 while ((cc = wait_for_reply(s, from, &t1)) != 0) { 1014 double T; 1015 int precis; 1016 1017 (void)gettimeofday(&t2, NULL); 1018 i = packet_ok(packet, cc, from, seq); 1019 /* Skip short packet */ 1020 if (i == 0) 1021 continue; 1022 if (!gotlastaddr || 1023 from->sin_addr.s_addr != lastaddr) { 1024 if (gotlastaddr) printf("\n "); 1025 print(packet, cc, from); 1026 lastaddr = from->sin_addr.s_addr; 1027 ++gotlastaddr; 1028 } 1029 T = deltaT(&t1, &t2); 1030#ifdef SANE_PRECISION 1031 if (T >= 1000.0) 1032 precis = 0; 1033 else if (T >= 100.0) 1034 precis = 1; 1035 else if (T >= 10.0) 1036 precis = 2; 1037 else 1038#endif 1039 precis = 3; 1040 Printf(" %.*f ms", precis, T); 1041 if (printdiff) { 1042 Printf("\n"); 1043 Printf("%*.*s%s\n", 1044 -(outip->ip_hl << 3), 1045 outip->ip_hl << 3, 1046 ip_hdr_key, 1047 proto->key); 1048 pkt_compare((void *)outip, packlen, 1049 (void *)hip, hiplen); 1050 } 1051 if (i == -2) { 1052#ifndef ARCHAIC 1053 ip = (struct ip *)packet; 1054 if (ip->ip_ttl <= 1) 1055 Printf(" !"); 1056#endif 1057 ++got_there; 1058 break; 1059 } 1060 /* time exceeded in transit */ 1061 if (i == -1) 1062 break; 1063 code = i - 1; 1064 switch (code) { 1065 1066 case ICMP_UNREACH_PORT: 1067#ifndef ARCHAIC 1068 ip = (struct ip *)packet; 1069 if (ip->ip_ttl <= 1) 1070 Printf(" !"); 1071#endif 1072 ++got_there; 1073 break; 1074 1075 case ICMP_UNREACH_NET: 1076 ++unreachable; 1077 Printf(" !N"); 1078 break; 1079 1080 case ICMP_UNREACH_HOST: 1081 ++unreachable; 1082 Printf(" !H"); 1083 break; 1084 1085 case ICMP_UNREACH_PROTOCOL: 1086 ++got_there; 1087 Printf(" !P"); 1088 break; 1089 1090 case ICMP_UNREACH_NEEDFRAG: 1091 ++unreachable; 1092 Printf(" !F-%d", pmtu); 1093 break; 1094 1095 case ICMP_UNREACH_SRCFAIL: 1096 ++unreachable; 1097 Printf(" !S"); 1098 break; 1099 1100 case ICMP_UNREACH_NET_UNKNOWN: 1101 ++unreachable; 1102 Printf(" !U"); 1103 break; 1104 1105 case ICMP_UNREACH_HOST_UNKNOWN: 1106 ++unreachable; 1107 Printf(" !W"); 1108 break; 1109 1110 case ICMP_UNREACH_ISOLATED: 1111 ++unreachable; 1112 Printf(" !I"); 1113 break; 1114 1115 case ICMP_UNREACH_NET_PROHIB: 1116 ++unreachable; 1117 Printf(" !A"); 1118 break; 1119 1120 case ICMP_UNREACH_HOST_PROHIB: 1121 ++unreachable; 1122 Printf(" !Z"); 1123 break; 1124 1125 case ICMP_UNREACH_TOSNET: 1126 ++unreachable; 1127 Printf(" !Q"); 1128 break; 1129 1130 case ICMP_UNREACH_TOSHOST: 1131 ++unreachable; 1132 Printf(" !T"); 1133 break; 1134 1135 case ICMP_UNREACH_FILTER_PROHIB: 1136 ++unreachable; 1137 Printf(" !X"); 1138 break; 1139 1140 case ICMP_UNREACH_HOST_PRECEDENCE: 1141 ++unreachable; 1142 Printf(" !V"); 1143 break; 1144 1145 case ICMP_UNREACH_PRECEDENCE_CUTOFF: 1146 ++unreachable; 1147 Printf(" !C"); 1148 break; 1149 1150 default: 1151 ++unreachable; 1152 Printf(" !<%d>", code); 1153 break; 1154 } 1155 break; 1156 } 1157 if (cc == 0) { 1158 loss++; 1159 Printf(" *"); 1160 } 1161 (void)fflush(stdout); 1162 } 1163 if (sump) { 1164 Printf(" (%d%% loss)", (loss * 100) / nprobes); 1165 } 1166 putchar('\n'); 1167 if (got_there || 1168 (unreachable > 0 && unreachable >= nprobes - 1)) 1169 break; 1170 } 1171 if (as_path) 1172 as_shutdown(asn); 1173 exit(0); 1174} 1175 1176int 1177wait_for_reply(register int sock, register struct sockaddr_in *fromp, 1178 register const struct timeval *tp) 1179{ 1180 fd_set *fdsp; 1181 size_t nfds; 1182 struct timeval now, wait; 1183 register int cc = 0; 1184 register int error; 1185 int fromlen = sizeof(*fromp); 1186 1187 nfds = howmany(sock + 1, NFDBITS); 1188 if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL) 1189 err(1, "malloc"); 1190 memset(fdsp, 0, nfds * sizeof(fd_mask)); 1191 FD_SET(sock, fdsp); 1192 1193 wait.tv_sec = tp->tv_sec + waittime; 1194 wait.tv_usec = tp->tv_usec; 1195 (void)gettimeofday(&now, NULL); 1196 tvsub(&wait, &now); 1197 if (wait.tv_sec < 0) { 1198 wait.tv_sec = 0; 1199 wait.tv_usec = 1; 1200 } 1201 1202 error = select(sock + 1, fdsp, NULL, NULL, &wait); 1203 if (error == -1 && errno == EINVAL) { 1204 Fprintf(stderr, "%s: botched select() args\n", prog); 1205 exit(1); 1206 } 1207 if (error > 0) 1208 cc = recvfrom(sock, (char *)packet, sizeof(packet), 0, 1209 (struct sockaddr *)fromp, &fromlen); 1210 1211 free(fdsp); 1212 return(cc); 1213} 1214 1215void 1216send_probe(int seq, int ttl) 1217{ 1218 register int cc; 1219 1220 outip->ip_ttl = ttl; 1221 outip->ip_id = htons(ident + seq); 1222 1223 /* XXX undocumented debugging hack */ 1224 if (verbose > 1) { 1225 register const u_short *sp; 1226 register int nshorts, i; 1227 1228 sp = (u_short *)outip; 1229 nshorts = (u_int)packlen / sizeof(u_short); 1230 i = 0; 1231 Printf("[ %d bytes", packlen); 1232 while (--nshorts >= 0) { 1233 if ((i++ % 8) == 0) 1234 Printf("\n\t"); 1235 Printf(" %04x", ntohs(*sp++)); 1236 } 1237 if (packlen & 1) { 1238 if ((i % 8) == 0) 1239 Printf("\n\t"); 1240 Printf(" %02x", *(u_char *)sp); 1241 } 1242 Printf("]\n"); 1243 } 1244 1245#if !defined(IP_HDRINCL) && defined(IP_TTL) 1246 if (setsockopt(sndsock, IPPROTO_IP, IP_TTL, 1247 (char *)&ttl, sizeof(ttl)) < 0) { 1248 Fprintf(stderr, "%s: setsockopt ttl %d: %s\n", 1249 prog, ttl, strerror(errno)); 1250 exit(1); 1251 } 1252#endif 1253 1254 cc = sendto(sndsock, (char *)outip, 1255 packlen, 0, &whereto, sizeof(whereto)); 1256 if (cc < 0 || cc != packlen) { 1257 if (cc < 0) 1258 Fprintf(stderr, "%s: sendto: %s\n", 1259 prog, strerror(errno)); 1260 Printf("%s: wrote %s %d chars, ret=%d\n", 1261 prog, hostname, packlen, cc); 1262 (void)fflush(stdout); 1263 } 1264} 1265 1266#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 1267int 1268setpolicy(so, policy) 1269 int so; 1270 char *policy; 1271{ 1272 char *buf; 1273 1274 buf = ipsec_set_policy(policy, strlen(policy)); 1275 if (buf == NULL) { 1276 warnx("%s", ipsec_strerror()); 1277 return -1; 1278 } 1279 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY, 1280 buf, ipsec_get_policylen(buf)); 1281 1282 free(buf); 1283 1284 return 0; 1285} 1286#endif 1287 1288double 1289deltaT(struct timeval *t1p, struct timeval *t2p) 1290{ 1291 register double dt; 1292 1293 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 1294 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 1295 return (dt); 1296} 1297 1298/* 1299 * Convert an ICMP "type" field to a printable string. 1300 */ 1301char * 1302pr_type(register u_char t) 1303{ 1304 static char *ttab[] = { 1305 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", 1306 "Source Quench", "Redirect", "ICMP 6", "ICMP 7", 1307 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", 1308 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", 1309 "Info Reply" 1310 }; 1311 1312 if (t > 16) 1313 return("OUT-OF-RANGE"); 1314 1315 return(ttab[t]); 1316} 1317 1318int 1319packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from, 1320 register int seq) 1321{ 1322 register struct icmp *icp; 1323 register u_char type, code; 1324 register int hlen; 1325#ifndef ARCHAIC 1326 register struct ip *ip; 1327 1328 ip = (struct ip *) buf; 1329 hlen = ip->ip_hl << 2; 1330 if (cc < hlen + ICMP_MINLEN) { 1331 if (verbose) 1332 Printf("packet too short (%d bytes) from %s\n", cc, 1333 inet_ntoa(from->sin_addr)); 1334 return (0); 1335 } 1336 cc -= hlen; 1337 icp = (struct icmp *)(buf + hlen); 1338#else 1339 icp = (struct icmp *)buf; 1340#endif 1341 type = icp->icmp_type; 1342 code = icp->icmp_code; 1343 /* Path MTU Discovery (RFC1191) */ 1344 if (code != ICMP_UNREACH_NEEDFRAG) 1345 pmtu = 0; 1346 else { 1347#ifdef HAVE_ICMP_NEXTMTU 1348 pmtu = ntohs(icp->icmp_nextmtu); 1349#else 1350 pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu); 1351#endif 1352 } 1353 if (type == ICMP_ECHOREPLY 1354 && proto->num == IPPROTO_ICMP 1355 && (*proto->check)((u_char *)icp, (u_char)seq)) 1356 return -2; 1357 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 1358 type == ICMP_UNREACH) { 1359 u_char *inner; 1360 1361 hip = &icp->icmp_ip; 1362 hiplen = ((u_char *)icp + cc) - (u_char *)hip; 1363 hlen = hip->ip_hl << 2; 1364 inner = (u_char *)((u_char *)hip + hlen); 1365 if (hlen + 16 <= cc 1366 && hip->ip_p == proto->num 1367 && (*proto->check)(inner, (u_char)seq)) 1368 return (type == ICMP_TIMXCEED ? -1 : code + 1); 1369 } 1370#ifndef ARCHAIC 1371 if (verbose) { 1372 register int i; 1373 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip; 1374 1375 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr)); 1376 Printf("%s: icmp type %d (%s) code %d\n", 1377 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); 1378 for (i = 4; i <= cc - ICMP_MINLEN; i += sizeof(*lp)) 1379 Printf("%2d: %8.8x\n", i, ntohl(*lp++)); 1380 } 1381#endif 1382 return(0); 1383} 1384 1385void 1386icmp_prep(struct outdata *outdata) 1387{ 1388 struct icmp *const icmpheader = (struct icmp *) outp; 1389 1390 icmpheader->icmp_type = ICMP_ECHO; 1391 icmpheader->icmp_id = htons(ident); 1392 icmpheader->icmp_seq = htons(outdata->seq); 1393 icmpheader->icmp_cksum = 0; 1394 icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen); 1395 if (icmpheader->icmp_cksum == 0) 1396 icmpheader->icmp_cksum = 0xffff; 1397} 1398 1399int 1400icmp_check(const u_char *data, int seq) 1401{ 1402 struct icmp *const icmpheader = (struct icmp *) data; 1403 1404 return (icmpheader->icmp_id == htons(ident) 1405 && icmpheader->icmp_seq == htons(seq)); 1406} 1407 1408void 1409udp_prep(struct outdata *outdata) 1410{ 1411 struct udphdr *const outudp = (struct udphdr *) outp; 1412 1413 outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0)); 1414 outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq)); 1415 outudp->uh_ulen = htons((u_short)protlen); 1416 outudp->uh_sum = 0; 1417 if (doipcksum) { 1418 u_short sum = p_cksum(outip, (u_short*)outudp, protlen, protlen); 1419 outudp->uh_sum = (sum) ? sum : 0xffff; 1420 } 1421 1422 return; 1423} 1424 1425int 1426udp_check(const u_char *data, int seq) 1427{ 1428 struct udphdr *const udp = (struct udphdr *) data; 1429 1430 return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) && 1431 ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq)); 1432} 1433 1434void 1435udplite_prep(struct outdata *outdata) 1436{ 1437 struct udphdr *const outudp = (struct udphdr *) outp; 1438 1439 outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0)); 1440 outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq)); 1441 outudp->uh_ulen = htons(8); 1442 outudp->uh_sum = 0; 1443 if (doipcksum) { 1444 u_short sum = p_cksum(outip, (u_short*)outudp, protlen, 8); 1445 outudp->uh_sum = (sum) ? sum : 0xffff; 1446 } 1447 1448 return; 1449} 1450 1451int 1452udplite_check(const u_char *data, int seq) 1453{ 1454 struct udphdr *const udp = (struct udphdr *) data; 1455 1456 return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) && 1457 ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq)); 1458} 1459 1460void 1461tcp_prep(struct outdata *outdata) 1462{ 1463 struct tcphdr *const tcp = (struct tcphdr *) outp; 1464 1465 tcp->th_sport = htons(ident); 1466 tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq)); 1467 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport; 1468 tcp->th_ack = 0; 1469 tcp->th_off = 5; 1470 tcp->th_flags = TH_SYN; 1471 tcp->th_sum = 0; 1472 1473 if (doipcksum) 1474 tcp->th_sum = p_cksum(outip, (u_short*)tcp, protlen, protlen); 1475} 1476 1477int 1478tcp_check(const u_char *data, int seq) 1479{ 1480 struct tcphdr *const tcp = (struct tcphdr *) data; 1481 1482 return (ntohs(tcp->th_sport) == ident 1483 && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq) 1484 && tcp->th_seq == (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport)); 1485} 1486 1487void 1488sctp_prep(struct outdata *outdata) 1489{ 1490 struct sctphdr *const sctp = (struct sctphdr *) outp; 1491 struct sctp_chunkhdr *chk; 1492 1493 sctp->src_port = htons(ident); 1494 sctp->dest_port = htons(port + (fixedPort ? 0 : outdata->seq)); 1495 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port; 1496 sctp->checksum = htonl(0); 1497 if (protlen >= 1498 (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))) { 1499 chk = (struct sctp_chunkhdr *)(sctp + 1); 1500 chk->chunk_type = SCTP_SHUTDOWN_ACK; 1501 chk->chunk_flags = 0; 1502 chk->chunk_length = htons(4); 1503 } 1504 if (protlen >= 1505 (int)(sizeof(struct sctphdr) + 2 * sizeof(struct sctp_chunkhdr))) { 1506 chk = chk + 1; 1507 chk->chunk_type = SCTP_PAD_CHUNK; 1508 chk->chunk_flags = 0; 1509 chk->chunk_length = htons(protlen - 1510 (sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))); 1511 } 1512 if (doipcksum) { 1513 sctp->checksum = sctp_crc32c(sctp, protlen); 1514 } 1515} 1516 1517int 1518sctp_check(const u_char *data, int seq) 1519{ 1520 struct sctphdr *const sctp = (struct sctphdr *) data; 1521 1522 return (ntohs(sctp->src_port) == ident 1523 && ntohs(sctp->dest_port) == port + (fixedPort ? 0 : seq) 1524 && sctp->v_tag == 1525 (u_int32_t)((sctp->src_port << 16) | sctp->dest_port)); 1526} 1527 1528void 1529gre_prep(struct outdata *outdata) 1530{ 1531 struct grehdr *const gre = (struct grehdr *) outp; 1532 1533 gre->flags = htons(0x2001); 1534 gre->proto = htons(port); 1535 gre->length = 0; 1536 gre->callId = htons(ident + outdata->seq); 1537} 1538 1539int 1540gre_check(const u_char *data, int seq) 1541{ 1542 struct grehdr *const gre = (struct grehdr *) data; 1543 1544 return(ntohs(gre->proto) == port 1545 && ntohs(gre->callId) == ident + seq); 1546} 1547 1548void 1549gen_prep(struct outdata *outdata) 1550{ 1551 u_int16_t *const ptr = (u_int16_t *) outp; 1552 1553 ptr[0] = htons(ident); 1554 ptr[1] = htons(port + outdata->seq); 1555} 1556 1557int 1558gen_check(const u_char *data, int seq) 1559{ 1560 u_int16_t *const ptr = (u_int16_t *) data; 1561 1562 return(ntohs(ptr[0]) == ident 1563 && ntohs(ptr[1]) == port + seq); 1564} 1565 1566void 1567print(register u_char *buf, register int cc, register struct sockaddr_in *from) 1568{ 1569 register struct ip *ip; 1570 register int hlen; 1571 char addr[INET_ADDRSTRLEN]; 1572 1573 ip = (struct ip *) buf; 1574 hlen = ip->ip_hl << 2; 1575 cc -= hlen; 1576 1577 strlcpy(addr, inet_ntoa(from->sin_addr), sizeof(addr)); 1578 1579 if (as_path) 1580 Printf(" [AS%u]", as_lookup(asn, addr, AF_INET)); 1581 1582 if (nflag) 1583 Printf(" %s", addr); 1584 else 1585 Printf(" %s (%s)", inetname(from->sin_addr), addr); 1586 1587 if (verbose) 1588 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); 1589} 1590 1591/* 1592 * Checksum routine for UDP and TCP headers. 1593 */ 1594u_short 1595p_cksum(struct ip *ip, u_short *data, int len, int cov) 1596{ 1597 static struct ipovly ipo; 1598 u_short sum[2]; 1599 1600 ipo.ih_pr = ip->ip_p; 1601 ipo.ih_len = htons(len); 1602 ipo.ih_src = ip->ip_src; 1603 ipo.ih_dst = ip->ip_dst; 1604 1605 sum[1] = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */ 1606 sum[0] = in_cksum(data, cov); /* payload data cksum */ 1607 1608 return ~in_cksum(sum, sizeof(sum)); 1609} 1610 1611/* 1612 * Checksum routine for Internet Protocol family headers (C Version) 1613 */ 1614u_short 1615in_cksum(register u_short *addr, register int len) 1616{ 1617 register int nleft = len; 1618 register u_short *w = addr; 1619 register u_short answer; 1620 register int sum = 0; 1621 1622 /* 1623 * Our algorithm is simple, using a 32 bit accumulator (sum), 1624 * we add sequential 16 bit words to it, and at the end, fold 1625 * back all the carry bits from the top 16 bits into the lower 1626 * 16 bits. 1627 */ 1628 while (nleft > 1) { 1629 sum += *w++; 1630 nleft -= 2; 1631 } 1632 1633 /* mop up an odd byte, if necessary */ 1634 if (nleft == 1) 1635 sum += *(u_char *)w; 1636 1637 /* 1638 * add back carry outs from top 16 bits to low 16 bits 1639 */ 1640 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1641 sum += (sum >> 16); /* add carry */ 1642 answer = ~sum; /* truncate to 16 bits */ 1643 return (answer); 1644} 1645 1646/* 1647 * CRC32C routine for the Stream Control Transmission Protocol 1648 */ 1649 1650#define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF]) 1651 1652static u_int32_t crc_c[256] = { 1653 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 1654 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 1655 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 1656 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 1657 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 1658 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 1659 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 1660 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 1661 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 1662 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 1663 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 1664 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 1665 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 1666 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 1667 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 1668 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 1669 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 1670 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 1671 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 1672 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 1673 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 1674 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 1675 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 1676 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 1677 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 1678 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 1679 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 1680 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 1681 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 1682 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 1683 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 1684 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 1685 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 1686 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 1687 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 1688 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 1689 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 1690 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 1691 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 1692 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 1693 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 1694 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 1695 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 1696 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 1697 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 1698 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 1699 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 1700 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 1701 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 1702 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 1703 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 1704 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 1705 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 1706 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 1707 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 1708 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 1709 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 1710 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 1711 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 1712 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 1713 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 1714 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 1715 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 1716 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 1717}; 1718 1719u_int32_t 1720sctp_crc32c(const void *packet, u_int32_t len) 1721{ 1722 u_int32_t i, crc32c; 1723 u_int8_t byte0, byte1, byte2, byte3; 1724 const u_int8_t *buf = (const u_int8_t *)packet; 1725 1726 crc32c = ~0; 1727 for (i = 0; i < len; i++) 1728 CRC32C(crc32c, buf[i]); 1729 crc32c = ~crc32c; 1730 byte0 = crc32c & 0xff; 1731 byte1 = (crc32c>>8) & 0xff; 1732 byte2 = (crc32c>>16) & 0xff; 1733 byte3 = (crc32c>>24) & 0xff; 1734 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); 1735 return htonl(crc32c); 1736} 1737 1738/* 1739 * Subtract 2 timeval structs: out = out - in. 1740 * Out is assumed to be within about LONG_MAX seconds of in. 1741 */ 1742void 1743tvsub(register struct timeval *out, register struct timeval *in) 1744{ 1745 1746 if ((out->tv_usec -= in->tv_usec) < 0) { 1747 --out->tv_sec; 1748 out->tv_usec += 1000000; 1749 } 1750 out->tv_sec -= in->tv_sec; 1751} 1752 1753/* 1754 * Construct an Internet address representation. 1755 * If the nflag has been supplied, give 1756 * numeric value, otherwise try for symbolic name. 1757 */ 1758char * 1759inetname(struct in_addr in) 1760{ 1761 register char *cp; 1762 register struct hostent *hp; 1763 static int first = 1; 1764 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1]; 1765 1766 if (first && !nflag) { 1767 first = 0; 1768 if (gethostname(domain, sizeof(domain) - 1) < 0) 1769 domain[0] = '\0'; 1770 else { 1771 cp = strchr(domain, '.'); 1772 if (cp == NULL) { 1773 hp = gethostbyname(domain); 1774 if (hp != NULL) 1775 cp = strchr(hp->h_name, '.'); 1776 } 1777 if (cp == NULL) 1778 domain[0] = '\0'; 1779 else { 1780 ++cp; 1781 (void)strncpy(domain, cp, sizeof(domain) - 1); 1782 domain[sizeof(domain) - 1] = '\0'; 1783 } 1784 } 1785 } 1786 if (!nflag && in.s_addr != INADDR_ANY) { 1787 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); 1788 if (hp != NULL) { 1789 if ((cp = strchr(hp->h_name, '.')) != NULL && 1790 strcmp(cp + 1, domain) == 0) 1791 *cp = '\0'; 1792 (void)strncpy(line, hp->h_name, sizeof(line) - 1); 1793 line[sizeof(line) - 1] = '\0'; 1794 return (line); 1795 } 1796 } 1797 return (inet_ntoa(in)); 1798} 1799 1800struct hostinfo * 1801gethostinfo(register char *hostname) 1802{ 1803 register int n; 1804 register struct hostent *hp; 1805 register struct hostinfo *hi; 1806 register char **p; 1807 register u_int32_t addr, *ap; 1808 1809 if (strlen(hostname) >= MAXHOSTNAMELEN) { 1810 Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n", 1811 prog, hostname); 1812 exit(1); 1813 } 1814 hi = calloc(1, sizeof(*hi)); 1815 if (hi == NULL) { 1816 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno)); 1817 exit(1); 1818 } 1819 addr = inet_addr(hostname); 1820 if ((int32_t)addr != -1) { 1821 hi->name = strdup(hostname); 1822 hi->n = 1; 1823 hi->addrs = calloc(1, sizeof(hi->addrs[0])); 1824 if (hi->addrs == NULL) { 1825 Fprintf(stderr, "%s: calloc %s\n", 1826 prog, strerror(errno)); 1827 exit(1); 1828 } 1829 hi->addrs[0] = addr; 1830 return (hi); 1831 } 1832 1833 hp = gethostbyname(hostname); 1834 if (hp == NULL) { 1835 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname); 1836 exit(1); 1837 } 1838 if (hp->h_addrtype != AF_INET || hp->h_length != 4) { 1839 Fprintf(stderr, "%s: bad host %s\n", prog, hostname); 1840 exit(1); 1841 } 1842 hi->name = strdup(hp->h_name); 1843 for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p) 1844 continue; 1845 hi->n = n; 1846 hi->addrs = calloc(n, sizeof(hi->addrs[0])); 1847 if (hi->addrs == NULL) { 1848 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno)); 1849 exit(1); 1850 } 1851 for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p) 1852 memcpy(ap, *p, sizeof(*ap)); 1853 return (hi); 1854} 1855 1856void 1857freehostinfo(register struct hostinfo *hi) 1858{ 1859 if (hi->name != NULL) { 1860 free(hi->name); 1861 hi->name = NULL; 1862 } 1863 free((char *)hi->addrs); 1864 free((char *)hi); 1865} 1866 1867void 1868getaddr(register u_int32_t *ap, register char *hostname) 1869{ 1870 register struct hostinfo *hi; 1871 1872 hi = gethostinfo(hostname); 1873 *ap = hi->addrs[0]; 1874 freehostinfo(hi); 1875} 1876 1877void 1878setsin(register struct sockaddr_in *sin, register u_int32_t addr) 1879{ 1880 1881 memset(sin, 0, sizeof(*sin)); 1882#ifdef HAVE_SOCKADDR_SA_LEN 1883 sin->sin_len = sizeof(*sin); 1884#endif 1885 sin->sin_family = AF_INET; 1886 sin->sin_addr.s_addr = addr; 1887} 1888 1889/* String to value with optional min and max. Handles decimal and hex. */ 1890int 1891str2val(register const char *str, register const char *what, 1892 register int mi, register int ma) 1893{ 1894 register const char *cp; 1895 register int val; 1896 char *ep; 1897 1898 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { 1899 cp = str + 2; 1900 val = (int)strtol(cp, &ep, 16); 1901 } else 1902 val = (int)strtol(str, &ep, 10); 1903 if (*ep != '\0') { 1904 Fprintf(stderr, "%s: \"%s\" bad value for %s \n", 1905 prog, str, what); 1906 exit(1); 1907 } 1908 if (val < mi && mi >= 0) { 1909 if (mi == 0) 1910 Fprintf(stderr, "%s: %s must be >= %d\n", 1911 prog, what, mi); 1912 else 1913 Fprintf(stderr, "%s: %s must be > %d\n", 1914 prog, what, mi - 1); 1915 exit(1); 1916 } 1917 if (val > ma && ma >= 0) { 1918 Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma); 1919 exit(1); 1920 } 1921 return (val); 1922} 1923 1924struct outproto * 1925setproto(char *pname) 1926{ 1927 struct outproto *proto; 1928 int i; 1929 1930 for (i = 0; protos[i].name != NULL; i++) { 1931 if (strcasecmp(protos[i].name, pname) == 0) { 1932 break; 1933 } 1934 } 1935 proto = &protos[i]; 1936 if (proto->name == NULL) { /* generic handler */ 1937 struct protoent *pe; 1938 u_long pnum; 1939 1940 /* Determine the IP protocol number */ 1941 if ((pe = getprotobyname(pname)) != NULL) 1942 pnum = pe->p_proto; 1943 else 1944 pnum = str2val(optarg, "proto number", 1, 255); 1945 proto->num = pnum; 1946 } 1947 return proto; 1948} 1949 1950void 1951pkt_compare(const u_char *a, int la, const u_char *b, int lb) { 1952 int l; 1953 int i; 1954 1955 for (i = 0; i < la; i++) 1956 Printf("%02x", (unsigned int)a[i]); 1957 Printf("\n"); 1958 l = (la <= lb) ? la : lb; 1959 for (i = 0; i < l; i++) 1960 if (a[i] == b[i]) 1961 Printf("__"); 1962 else 1963 Printf("%02x", (unsigned int)b[i]); 1964 for (; i < lb; i++) 1965 Printf("%02x", (unsigned int)b[i]); 1966 Printf("\n"); 1967} 1968 1969 1970void 1971usage(void) 1972{ 1973 extern char version[]; 1974 1975 Fprintf(stderr, "Version %s\n", version); 1976 Fprintf(stderr, 1977 "Usage: %s [-adDeFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n" 1978 "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n" 1979 "\t[-t tos] [-w waittime] [-A as_server] [-z pausemsecs] host [packetlen]\n", prog); 1980 exit(1); 1981} 1982