19b7a920aSLexi Winter /*
29b7a920aSLexi Winter * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
39b7a920aSLexi Winter * The Regents of the University of California. All rights reserved.
49b7a920aSLexi Winter *
59b7a920aSLexi Winter * Redistribution and use in source and binary forms, with or without
69b7a920aSLexi Winter * modification, are permitted provided that: (1) source code distributions
79b7a920aSLexi Winter * retain the above copyright notice and this paragraph in its entirety, (2)
89b7a920aSLexi Winter * distributions including binary code include the above copyright notice and
99b7a920aSLexi Winter * this paragraph in its entirety in the documentation or other materials
109b7a920aSLexi Winter * provided with the distribution, and (3) all advertising materials mentioning
119b7a920aSLexi Winter * features or use of this software display the following acknowledgement:
129b7a920aSLexi Winter * ``This product includes software developed by the University of California,
139b7a920aSLexi Winter * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
149b7a920aSLexi Winter * the University nor the names of its contributors may be used to endorse
159b7a920aSLexi Winter * or promote products derived from this software without specific prior
169b7a920aSLexi Winter * written permission.
179b7a920aSLexi Winter * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
189b7a920aSLexi Winter * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
199b7a920aSLexi Winter * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
209b7a920aSLexi Winter */
219b7a920aSLexi Winter
229b7a920aSLexi Winter /*
239b7a920aSLexi Winter * traceroute host - trace the route ip packets follow going to "host".
249b7a920aSLexi Winter *
259b7a920aSLexi Winter * Attempt to trace the route an ip packet would follow to some
269b7a920aSLexi Winter * internet host. We find out intermediate hops by launching probe
279b7a920aSLexi Winter * packets with a small ttl (time to live) then listening for an
289b7a920aSLexi Winter * icmp "time exceeded" reply from a gateway. We start our probes
299b7a920aSLexi Winter * with a ttl of one and increase by one until we get an icmp "port
309b7a920aSLexi Winter * unreachable" (which means we got to "host") or hit a max (which
319b7a920aSLexi Winter * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
329b7a920aSLexi Winter * Three probes (change with -q flag) are sent at each ttl setting and
339b7a920aSLexi Winter * a line is printed showing the ttl, address of the gateway and
349b7a920aSLexi Winter * round trip time of each probe. If the probe answers come from
359b7a920aSLexi Winter * different gateways, the address of each responding system will
369b7a920aSLexi Winter * be printed. If there is no response within a 5 sec. timeout
379b7a920aSLexi Winter * interval (changed with the -w flag), a "*" is printed for that
389b7a920aSLexi Winter * probe.
399b7a920aSLexi Winter *
409b7a920aSLexi Winter * Probe packets are UDP format. We don't want the destination
419b7a920aSLexi Winter * host to process them so the destination port is set to an
429b7a920aSLexi Winter * unlikely value (if some clod on the destination is using that
439b7a920aSLexi Winter * value, it can be changed with the -p flag).
449b7a920aSLexi Winter *
459b7a920aSLexi Winter * A sample use might be:
469b7a920aSLexi Winter *
479b7a920aSLexi Winter * [yak 71]% traceroute nis.nsf.net.
489b7a920aSLexi Winter * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 40 byte packets
499b7a920aSLexi Winter * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
509b7a920aSLexi Winter * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
519b7a920aSLexi Winter * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
529b7a920aSLexi Winter * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
539b7a920aSLexi Winter * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
549b7a920aSLexi Winter * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
559b7a920aSLexi Winter * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
569b7a920aSLexi Winter * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
579b7a920aSLexi Winter * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
589b7a920aSLexi Winter * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
599b7a920aSLexi Winter * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
609b7a920aSLexi Winter *
619b7a920aSLexi Winter * Note that lines 2 & 3 are the same. This is due to a buggy
629b7a920aSLexi Winter * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
639b7a920aSLexi Winter * packets with a zero ttl.
649b7a920aSLexi Winter *
659b7a920aSLexi Winter * A more interesting example is:
669b7a920aSLexi Winter *
679b7a920aSLexi Winter * [yak 72]% traceroute allspice.lcs.mit.edu.
689b7a920aSLexi Winter * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max, 40 byte packets
699b7a920aSLexi Winter * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
709b7a920aSLexi Winter * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
719b7a920aSLexi Winter * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
729b7a920aSLexi Winter * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
739b7a920aSLexi Winter * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
749b7a920aSLexi Winter * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
759b7a920aSLexi Winter * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
769b7a920aSLexi Winter * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
779b7a920aSLexi Winter * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
789b7a920aSLexi Winter * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
799b7a920aSLexi Winter * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
809b7a920aSLexi Winter * 12 * * *
819b7a920aSLexi Winter * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
829b7a920aSLexi Winter * 14 * * *
839b7a920aSLexi Winter * 15 * * *
849b7a920aSLexi Winter * 16 * * *
859b7a920aSLexi Winter * 17 * * *
869b7a920aSLexi Winter * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
879b7a920aSLexi Winter *
889b7a920aSLexi Winter * (I start to see why I'm having so much trouble with mail to
899b7a920aSLexi Winter * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
909b7a920aSLexi Winter * either don't send ICMP "time exceeded" messages or send them
919b7a920aSLexi Winter * with a ttl too small to reach us. 14 - 17 are running the
929b7a920aSLexi Winter * MIT C Gateway code that doesn't send "time exceeded"s. God
939b7a920aSLexi Winter * only knows what's going on with 12.
949b7a920aSLexi Winter *
959b7a920aSLexi Winter * The silent gateway 12 in the above may be the result of a bug in
969b7a920aSLexi Winter * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
979b7a920aSLexi Winter * sends an unreachable message using whatever ttl remains in the
989b7a920aSLexi Winter * original datagram. Since, for gateways, the remaining ttl is
999b7a920aSLexi Winter * zero, the icmp "time exceeded" is guaranteed to not make it back
1009b7a920aSLexi Winter * to us. The behavior of this bug is slightly more interesting
1019b7a920aSLexi Winter * when it appears on the destination system:
1029b7a920aSLexi Winter *
1039b7a920aSLexi Winter * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
1049b7a920aSLexi Winter * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
1059b7a920aSLexi Winter * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
1069b7a920aSLexi Winter * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
1079b7a920aSLexi Winter * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
1089b7a920aSLexi Winter * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
1099b7a920aSLexi Winter * 7 * * *
1109b7a920aSLexi Winter * 8 * * *
1119b7a920aSLexi Winter * 9 * * *
1129b7a920aSLexi Winter * 10 * * *
1139b7a920aSLexi Winter * 11 * * *
1149b7a920aSLexi Winter * 12 * * *
1159b7a920aSLexi Winter * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
1169b7a920aSLexi Winter *
1179b7a920aSLexi Winter * Notice that there are 12 "gateways" (13 is the final
1189b7a920aSLexi Winter * destination) and exactly the last half of them are "missing".
1199b7a920aSLexi Winter * What's really happening is that rip (a Sun-3 running Sun OS3.5)
1209b7a920aSLexi Winter * is using the ttl from our arriving datagram as the ttl in its
1219b7a920aSLexi Winter * icmp reply. So, the reply will time out on the return path
1229b7a920aSLexi Winter * (with no notice sent to anyone since icmp's aren't sent for
1239b7a920aSLexi Winter * icmp's) until we probe with a ttl that's at least twice the path
1249b7a920aSLexi Winter * length. I.e., rip is really only 7 hops away. A reply that
1259b7a920aSLexi Winter * returns with a ttl of 1 is a clue this problem exists.
1269b7a920aSLexi Winter * Traceroute prints a "!" after the time if the ttl is <= 1.
1279b7a920aSLexi Winter * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
1289b7a920aSLexi Winter * non-standard (HPUX) software, expect to see this problem
1299b7a920aSLexi Winter * frequently and/or take care picking the target host of your
1309b7a920aSLexi Winter * probes.
1319b7a920aSLexi Winter *
1329b7a920aSLexi Winter * Other possible annotations after the time are !H, !N, !P (got a host,
1339b7a920aSLexi Winter * network or protocol unreachable, respectively), !S or !F (source
1349b7a920aSLexi Winter * route failed or fragmentation needed -- neither of these should
1359b7a920aSLexi Winter * ever occur and the associated gateway is busted if you see one). If
1369b7a920aSLexi Winter * almost all the probes result in some kind of unreachable, traceroute
1379b7a920aSLexi Winter * will give up and exit.
1389b7a920aSLexi Winter *
1399b7a920aSLexi Winter * Notes
1409b7a920aSLexi Winter * -----
1419b7a920aSLexi Winter * This program must be run by root or be setuid. (I suggest that
1429b7a920aSLexi Winter * you *don't* make it setuid -- casual use could result in a lot
1439b7a920aSLexi Winter * of unnecessary traffic on our poor, congested nets.)
1449b7a920aSLexi Winter *
1459b7a920aSLexi Winter * This program requires a kernel mod that does not appear in any
1469b7a920aSLexi Winter * system available from Berkeley: A raw ip socket using proto
1479b7a920aSLexi Winter * IPPROTO_RAW must interpret the data sent as an ip datagram (as
1489b7a920aSLexi Winter * opposed to data to be wrapped in an ip datagram). See the README
1499b7a920aSLexi Winter * file that came with the source to this program for a description
1509b7a920aSLexi Winter * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
1519b7a920aSLexi Winter * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
1529b7a920aSLexi Winter * MODIFIED TO RUN THIS PROGRAM.
1539b7a920aSLexi Winter *
1549b7a920aSLexi Winter * The udp port usage may appear bizarre (well, ok, it is bizarre).
1559b7a920aSLexi Winter * The problem is that an icmp message only contains 8 bytes of
1569b7a920aSLexi Winter * data from the original datagram. 8 bytes is the size of a udp
1579b7a920aSLexi Winter * header so, if we want to associate replies with the original
1589b7a920aSLexi Winter * datagram, the necessary information must be encoded into the
1599b7a920aSLexi Winter * udp header (the ip id could be used but there's no way to
1609b7a920aSLexi Winter * interlock with the kernel's assignment of ip id's and, anyway,
1619b7a920aSLexi Winter * it would have taken a lot more kernel hacking to allow this
1629b7a920aSLexi Winter * code to set the ip id). So, to allow two or more users to
1639b7a920aSLexi Winter * use traceroute simultaneously, we use this task's pid as the
1649b7a920aSLexi Winter * source port (the high bit is set to move the port number out
1659b7a920aSLexi Winter * of the "likely" range). To keep track of which probe is being
1669b7a920aSLexi Winter * replied to (so times and/or hop counts don't get confused by a
1679b7a920aSLexi Winter * reply that was delayed in transit), we increment the destination
1689b7a920aSLexi Winter * port number before each probe.
1699b7a920aSLexi Winter *
1709b7a920aSLexi Winter * Don't use this as a coding example. I was trying to find a
1719b7a920aSLexi Winter * routing problem and this code sort-of popped out after 48 hours
1729b7a920aSLexi Winter * without sleep. I was amazed it ever compiled, much less ran.
1739b7a920aSLexi Winter *
1749b7a920aSLexi Winter * I stole the idea for this program from Steve Deering. Since
1759b7a920aSLexi Winter * the first release, I've learned that had I attended the right
1769b7a920aSLexi Winter * IETF working group meetings, I also could have stolen it from Guy
1779b7a920aSLexi Winter * Almes or Matt Mathis. I don't know (or care) who came up with
1789b7a920aSLexi Winter * the idea first. I envy the originators' perspicacity and I'm
1799b7a920aSLexi Winter * glad they didn't keep the idea a secret.
1809b7a920aSLexi Winter *
1819b7a920aSLexi Winter * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
1829b7a920aSLexi Winter * enhancements to the original distribution.
1839b7a920aSLexi Winter *
1849b7a920aSLexi Winter * I've hacked up a round-trip-route version of this that works by
1859b7a920aSLexi Winter * sending a loose-source-routed udp datagram through the destination
1869b7a920aSLexi Winter * back to yourself. Unfortunately, SO many gateways botch source
1879b7a920aSLexi Winter * routing, the thing is almost worthless. Maybe one day...
1889b7a920aSLexi Winter *
1899b7a920aSLexi Winter * -- Van Jacobson (van@ee.lbl.gov)
1909b7a920aSLexi Winter * Tue Dec 20 03:50:13 PST 1988
1919b7a920aSLexi Winter */
1929b7a920aSLexi Winter
1939b7a920aSLexi Winter #include <sys/param.h>
1949b7a920aSLexi Winter #include <sys/capsicum.h>
1959b7a920aSLexi Winter #include <sys/file.h>
1969b7a920aSLexi Winter #include <sys/ioctl.h>
1979b7a920aSLexi Winter #include <sys/select.h>
1989b7a920aSLexi Winter #include <sys/socket.h>
1999b7a920aSLexi Winter #include <sys/sysctl.h>
2009b7a920aSLexi Winter #include <sys/time.h>
2019b7a920aSLexi Winter
2029b7a920aSLexi Winter #include <netinet/in_systm.h>
2039b7a920aSLexi Winter #include <netinet/in.h>
2049b7a920aSLexi Winter #include <netinet/ip.h>
2059b7a920aSLexi Winter #include <netinet/ip_var.h>
2069b7a920aSLexi Winter #include <netinet/ip_icmp.h>
2079b7a920aSLexi Winter #include <netinet/sctp.h>
2089b7a920aSLexi Winter #include <netinet/sctp_header.h>
2099b7a920aSLexi Winter #include <netinet/udp.h>
2109b7a920aSLexi Winter #include <netinet/tcp.h>
2119b7a920aSLexi Winter #include <netinet/tcpip.h>
2129b7a920aSLexi Winter
2139b7a920aSLexi Winter #include <arpa/inet.h>
2149b7a920aSLexi Winter
2159b7a920aSLexi Winter #ifdef WITH_CASPER
2169b7a920aSLexi Winter #include <libcasper.h>
2179b7a920aSLexi Winter #include <casper/cap_dns.h>
2189b7a920aSLexi Winter #endif
2199b7a920aSLexi Winter
2209b7a920aSLexi Winter #ifdef IPSEC
2219b7a920aSLexi Winter #include <net/route.h>
2229b7a920aSLexi Winter #include <netipsec/ipsec.h> /* XXX */
2239b7a920aSLexi Winter #endif /* IPSEC */
2249b7a920aSLexi Winter
2259b7a920aSLexi Winter #include <ctype.h>
2269b7a920aSLexi Winter #include <capsicum_helpers.h>
2279b7a920aSLexi Winter #include <err.h>
2289b7a920aSLexi Winter #include <errno.h>
2299b7a920aSLexi Winter #include <fcntl.h>
2309b7a920aSLexi Winter #include <malloc.h>
2319b7a920aSLexi Winter #include <memory.h>
2329b7a920aSLexi Winter #include <netdb.h>
2339b7a920aSLexi Winter #include <stdio.h>
2349b7a920aSLexi Winter #include <stdlib.h>
2359b7a920aSLexi Winter #include <string.h>
2369b7a920aSLexi Winter #include <unistd.h>
2379b7a920aSLexi Winter
2389b7a920aSLexi Winter /* rfc1716 */
2399b7a920aSLexi Winter #ifndef ICMP_UNREACH_FILTER_PROHIB
2409b7a920aSLexi Winter #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
2419b7a920aSLexi Winter #endif
2429b7a920aSLexi Winter #ifndef ICMP_UNREACH_HOST_PRECEDENCE
2439b7a920aSLexi Winter #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
2449b7a920aSLexi Winter #endif
2459b7a920aSLexi Winter #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
2469b7a920aSLexi Winter #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
2479b7a920aSLexi Winter #endif
2489b7a920aSLexi Winter
2499b7a920aSLexi Winter #include "findsaddr.h"
2509b7a920aSLexi Winter #include "ifaddrlist.h"
2519b7a920aSLexi Winter #include "as.h"
2529b7a920aSLexi Winter #include "traceroute.h"
2539b7a920aSLexi Winter
2549b7a920aSLexi Winter /* Maximum number of gateways (include room for one noop) */
2559b7a920aSLexi Winter #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
2569b7a920aSLexi Winter
2579b7a920aSLexi Winter #ifndef MAXHOSTNAMELEN
2589b7a920aSLexi Winter #define MAXHOSTNAMELEN 64
2599b7a920aSLexi Winter #endif
2609b7a920aSLexi Winter
2619b7a920aSLexi Winter #define Fprintf (void)fprintf
2629b7a920aSLexi Winter #define Printf (void)printf
2639b7a920aSLexi Winter
2649b7a920aSLexi Winter /* What a GRE packet header looks like */
2659b7a920aSLexi Winter struct grehdr {
2669b7a920aSLexi Winter u_int16_t flags;
2679b7a920aSLexi Winter u_int16_t proto;
2689b7a920aSLexi Winter u_int16_t length; /* PPTP version of these fields */
2699b7a920aSLexi Winter u_int16_t callId;
2709b7a920aSLexi Winter };
2719b7a920aSLexi Winter #ifndef IPPROTO_GRE
2729b7a920aSLexi Winter #define IPPROTO_GRE 47
2739b7a920aSLexi Winter #endif
2749b7a920aSLexi Winter
2759b7a920aSLexi Winter /* For GRE, we prepare what looks like a PPTP packet */
2769b7a920aSLexi Winter #define GRE_PPTP_PROTO 0x880b
2779b7a920aSLexi Winter
2789b7a920aSLexi Winter /* Host name and address list */
2799b7a920aSLexi Winter struct hostinfo {
2809b7a920aSLexi Winter char *name;
2819b7a920aSLexi Winter int n;
2829b7a920aSLexi Winter u_int32_t *addrs;
2839b7a920aSLexi Winter };
2849b7a920aSLexi Winter
2859b7a920aSLexi Winter /* Data section of the probe packet */
2869b7a920aSLexi Winter struct outdata {
2879b7a920aSLexi Winter u_char seq; /* sequence number of this packet */
2889b7a920aSLexi Winter u_char ttl; /* ttl packet left with */
2899b7a920aSLexi Winter struct timeval tv; /* time packet left */
2909b7a920aSLexi Winter };
2919b7a920aSLexi Winter
2929b7a920aSLexi Winter u_char packet[512]; /* last inbound (icmp) packet */
2939b7a920aSLexi Winter
2949b7a920aSLexi Winter struct ip *outip; /* last output ip packet */
2959b7a920aSLexi Winter u_char *outp; /* last output inner protocol packet */
2969b7a920aSLexi Winter
2979b7a920aSLexi Winter struct ip *hip = NULL; /* Quoted IP header */
2989b7a920aSLexi Winter int hiplen = 0;
2999b7a920aSLexi Winter
3009b7a920aSLexi Winter /* loose source route gateway list (including room for final destination) */
3019b7a920aSLexi Winter u_int32_t gwlist[NGATEWAYS + 1];
3029b7a920aSLexi Winter
3039b7a920aSLexi Winter int s; /* receive (icmp) socket file descriptor */
3049b7a920aSLexi Winter int sndsock; /* send (udp) socket file descriptor */
3059b7a920aSLexi Winter
3069b7a920aSLexi Winter struct sockaddr whereto; /* Who to try to reach */
3079b7a920aSLexi Winter struct sockaddr wherefrom; /* Who we are */
3089b7a920aSLexi Winter int packlen; /* total length of packet */
3099b7a920aSLexi Winter int protlen; /* length of protocol part of packet */
3109b7a920aSLexi Winter int minpacket; /* min ip packet size */
3119b7a920aSLexi Winter int maxpacket = 32 * 1024; /* max ip packet size */
3129b7a920aSLexi Winter int pmtu; /* Path MTU Discovery (RFC1191) */
3139b7a920aSLexi Winter u_int pausemsecs;
3149b7a920aSLexi Winter
3159b7a920aSLexi Winter char *prog;
3169b7a920aSLexi Winter char *source;
3179b7a920aSLexi Winter char *hostname;
3189b7a920aSLexi Winter char *device;
3199b7a920aSLexi Winter static const char devnull[] = "/dev/null";
3209b7a920aSLexi Winter
3219b7a920aSLexi Winter int nprobes = -1;
3229b7a920aSLexi Winter int max_ttl;
3239b7a920aSLexi Winter int first_ttl = 1;
3249b7a920aSLexi Winter u_short ident;
3259b7a920aSLexi Winter u_short port; /* protocol specific base "port" */
3269b7a920aSLexi Winter
3279b7a920aSLexi Winter int options; /* socket options */
3289b7a920aSLexi Winter int verbose;
3299b7a920aSLexi Winter int waittime = 5; /* time to wait for response (in seconds) */
3309b7a920aSLexi Winter int nflag; /* print addresses numerically */
3319b7a920aSLexi Winter int as_path; /* print as numbers for each hop */
3329b7a920aSLexi Winter char *as_server = NULL;
3339b7a920aSLexi Winter void *asn;
3349b7a920aSLexi Winter #ifdef CANT_HACK_IPCKSUM
3359b7a920aSLexi Winter int doipcksum = 0; /* don't calculate ip checksums by default */
3369b7a920aSLexi Winter #else
3379b7a920aSLexi Winter int doipcksum = 1; /* calculate ip checksums by default */
3389b7a920aSLexi Winter #endif
3399b7a920aSLexi Winter int optlen; /* length of ip options */
3409b7a920aSLexi Winter int fixedPort = 0; /* Use fixed destination port for TCP and UDP */
3419b7a920aSLexi Winter int printdiff = 0; /* Print the difference between sent and quoted */
3429b7a920aSLexi Winter int ecnflag = 0; /* ECN bleaching detection flag */
3439b7a920aSLexi Winter
3449b7a920aSLexi Winter extern int optind;
3459b7a920aSLexi Winter extern int opterr;
3469b7a920aSLexi Winter extern char *optarg;
3479b7a920aSLexi Winter
3489b7a920aSLexi Winter #ifdef WITH_CASPER
3499b7a920aSLexi Winter static cap_channel_t *capdns;
3509b7a920aSLexi Winter #endif
3519b7a920aSLexi Winter
3529b7a920aSLexi Winter /* Forwards */
3539b7a920aSLexi Winter double deltaT(struct timeval *, struct timeval *);
3549b7a920aSLexi Winter void freehostinfo(struct hostinfo *);
3559b7a920aSLexi Winter void getaddr(u_int32_t *, char *);
3569b7a920aSLexi Winter struct hostinfo *gethostinfo(char *);
3579b7a920aSLexi Winter u_short in_cksum(u_short *, int);
3589b7a920aSLexi Winter u_int32_t sctp_crc32c(const void *, u_int32_t);
3599b7a920aSLexi Winter char *inetname(struct in_addr);
3609b7a920aSLexi Winter int main(int, char **);
3619b7a920aSLexi Winter u_short p_cksum(struct ip *, u_short *, int, int);
3629b7a920aSLexi Winter int packet_ok(u_char *, int, struct sockaddr_in *, int);
3639b7a920aSLexi Winter char *pr_type(u_char);
3649b7a920aSLexi Winter void print(u_char *, int, struct sockaddr_in *);
3659b7a920aSLexi Winter #ifdef IPSEC
3669b7a920aSLexi Winter int setpolicy(int so, char *policy);
3679b7a920aSLexi Winter #endif
3689b7a920aSLexi Winter void send_probe(int, int);
3699b7a920aSLexi Winter struct outproto *setproto(char *);
3709b7a920aSLexi Winter int str2val(const char *, const char *, int, int);
3719b7a920aSLexi Winter void tvsub(struct timeval *, struct timeval *);
3729b7a920aSLexi Winter void usage(void);
3739b7a920aSLexi Winter int wait_for_reply(int, struct sockaddr_in *, const struct timeval *);
3749b7a920aSLexi Winter void pkt_compare(const u_char *, int, const u_char *, int);
3759b7a920aSLexi Winter
3769b7a920aSLexi Winter void udp_prep(struct outdata *);
3779b7a920aSLexi Winter int udp_check(const u_char *, int);
3789b7a920aSLexi Winter void udplite_prep(struct outdata *);
3799b7a920aSLexi Winter int udplite_check(const u_char *, int);
3809b7a920aSLexi Winter void tcp_prep(struct outdata *);
3819b7a920aSLexi Winter int tcp_check(const u_char *, int);
3829b7a920aSLexi Winter void sctp_prep(struct outdata *);
3839b7a920aSLexi Winter int sctp_check(const u_char *, int);
3849b7a920aSLexi Winter void gre_prep(struct outdata *);
3859b7a920aSLexi Winter int gre_check(const u_char *, int);
3869b7a920aSLexi Winter void gen_prep(struct outdata *);
3879b7a920aSLexi Winter int gen_check(const u_char *, int);
3889b7a920aSLexi Winter void icmp_prep(struct outdata *);
3899b7a920aSLexi Winter int icmp_check(const u_char *, int);
3909b7a920aSLexi Winter
3919b7a920aSLexi Winter /* Descriptor structure for each outgoing protocol we support */
3929b7a920aSLexi Winter struct outproto {
3939b7a920aSLexi Winter char *name; /* name of protocol */
3949b7a920aSLexi Winter const char *key; /* An ascii key for the bytes of the header */
3959b7a920aSLexi Winter u_char num; /* IP protocol number */
3969b7a920aSLexi Winter u_short hdrlen; /* max size of protocol header */
3979b7a920aSLexi Winter u_short port; /* default base protocol-specific "port" */
3989b7a920aSLexi Winter void (*prepare)(struct outdata *);
3999b7a920aSLexi Winter /* finish preparing an outgoing packet */
4009b7a920aSLexi Winter int (*check)(const u_char *, int);
4019b7a920aSLexi Winter /* check an incoming packet */
4029b7a920aSLexi Winter };
4039b7a920aSLexi Winter
4049b7a920aSLexi Winter /* List of supported protocols. The first one is the default. The last
4059b7a920aSLexi Winter one is the handler for generic protocols not explicitly listed. */
4069b7a920aSLexi Winter struct outproto protos[] = {
4079b7a920aSLexi Winter {
4089b7a920aSLexi Winter "udp",
4099b7a920aSLexi Winter "spt dpt len sum",
4109b7a920aSLexi Winter IPPROTO_UDP,
4119b7a920aSLexi Winter sizeof(struct udphdr),
4129b7a920aSLexi Winter 32768 + 666,
4139b7a920aSLexi Winter udp_prep,
4149b7a920aSLexi Winter udp_check
4159b7a920aSLexi Winter },
4169b7a920aSLexi Winter {
4179b7a920aSLexi Winter "udplite",
4189b7a920aSLexi Winter "spt dpt cov sum",
4199b7a920aSLexi Winter IPPROTO_UDPLITE,
4209b7a920aSLexi Winter sizeof(struct udphdr),
4219b7a920aSLexi Winter 32768 + 666,
4229b7a920aSLexi Winter udplite_prep,
4239b7a920aSLexi Winter udplite_check
4249b7a920aSLexi Winter },
4259b7a920aSLexi Winter {
4269b7a920aSLexi Winter "tcp",
4279b7a920aSLexi Winter "spt dpt seq ack xxflwin sum urp",
4289b7a920aSLexi Winter IPPROTO_TCP,
4299b7a920aSLexi Winter sizeof(struct tcphdr),
4309b7a920aSLexi Winter 32768 + 666,
4319b7a920aSLexi Winter tcp_prep,
4329b7a920aSLexi Winter tcp_check
4339b7a920aSLexi Winter },
4349b7a920aSLexi Winter {
4359b7a920aSLexi Winter "sctp",
4369b7a920aSLexi Winter "spt dpt vtag crc tyfllen tyfllen ",
4379b7a920aSLexi Winter IPPROTO_SCTP,
4389b7a920aSLexi Winter sizeof(struct sctphdr),
4399b7a920aSLexi Winter 32768 + 666,
4409b7a920aSLexi Winter sctp_prep,
4419b7a920aSLexi Winter sctp_check
4429b7a920aSLexi Winter },
4439b7a920aSLexi Winter {
4449b7a920aSLexi Winter "gre",
4459b7a920aSLexi Winter "flg pro len clid",
4469b7a920aSLexi Winter IPPROTO_GRE,
4479b7a920aSLexi Winter sizeof(struct grehdr),
4489b7a920aSLexi Winter GRE_PPTP_PROTO,
4499b7a920aSLexi Winter gre_prep,
4509b7a920aSLexi Winter gre_check
4519b7a920aSLexi Winter },
4529b7a920aSLexi Winter {
4539b7a920aSLexi Winter "icmp",
4549b7a920aSLexi Winter "typ cod sum ",
4559b7a920aSLexi Winter IPPROTO_ICMP,
4569b7a920aSLexi Winter sizeof(struct icmp),
4579b7a920aSLexi Winter 0,
4589b7a920aSLexi Winter icmp_prep,
4599b7a920aSLexi Winter icmp_check
4609b7a920aSLexi Winter },
4619b7a920aSLexi Winter {
4629b7a920aSLexi Winter NULL,
4639b7a920aSLexi Winter "",
4649b7a920aSLexi Winter 0,
4659b7a920aSLexi Winter 2 * sizeof(u_short),
4669b7a920aSLexi Winter 0,
4679b7a920aSLexi Winter gen_prep,
4689b7a920aSLexi Winter gen_check
4699b7a920aSLexi Winter },
4709b7a920aSLexi Winter };
4719b7a920aSLexi Winter struct outproto *proto = &protos[0];
4729b7a920aSLexi Winter
4739b7a920aSLexi Winter const char *ip_hdr_key = "vhtslen id off tlprsum srcip dstip opts";
4749b7a920aSLexi Winter
4759b7a920aSLexi Winter int
main(int argc,char ** argv)4769b7a920aSLexi Winter main(int argc, char **argv)
4779b7a920aSLexi Winter {
4789b7a920aSLexi Winter register int op, code, n;
4799b7a920aSLexi Winter register char *cp;
4809b7a920aSLexi Winter register const char *err;
4819b7a920aSLexi Winter register u_int32_t *ap;
4829b7a920aSLexi Winter register struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
4839b7a920aSLexi Winter register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
4849b7a920aSLexi Winter register struct hostinfo *hi;
4859b7a920aSLexi Winter int on = 1;
4869b7a920aSLexi Winter register struct protoent *pe;
4879b7a920aSLexi Winter register int ttl, probe, i;
4889b7a920aSLexi Winter register int seq = 0;
4899b7a920aSLexi Winter int tos = 0, settos = 0;
4909b7a920aSLexi Winter register int lsrr = 0;
4919b7a920aSLexi Winter register u_short off = 0;
4929b7a920aSLexi Winter struct ifaddrlist *al;
4939b7a920aSLexi Winter char errbuf[132];
4949b7a920aSLexi Winter int requestPort = -1;
4959b7a920aSLexi Winter int sump = 0;
4969b7a920aSLexi Winter int sockerrno;
4979b7a920aSLexi Winter #ifdef WITH_CASPER
4989b7a920aSLexi Winter const char *types[] = { "NAME2ADDR", "ADDR2NAME" };
4999b7a920aSLexi Winter int families[1];
5009b7a920aSLexi Winter cap_channel_t *casper;
5019b7a920aSLexi Winter #endif
5029b7a920aSLexi Winter cap_rights_t rights;
5039b7a920aSLexi Winter bool cansandbox;
5049b7a920aSLexi Winter
5059b7a920aSLexi Winter /* Insure the socket fds won't be 0, 1 or 2 */
5069b7a920aSLexi Winter if (open(devnull, O_RDONLY) < 0 ||
5079b7a920aSLexi Winter open(devnull, O_RDONLY) < 0 ||
5089b7a920aSLexi Winter open(devnull, O_RDONLY) < 0) {
5099b7a920aSLexi Winter Fprintf(stderr, "%s: open \"%s\": %s\n",
5109b7a920aSLexi Winter prog, devnull, strerror(errno));
5119b7a920aSLexi Winter exit(1);
5129b7a920aSLexi Winter }
5139b7a920aSLexi Winter /*
5149b7a920aSLexi Winter * Do the setuid-required stuff first, then lose privileges ASAP.
5159b7a920aSLexi Winter * Do error checking for these two calls where they appeared in
5169b7a920aSLexi Winter * the original code.
5179b7a920aSLexi Winter */
5189b7a920aSLexi Winter cp = "icmp";
5199b7a920aSLexi Winter pe = getprotobyname(cp);
5209b7a920aSLexi Winter if (pe) {
5219b7a920aSLexi Winter if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
5229b7a920aSLexi Winter sockerrno = errno;
5239b7a920aSLexi Winter else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
5249b7a920aSLexi Winter sockerrno = errno;
5259b7a920aSLexi Winter }
5269b7a920aSLexi Winter
5279b7a920aSLexi Winter if (setuid(getuid()) != 0) {
5289b7a920aSLexi Winter perror("setuid()");
5299b7a920aSLexi Winter exit(1);
5309b7a920aSLexi Winter }
5319b7a920aSLexi Winter
5329b7a920aSLexi Winter #ifdef WITH_CASPER
5339b7a920aSLexi Winter casper = cap_init();
5349b7a920aSLexi Winter if (casper == NULL)
5359b7a920aSLexi Winter errx(1, "unable to create casper process");
5369b7a920aSLexi Winter capdns = cap_service_open(casper, "system.dns");
5379b7a920aSLexi Winter if (capdns == NULL)
5389b7a920aSLexi Winter errx(1, "unable to open system.dns service");
5399b7a920aSLexi Winter if (cap_dns_type_limit(capdns, types, 2) < 0)
5409b7a920aSLexi Winter errx(1, "unable to limit access to system.dns service");
5419b7a920aSLexi Winter families[0] = AF_INET;
5429b7a920aSLexi Winter if (cap_dns_family_limit(capdns, families, 1) < 0)
5439b7a920aSLexi Winter errx(1, "unable to limit access to system.dns service");
5449b7a920aSLexi Winter #endif /* WITH_CASPER */
5459b7a920aSLexi Winter
5469b7a920aSLexi Winter #ifdef IPCTL_DEFTTL
5479b7a920aSLexi Winter {
5489b7a920aSLexi Winter int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
5499b7a920aSLexi Winter size_t sz = sizeof(max_ttl);
5509b7a920aSLexi Winter
5519b7a920aSLexi Winter if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) {
5529b7a920aSLexi Winter perror("sysctl(net.inet.ip.ttl)");
5539b7a920aSLexi Winter exit(1);
5549b7a920aSLexi Winter }
5559b7a920aSLexi Winter }
5569b7a920aSLexi Winter #else /* !IPCTL_DEFTTL */
5579b7a920aSLexi Winter max_ttl = 30;
5589b7a920aSLexi Winter #endif
5599b7a920aSLexi Winter
5609b7a920aSLexi Winter #ifdef WITH_CASPER
5619b7a920aSLexi Winter cap_close(casper);
5629b7a920aSLexi Winter #endif
5639b7a920aSLexi Winter
5649b7a920aSLexi Winter if (argv[0] == NULL)
5659b7a920aSLexi Winter prog = "traceroute";
5669b7a920aSLexi Winter else if ((cp = strrchr(argv[0], '/')) != NULL)
5679b7a920aSLexi Winter prog = cp + 1;
5689b7a920aSLexi Winter else
5699b7a920aSLexi Winter prog = argv[0];
5709b7a920aSLexi Winter
5719b7a920aSLexi Winter opterr = 0;
5729b7a920aSLexi Winter while ((op = getopt(argc, argv, "aA:eEdDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF)
5739b7a920aSLexi Winter switch (op) {
5749b7a920aSLexi Winter case 'a':
5759b7a920aSLexi Winter as_path = 1;
5769b7a920aSLexi Winter break;
5779b7a920aSLexi Winter
5789b7a920aSLexi Winter case 'A':
5799b7a920aSLexi Winter as_path = 1;
5809b7a920aSLexi Winter as_server = optarg;
5819b7a920aSLexi Winter break;
5829b7a920aSLexi Winter
5839b7a920aSLexi Winter case 'd':
5849b7a920aSLexi Winter options |= SO_DEBUG;
5859b7a920aSLexi Winter break;
5869b7a920aSLexi Winter
5879b7a920aSLexi Winter case 'D':
5889b7a920aSLexi Winter printdiff = 1;
5899b7a920aSLexi Winter break;
5909b7a920aSLexi Winter
5919b7a920aSLexi Winter case 'e':
5929b7a920aSLexi Winter fixedPort = 1;
5939b7a920aSLexi Winter break;
5949b7a920aSLexi Winter
5959b7a920aSLexi Winter case 'E':
5969b7a920aSLexi Winter ecnflag = 1;
5979b7a920aSLexi Winter break;
5989b7a920aSLexi Winter
5999b7a920aSLexi Winter case 'f':
6009b7a920aSLexi Winter case 'M': /* FreeBSD compat. */
6019b7a920aSLexi Winter first_ttl = str2val(optarg, "first ttl", 1, 255);
6029b7a920aSLexi Winter break;
6039b7a920aSLexi Winter
6049b7a920aSLexi Winter case 'F':
6059b7a920aSLexi Winter off = IP_DF;
6069b7a920aSLexi Winter break;
6079b7a920aSLexi Winter
6089b7a920aSLexi Winter case 'g':
6099b7a920aSLexi Winter if (lsrr >= NGATEWAYS) {
6109b7a920aSLexi Winter Fprintf(stderr,
6119b7a920aSLexi Winter "%s: No more than %d gateways\n",
6129b7a920aSLexi Winter prog, NGATEWAYS);
6139b7a920aSLexi Winter exit(1);
6149b7a920aSLexi Winter }
6159b7a920aSLexi Winter getaddr(gwlist + lsrr, optarg);
6169b7a920aSLexi Winter ++lsrr;
6179b7a920aSLexi Winter break;
6189b7a920aSLexi Winter
6199b7a920aSLexi Winter case 'i':
6209b7a920aSLexi Winter device = optarg;
6219b7a920aSLexi Winter break;
6229b7a920aSLexi Winter
6239b7a920aSLexi Winter case 'I':
6249b7a920aSLexi Winter proto = setproto("icmp");
6259b7a920aSLexi Winter break;
6269b7a920aSLexi Winter
6279b7a920aSLexi Winter case 'm':
6289b7a920aSLexi Winter max_ttl = str2val(optarg, "max ttl", 1, 255);
6299b7a920aSLexi Winter break;
6309b7a920aSLexi Winter
6319b7a920aSLexi Winter case 'n':
6329b7a920aSLexi Winter ++nflag;
6339b7a920aSLexi Winter break;
6349b7a920aSLexi Winter
6359b7a920aSLexi Winter case 'P':
6369b7a920aSLexi Winter proto = setproto(optarg);
6379b7a920aSLexi Winter break;
6389b7a920aSLexi Winter
6399b7a920aSLexi Winter case 'p':
6409b7a920aSLexi Winter requestPort = (u_short)str2val(optarg, "port",
6419b7a920aSLexi Winter 1, (1 << 16) - 1);
6429b7a920aSLexi Winter break;
6439b7a920aSLexi Winter
6449b7a920aSLexi Winter case 'q':
6459b7a920aSLexi Winter nprobes = str2val(optarg, "nprobes", 1, -1);
6469b7a920aSLexi Winter break;
6479b7a920aSLexi Winter
6489b7a920aSLexi Winter case 'r':
6499b7a920aSLexi Winter options |= SO_DONTROUTE;
6509b7a920aSLexi Winter break;
6519b7a920aSLexi Winter
6529b7a920aSLexi Winter case 's':
6539b7a920aSLexi Winter /*
6549b7a920aSLexi Winter * set the ip source address of the outbound
6559b7a920aSLexi Winter * probe (e.g., on a multi-homed host).
6569b7a920aSLexi Winter */
6579b7a920aSLexi Winter source = optarg;
6589b7a920aSLexi Winter break;
6599b7a920aSLexi Winter
6609b7a920aSLexi Winter case 'S':
6619b7a920aSLexi Winter sump = 1;
6629b7a920aSLexi Winter break;
6639b7a920aSLexi Winter
6649b7a920aSLexi Winter case 't':
6659b7a920aSLexi Winter tos = str2val(optarg, "tos", 0, 255);
6669b7a920aSLexi Winter ++settos;
6679b7a920aSLexi Winter break;
6689b7a920aSLexi Winter
6699b7a920aSLexi Winter case 'v':
6709b7a920aSLexi Winter ++verbose;
6719b7a920aSLexi Winter break;
6729b7a920aSLexi Winter
6739b7a920aSLexi Winter case 'x':
6749b7a920aSLexi Winter doipcksum = (doipcksum == 0);
6759b7a920aSLexi Winter break;
6769b7a920aSLexi Winter
6779b7a920aSLexi Winter case 'w':
6789b7a920aSLexi Winter waittime = str2val(optarg, "wait time",
6799b7a920aSLexi Winter 1, 24 * 60 * 60);
6809b7a920aSLexi Winter break;
6819b7a920aSLexi Winter
6829b7a920aSLexi Winter case 'z':
6839b7a920aSLexi Winter pausemsecs = str2val(optarg, "pause msecs",
6849b7a920aSLexi Winter 0, 60 * 60 * 1000);
6859b7a920aSLexi Winter break;
6869b7a920aSLexi Winter
6879b7a920aSLexi Winter default:
6889b7a920aSLexi Winter usage();
6899b7a920aSLexi Winter }
6909b7a920aSLexi Winter
6919b7a920aSLexi Winter /* Set requested port, if any, else default for this protocol */
6929b7a920aSLexi Winter port = (requestPort != -1) ? requestPort : proto->port;
6939b7a920aSLexi Winter
6949b7a920aSLexi Winter if (nprobes == -1)
6959b7a920aSLexi Winter nprobes = printdiff ? 1 : 3;
6969b7a920aSLexi Winter
6979b7a920aSLexi Winter if (first_ttl > max_ttl) {
6989b7a920aSLexi Winter Fprintf(stderr,
6999b7a920aSLexi Winter "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
7009b7a920aSLexi Winter prog, first_ttl, max_ttl);
7019b7a920aSLexi Winter exit(1);
7029b7a920aSLexi Winter }
7039b7a920aSLexi Winter
7049b7a920aSLexi Winter if (!doipcksum)
7059b7a920aSLexi Winter Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog);
7069b7a920aSLexi Winter
7079b7a920aSLexi Winter if (lsrr > 0)
7089b7a920aSLexi Winter optlen = (lsrr + 1) * sizeof(gwlist[0]);
7099b7a920aSLexi Winter minpacket = sizeof(*outip) + proto->hdrlen + optlen;
7109b7a920aSLexi Winter if (minpacket > 40)
7119b7a920aSLexi Winter packlen = minpacket;
7129b7a920aSLexi Winter else
7139b7a920aSLexi Winter packlen = 40;
7149b7a920aSLexi Winter
7159b7a920aSLexi Winter /* Process destination and optional packet size */
7169b7a920aSLexi Winter switch (argc - optind) {
7179b7a920aSLexi Winter
7189b7a920aSLexi Winter case 2:
7199b7a920aSLexi Winter packlen = str2val(argv[optind + 1],
7209b7a920aSLexi Winter "packet length", minpacket, maxpacket);
7219b7a920aSLexi Winter /* Fall through */
7229b7a920aSLexi Winter
7239b7a920aSLexi Winter case 1:
7249b7a920aSLexi Winter hostname = argv[optind];
7259b7a920aSLexi Winter hi = gethostinfo(hostname);
7269b7a920aSLexi Winter setsin(to, hi->addrs[0]);
7279b7a920aSLexi Winter if (hi->n > 1)
7289b7a920aSLexi Winter Fprintf(stderr,
7299b7a920aSLexi Winter "%s: Warning: %s has multiple addresses; using %s\n",
7309b7a920aSLexi Winter prog, hostname, inet_ntoa(to->sin_addr));
7319b7a920aSLexi Winter hostname = hi->name;
7329b7a920aSLexi Winter hi->name = NULL;
7339b7a920aSLexi Winter freehostinfo(hi);
7349b7a920aSLexi Winter break;
7359b7a920aSLexi Winter
7369b7a920aSLexi Winter default:
7379b7a920aSLexi Winter usage();
7389b7a920aSLexi Winter }
7399b7a920aSLexi Winter
7409b7a920aSLexi Winter setlinebuf(stdout);
7419b7a920aSLexi Winter
7429b7a920aSLexi Winter protlen = packlen - sizeof(*outip) - optlen;
7439b7a920aSLexi Winter if ((proto->num == IPPROTO_SCTP) && (packlen & 3)) {
7449b7a920aSLexi Winter Fprintf(stderr, "%s: packet length must be a multiple of 4\n",
7459b7a920aSLexi Winter prog);
7469b7a920aSLexi Winter exit(1);
7479b7a920aSLexi Winter }
7489b7a920aSLexi Winter
7499b7a920aSLexi Winter outip = (struct ip *)malloc((unsigned)packlen);
7509b7a920aSLexi Winter if (outip == NULL) {
7519b7a920aSLexi Winter Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
7529b7a920aSLexi Winter exit(1);
7539b7a920aSLexi Winter }
7549b7a920aSLexi Winter memset((char *)outip, 0, packlen);
7559b7a920aSLexi Winter
7569b7a920aSLexi Winter outip->ip_v = IPVERSION;
7579b7a920aSLexi Winter if (settos)
7589b7a920aSLexi Winter outip->ip_tos = tos;
7599b7a920aSLexi Winter if (ecnflag) {
7609b7a920aSLexi Winter outip->ip_tos &= ~IPTOS_ECN_MASK;
7619b7a920aSLexi Winter outip->ip_tos |= IPTOS_ECN_ECT1;
7629b7a920aSLexi Winter }
7639b7a920aSLexi Winter outip->ip_len = htons(packlen);
7649b7a920aSLexi Winter outip->ip_off = htons(off);
7659b7a920aSLexi Winter outip->ip_p = proto->num;
7669b7a920aSLexi Winter outp = (u_char *)(outip + 1);
7679b7a920aSLexi Winter if (lsrr > 0) {
7689b7a920aSLexi Winter register u_char *optlist;
7699b7a920aSLexi Winter
7709b7a920aSLexi Winter optlist = outp;
7719b7a920aSLexi Winter outp += optlen;
7729b7a920aSLexi Winter
7739b7a920aSLexi Winter /* final hop */
7749b7a920aSLexi Winter gwlist[lsrr] = to->sin_addr.s_addr;
7759b7a920aSLexi Winter
7769b7a920aSLexi Winter outip->ip_dst.s_addr = gwlist[0];
7779b7a920aSLexi Winter
7789b7a920aSLexi Winter /* force 4 byte alignment */
7799b7a920aSLexi Winter optlist[0] = IPOPT_NOP;
7809b7a920aSLexi Winter /* loose source route option */
7819b7a920aSLexi Winter optlist[1] = IPOPT_LSRR;
7829b7a920aSLexi Winter i = lsrr * sizeof(gwlist[0]);
7839b7a920aSLexi Winter optlist[2] = i + 3;
7849b7a920aSLexi Winter /* Pointer to LSRR addresses */
7859b7a920aSLexi Winter optlist[3] = IPOPT_MINOFF;
7869b7a920aSLexi Winter memcpy(optlist + 4, gwlist + 1, i);
7879b7a920aSLexi Winter } else
7889b7a920aSLexi Winter outip->ip_dst = to->sin_addr;
7899b7a920aSLexi Winter
7909b7a920aSLexi Winter outip->ip_hl = (outp - (u_char *)outip) >> 2;
7919b7a920aSLexi Winter ident = (getpid() & 0xffff) | 0x8000;
7929b7a920aSLexi Winter
7939b7a920aSLexi Winter if (pe == NULL) {
7949b7a920aSLexi Winter Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
7959b7a920aSLexi Winter exit(1);
7969b7a920aSLexi Winter }
7979b7a920aSLexi Winter if (s < 0) {
7989b7a920aSLexi Winter errno = sockerrno;
7999b7a920aSLexi Winter Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
8009b7a920aSLexi Winter exit(1);
8019b7a920aSLexi Winter }
8029b7a920aSLexi Winter if (options & SO_DEBUG)
8039b7a920aSLexi Winter (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
8049b7a920aSLexi Winter sizeof(on));
8059b7a920aSLexi Winter if (options & SO_DONTROUTE)
8069b7a920aSLexi Winter (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
8079b7a920aSLexi Winter sizeof(on));
8089b7a920aSLexi Winter
8099b7a920aSLexi Winter #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
8109b7a920aSLexi Winter if (setpolicy(s, "in bypass") < 0)
8119b7a920aSLexi Winter errx(1, "%s", ipsec_strerror());
8129b7a920aSLexi Winter
8139b7a920aSLexi Winter if (setpolicy(s, "out bypass") < 0)
8149b7a920aSLexi Winter errx(1, "%s", ipsec_strerror());
8159b7a920aSLexi Winter #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
8169b7a920aSLexi Winter
8179b7a920aSLexi Winter if (sndsock < 0) {
8189b7a920aSLexi Winter errno = sockerrno;
8199b7a920aSLexi Winter Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
8209b7a920aSLexi Winter exit(1);
8219b7a920aSLexi Winter }
8229b7a920aSLexi Winter
8239b7a920aSLexi Winter #ifdef SO_SNDBUF
8249b7a920aSLexi Winter if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
8259b7a920aSLexi Winter sizeof(packlen)) < 0) {
8269b7a920aSLexi Winter Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
8279b7a920aSLexi Winter exit(1);
8289b7a920aSLexi Winter }
8299b7a920aSLexi Winter #endif
8309b7a920aSLexi Winter #ifdef IP_HDRINCL
8319b7a920aSLexi Winter if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
8329b7a920aSLexi Winter sizeof(on)) < 0) {
8339b7a920aSLexi Winter Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
8349b7a920aSLexi Winter exit(1);
8359b7a920aSLexi Winter }
8369b7a920aSLexi Winter #else
8379b7a920aSLexi Winter #ifdef IP_TOS
8389b7a920aSLexi Winter if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
8399b7a920aSLexi Winter (char *)&tos, sizeof(tos)) < 0) {
8409b7a920aSLexi Winter Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
8419b7a920aSLexi Winter prog, tos, strerror(errno));
8429b7a920aSLexi Winter exit(1);
8439b7a920aSLexi Winter }
8449b7a920aSLexi Winter #endif
8459b7a920aSLexi Winter #endif
8469b7a920aSLexi Winter if (options & SO_DEBUG)
8479b7a920aSLexi Winter (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
8489b7a920aSLexi Winter sizeof(on));
8499b7a920aSLexi Winter if (options & SO_DONTROUTE)
8509b7a920aSLexi Winter (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
8519b7a920aSLexi Winter sizeof(on));
8529b7a920aSLexi Winter
8539b7a920aSLexi Winter /* Get the interface address list */
8549b7a920aSLexi Winter n = ifaddrlist(&al, errbuf);
8559b7a920aSLexi Winter if (n < 0) {
8569b7a920aSLexi Winter Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
8579b7a920aSLexi Winter exit(1);
8589b7a920aSLexi Winter }
8599b7a920aSLexi Winter if (n == 0) {
8609b7a920aSLexi Winter Fprintf(stderr,
8619b7a920aSLexi Winter "%s: Can't find any network interfaces\n", prog);
8629b7a920aSLexi Winter exit(1);
8639b7a920aSLexi Winter }
8649b7a920aSLexi Winter
8659b7a920aSLexi Winter /* Look for a specific device */
8669b7a920aSLexi Winter if (device != NULL) {
8679b7a920aSLexi Winter for (i = n; i > 0; --i, ++al)
8689b7a920aSLexi Winter if (strcmp(device, al->device) == 0)
8699b7a920aSLexi Winter break;
8709b7a920aSLexi Winter if (i <= 0) {
8719b7a920aSLexi Winter Fprintf(stderr, "%s: Can't find interface %.32s\n",
8729b7a920aSLexi Winter prog, device);
8739b7a920aSLexi Winter exit(1);
8749b7a920aSLexi Winter }
8759b7a920aSLexi Winter }
8769b7a920aSLexi Winter
8779b7a920aSLexi Winter /* Determine our source address */
8789b7a920aSLexi Winter if (source == NULL) {
8799b7a920aSLexi Winter /*
8809b7a920aSLexi Winter * If a device was specified, use the interface address.
8819b7a920aSLexi Winter * Otherwise, try to determine our source address.
8829b7a920aSLexi Winter */
8839b7a920aSLexi Winter if (device != NULL)
8849b7a920aSLexi Winter setsin(from, al->addr);
8859b7a920aSLexi Winter else if ((err = findsaddr(to, from)) != NULL) {
8869b7a920aSLexi Winter Fprintf(stderr, "%s: findsaddr: %s\n",
8879b7a920aSLexi Winter prog, err);
8889b7a920aSLexi Winter exit(1);
8899b7a920aSLexi Winter }
8909b7a920aSLexi Winter } else {
8919b7a920aSLexi Winter hi = gethostinfo(source);
8929b7a920aSLexi Winter source = hi->name;
8939b7a920aSLexi Winter hi->name = NULL;
8949b7a920aSLexi Winter /*
8959b7a920aSLexi Winter * If the device was specified make sure it
8969b7a920aSLexi Winter * corresponds to the source address specified.
8979b7a920aSLexi Winter * Otherwise, use the first address (and warn if
8989b7a920aSLexi Winter * there are more than one).
8999b7a920aSLexi Winter */
9009b7a920aSLexi Winter if (device != NULL) {
9019b7a920aSLexi Winter for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
9029b7a920aSLexi Winter if (*ap == al->addr)
9039b7a920aSLexi Winter break;
9049b7a920aSLexi Winter if (i <= 0) {
9059b7a920aSLexi Winter Fprintf(stderr,
9069b7a920aSLexi Winter "%s: %s is not on interface %.32s\n",
9079b7a920aSLexi Winter prog, source, device);
9089b7a920aSLexi Winter exit(1);
9099b7a920aSLexi Winter }
9109b7a920aSLexi Winter setsin(from, *ap);
9119b7a920aSLexi Winter } else {
9129b7a920aSLexi Winter setsin(from, hi->addrs[0]);
9139b7a920aSLexi Winter if (hi->n > 1)
9149b7a920aSLexi Winter Fprintf(stderr,
9159b7a920aSLexi Winter "%s: Warning: %s has multiple addresses; using %s\n",
9169b7a920aSLexi Winter prog, source, inet_ntoa(from->sin_addr));
9179b7a920aSLexi Winter }
9189b7a920aSLexi Winter freehostinfo(hi);
9199b7a920aSLexi Winter }
9209b7a920aSLexi Winter
9219b7a920aSLexi Winter outip->ip_src = from->sin_addr;
9229b7a920aSLexi Winter
9239b7a920aSLexi Winter /* Check the source address (-s), if any, is valid */
9249b7a920aSLexi Winter if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
9259b7a920aSLexi Winter Fprintf(stderr, "%s: bind: %s\n",
9269b7a920aSLexi Winter prog, strerror(errno));
9279b7a920aSLexi Winter exit(1);
9289b7a920aSLexi Winter }
9299b7a920aSLexi Winter
9309b7a920aSLexi Winter if (as_path) {
9319b7a920aSLexi Winter asn = as_setup(as_server);
9329b7a920aSLexi Winter if (asn == NULL) {
9339b7a920aSLexi Winter Fprintf(stderr, "%s: as_setup failed, AS# lookups"
9349b7a920aSLexi Winter " disabled\n", prog);
9359b7a920aSLexi Winter (void)fflush(stderr);
9369b7a920aSLexi Winter as_path = 0;
9379b7a920aSLexi Winter }
9389b7a920aSLexi Winter }
9399b7a920aSLexi Winter
9409b7a920aSLexi Winter if (connect(sndsock, (struct sockaddr *)&whereto,
9419b7a920aSLexi Winter sizeof(whereto)) != 0) {
9429b7a920aSLexi Winter Fprintf(stderr, "%s: connect: %s\n", prog, strerror(errno));
9439b7a920aSLexi Winter exit(1);
9449b7a920aSLexi Winter }
9459b7a920aSLexi Winter
9469b7a920aSLexi Winter #ifdef WITH_CASPER
9479b7a920aSLexi Winter cansandbox = true;
9489b7a920aSLexi Winter #else
9499b7a920aSLexi Winter if (nflag)
9509b7a920aSLexi Winter cansandbox = true;
9519b7a920aSLexi Winter else
9529b7a920aSLexi Winter cansandbox = false;
9539b7a920aSLexi Winter #endif
9549b7a920aSLexi Winter
9559b7a920aSLexi Winter caph_cache_catpages();
9569b7a920aSLexi Winter
9579b7a920aSLexi Winter /*
9589b7a920aSLexi Winter * Here we enter capability mode. Further down access to global
9599b7a920aSLexi Winter * namespaces (e.g filesystem) is restricted (see capsicum(4)).
9609b7a920aSLexi Winter * We must connect(2) our socket before this point.
9619b7a920aSLexi Winter */
9629b7a920aSLexi Winter if (cansandbox && cap_enter() < 0) {
9639b7a920aSLexi Winter if (errno != ENOSYS) {
9649b7a920aSLexi Winter Fprintf(stderr, "%s: cap_enter: %s\n", prog,
9659b7a920aSLexi Winter strerror(errno));
9669b7a920aSLexi Winter exit(1);
9679b7a920aSLexi Winter } else {
9689b7a920aSLexi Winter cansandbox = false;
9699b7a920aSLexi Winter }
9709b7a920aSLexi Winter }
9719b7a920aSLexi Winter
9729b7a920aSLexi Winter cap_rights_init(&rights, CAP_SEND, CAP_SETSOCKOPT);
9739b7a920aSLexi Winter if (cansandbox && cap_rights_limit(sndsock, &rights) < 0) {
9749b7a920aSLexi Winter Fprintf(stderr, "%s: cap_rights_limit sndsock: %s\n", prog,
9759b7a920aSLexi Winter strerror(errno));
9769b7a920aSLexi Winter exit(1);
9779b7a920aSLexi Winter }
9789b7a920aSLexi Winter
9799b7a920aSLexi Winter cap_rights_init(&rights, CAP_RECV, CAP_EVENT);
9809b7a920aSLexi Winter if (cansandbox && cap_rights_limit(s, &rights) < 0) {
9819b7a920aSLexi Winter Fprintf(stderr, "%s: cap_rights_limit s: %s\n", prog,
9829b7a920aSLexi Winter strerror(errno));
9839b7a920aSLexi Winter exit(1);
9849b7a920aSLexi Winter }
9859b7a920aSLexi Winter
9869b7a920aSLexi Winter #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
9879b7a920aSLexi Winter if (setpolicy(sndsock, "in bypass") < 0)
9889b7a920aSLexi Winter errx(1, "%s", ipsec_strerror());
9899b7a920aSLexi Winter
9909b7a920aSLexi Winter if (setpolicy(sndsock, "out bypass") < 0)
9919b7a920aSLexi Winter errx(1, "%s", ipsec_strerror());
9929b7a920aSLexi Winter #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
9939b7a920aSLexi Winter
9949b7a920aSLexi Winter Fprintf(stderr, "%s to %s (%s)",
9959b7a920aSLexi Winter prog, hostname, inet_ntoa(to->sin_addr));
9969b7a920aSLexi Winter if (source)
9979b7a920aSLexi Winter Fprintf(stderr, " from %s", source);
9989b7a920aSLexi Winter Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
9999b7a920aSLexi Winter (void)fflush(stderr);
10009b7a920aSLexi Winter
10019b7a920aSLexi Winter for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
10029b7a920aSLexi Winter u_int32_t lastaddr = 0;
10039b7a920aSLexi Winter int gotlastaddr = 0;
10049b7a920aSLexi Winter int got_there = 0;
10059b7a920aSLexi Winter int unreachable = 0;
10069b7a920aSLexi Winter int sentfirst = 0;
10079b7a920aSLexi Winter int loss;
10089b7a920aSLexi Winter
10099b7a920aSLexi Winter Printf("%2d ", ttl);
10109b7a920aSLexi Winter for (probe = 0, loss = 0; probe < nprobes; ++probe) {
10119b7a920aSLexi Winter register int cc;
10129b7a920aSLexi Winter struct timeval t1, t2;
10139b7a920aSLexi Winter register struct ip *ip;
10149b7a920aSLexi Winter struct outdata outdata;
10159b7a920aSLexi Winter
10169b7a920aSLexi Winter if (sentfirst && pausemsecs > 0)
10179b7a920aSLexi Winter usleep(pausemsecs * 1000);
10189b7a920aSLexi Winter /* Prepare outgoing data */
10199b7a920aSLexi Winter outdata.seq = ++seq;
10209b7a920aSLexi Winter outdata.ttl = ttl;
10219b7a920aSLexi Winter
10229b7a920aSLexi Winter /* Avoid alignment problems by copying bytewise: */
10239b7a920aSLexi Winter (void)gettimeofday(&t1, NULL);
10249b7a920aSLexi Winter memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
10259b7a920aSLexi Winter
10269b7a920aSLexi Winter /* Finalize and send packet */
10279b7a920aSLexi Winter (*proto->prepare)(&outdata);
10289b7a920aSLexi Winter send_probe(seq, ttl);
10299b7a920aSLexi Winter ++sentfirst;
10309b7a920aSLexi Winter
10319b7a920aSLexi Winter /* Wait for a reply */
10329b7a920aSLexi Winter while ((cc = wait_for_reply(s, from, &t1)) != 0) {
10339b7a920aSLexi Winter double T;
10349b7a920aSLexi Winter int precis;
10359b7a920aSLexi Winter
10369b7a920aSLexi Winter (void)gettimeofday(&t2, NULL);
10379b7a920aSLexi Winter i = packet_ok(packet, cc, from, seq);
10389b7a920aSLexi Winter /* Skip short packet */
10399b7a920aSLexi Winter if (i == 0)
10409b7a920aSLexi Winter continue;
10419b7a920aSLexi Winter if (!gotlastaddr ||
10429b7a920aSLexi Winter from->sin_addr.s_addr != lastaddr) {
10439b7a920aSLexi Winter if (gotlastaddr)
10449b7a920aSLexi Winter printf("\n ");
10459b7a920aSLexi Winter print(packet, cc, from);
10469b7a920aSLexi Winter lastaddr = from->sin_addr.s_addr;
10479b7a920aSLexi Winter ++gotlastaddr;
10489b7a920aSLexi Winter }
10499b7a920aSLexi Winter T = deltaT(&t1, &t2);
10509b7a920aSLexi Winter #ifdef SANE_PRECISION
10519b7a920aSLexi Winter if (T >= 1000.0)
10529b7a920aSLexi Winter precis = 0;
10539b7a920aSLexi Winter else if (T >= 100.0)
10549b7a920aSLexi Winter precis = 1;
10559b7a920aSLexi Winter else if (T >= 10.0)
10569b7a920aSLexi Winter precis = 2;
10579b7a920aSLexi Winter else
10589b7a920aSLexi Winter #endif
10599b7a920aSLexi Winter precis = 3;
10609b7a920aSLexi Winter Printf(" %.*f ms", precis, T);
10619b7a920aSLexi Winter if (ecnflag) {
10629b7a920aSLexi Winter u_char ecn = hip->ip_tos & IPTOS_ECN_MASK;
10639b7a920aSLexi Winter switch (ecn) {
10649b7a920aSLexi Winter case IPTOS_ECN_ECT1:
10659b7a920aSLexi Winter Printf(" (ecn=passed)");
10669b7a920aSLexi Winter break;
10679b7a920aSLexi Winter case IPTOS_ECN_NOTECT:
10689b7a920aSLexi Winter Printf(" (ecn=bleached)");
10699b7a920aSLexi Winter break;
10709b7a920aSLexi Winter case IPTOS_ECN_CE:
10719b7a920aSLexi Winter Printf(" (ecn=congested)");
10729b7a920aSLexi Winter break;
10739b7a920aSLexi Winter default:
10749b7a920aSLexi Winter Printf(" (ecn=mangled)");
10759b7a920aSLexi Winter break;
10769b7a920aSLexi Winter }
10779b7a920aSLexi Winter }
10789b7a920aSLexi Winter if (printdiff) {
10799b7a920aSLexi Winter Printf("\n");
10809b7a920aSLexi Winter Printf("%*.*s%s\n",
10819b7a920aSLexi Winter -(outip->ip_hl << 3),
10829b7a920aSLexi Winter outip->ip_hl << 3,
10839b7a920aSLexi Winter ip_hdr_key,
10849b7a920aSLexi Winter proto->key);
10859b7a920aSLexi Winter pkt_compare((void *)outip, packlen,
10869b7a920aSLexi Winter (void *)hip, hiplen);
10879b7a920aSLexi Winter }
10889b7a920aSLexi Winter if (i == -2) {
10899b7a920aSLexi Winter #ifndef ARCHAIC
10909b7a920aSLexi Winter ip = (struct ip *)packet;
10919b7a920aSLexi Winter if (ip->ip_ttl <= 1)
10929b7a920aSLexi Winter Printf(" !");
10939b7a920aSLexi Winter #endif
10949b7a920aSLexi Winter ++got_there;
10959b7a920aSLexi Winter break;
10969b7a920aSLexi Winter }
10979b7a920aSLexi Winter /* time exceeded in transit */
10989b7a920aSLexi Winter if (i == -1)
10999b7a920aSLexi Winter break;
11009b7a920aSLexi Winter code = i - 1;
11019b7a920aSLexi Winter switch (code) {
11029b7a920aSLexi Winter
11039b7a920aSLexi Winter case ICMP_UNREACH_PORT:
11049b7a920aSLexi Winter #ifndef ARCHAIC
11059b7a920aSLexi Winter ip = (struct ip *)packet;
11069b7a920aSLexi Winter if (ip->ip_ttl <= 1)
11079b7a920aSLexi Winter Printf(" !");
11089b7a920aSLexi Winter #endif
11099b7a920aSLexi Winter ++got_there;
11109b7a920aSLexi Winter break;
11119b7a920aSLexi Winter
11129b7a920aSLexi Winter case ICMP_UNREACH_NET:
11139b7a920aSLexi Winter ++unreachable;
11149b7a920aSLexi Winter Printf(" !N");
11159b7a920aSLexi Winter break;
11169b7a920aSLexi Winter
11179b7a920aSLexi Winter case ICMP_UNREACH_HOST:
11189b7a920aSLexi Winter ++unreachable;
11199b7a920aSLexi Winter Printf(" !H");
11209b7a920aSLexi Winter break;
11219b7a920aSLexi Winter
11229b7a920aSLexi Winter case ICMP_UNREACH_PROTOCOL:
11239b7a920aSLexi Winter ++got_there;
11249b7a920aSLexi Winter Printf(" !P");
11259b7a920aSLexi Winter break;
11269b7a920aSLexi Winter
11279b7a920aSLexi Winter case ICMP_UNREACH_NEEDFRAG:
11289b7a920aSLexi Winter ++unreachable;
11299b7a920aSLexi Winter Printf(" !F-%d", pmtu);
11309b7a920aSLexi Winter break;
11319b7a920aSLexi Winter
11329b7a920aSLexi Winter case ICMP_UNREACH_SRCFAIL:
11339b7a920aSLexi Winter ++unreachable;
11349b7a920aSLexi Winter Printf(" !S");
11359b7a920aSLexi Winter break;
11369b7a920aSLexi Winter
11379b7a920aSLexi Winter case ICMP_UNREACH_NET_UNKNOWN:
11389b7a920aSLexi Winter ++unreachable;
11399b7a920aSLexi Winter Printf(" !U");
11409b7a920aSLexi Winter break;
11419b7a920aSLexi Winter
11429b7a920aSLexi Winter case ICMP_UNREACH_HOST_UNKNOWN:
11439b7a920aSLexi Winter ++unreachable;
11449b7a920aSLexi Winter Printf(" !W");
11459b7a920aSLexi Winter break;
11469b7a920aSLexi Winter
11479b7a920aSLexi Winter case ICMP_UNREACH_ISOLATED:
11489b7a920aSLexi Winter ++unreachable;
11499b7a920aSLexi Winter Printf(" !I");
11509b7a920aSLexi Winter break;
11519b7a920aSLexi Winter
11529b7a920aSLexi Winter case ICMP_UNREACH_NET_PROHIB:
11539b7a920aSLexi Winter ++unreachable;
11549b7a920aSLexi Winter Printf(" !A");
11559b7a920aSLexi Winter break;
11569b7a920aSLexi Winter
11579b7a920aSLexi Winter case ICMP_UNREACH_HOST_PROHIB:
11589b7a920aSLexi Winter ++unreachable;
11599b7a920aSLexi Winter Printf(" !Z");
11609b7a920aSLexi Winter break;
11619b7a920aSLexi Winter
11629b7a920aSLexi Winter case ICMP_UNREACH_TOSNET:
11639b7a920aSLexi Winter ++unreachable;
11649b7a920aSLexi Winter Printf(" !Q");
11659b7a920aSLexi Winter break;
11669b7a920aSLexi Winter
11679b7a920aSLexi Winter case ICMP_UNREACH_TOSHOST:
11689b7a920aSLexi Winter ++unreachable;
11699b7a920aSLexi Winter Printf(" !T");
11709b7a920aSLexi Winter break;
11719b7a920aSLexi Winter
11729b7a920aSLexi Winter case ICMP_UNREACH_FILTER_PROHIB:
11739b7a920aSLexi Winter ++unreachable;
11749b7a920aSLexi Winter Printf(" !X");
11759b7a920aSLexi Winter break;
11769b7a920aSLexi Winter
11779b7a920aSLexi Winter case ICMP_UNREACH_HOST_PRECEDENCE:
11789b7a920aSLexi Winter ++unreachable;
11799b7a920aSLexi Winter Printf(" !V");
11809b7a920aSLexi Winter break;
11819b7a920aSLexi Winter
11829b7a920aSLexi Winter case ICMP_UNREACH_PRECEDENCE_CUTOFF:
11839b7a920aSLexi Winter ++unreachable;
11849b7a920aSLexi Winter Printf(" !C");
11859b7a920aSLexi Winter break;
11869b7a920aSLexi Winter
11879b7a920aSLexi Winter default:
11889b7a920aSLexi Winter ++unreachable;
11899b7a920aSLexi Winter Printf(" !<%d>", code);
11909b7a920aSLexi Winter break;
11919b7a920aSLexi Winter }
11929b7a920aSLexi Winter break;
11939b7a920aSLexi Winter }
11949b7a920aSLexi Winter if (cc == 0) {
11959b7a920aSLexi Winter loss++;
11969b7a920aSLexi Winter Printf(" *");
11979b7a920aSLexi Winter }
11989b7a920aSLexi Winter (void)fflush(stdout);
11999b7a920aSLexi Winter }
12009b7a920aSLexi Winter if (sump) {
12019b7a920aSLexi Winter Printf(" (%d%% loss)", (loss * 100) / nprobes);
12029b7a920aSLexi Winter }
12039b7a920aSLexi Winter putchar('\n');
12049b7a920aSLexi Winter if (got_there ||
12059b7a920aSLexi Winter (unreachable > 0 && unreachable >= nprobes - 1))
12069b7a920aSLexi Winter break;
12079b7a920aSLexi Winter }
12089b7a920aSLexi Winter if (as_path)
12099b7a920aSLexi Winter as_shutdown(asn);
12109b7a920aSLexi Winter exit(0);
12119b7a920aSLexi Winter }
12129b7a920aSLexi Winter
12139b7a920aSLexi Winter int
wait_for_reply(register int sock,register struct sockaddr_in * fromp,register const struct timeval * tp)12149b7a920aSLexi Winter wait_for_reply(register int sock, register struct sockaddr_in *fromp,
12159b7a920aSLexi Winter register const struct timeval *tp)
12169b7a920aSLexi Winter {
12179b7a920aSLexi Winter fd_set *fdsp;
12189b7a920aSLexi Winter size_t nfds;
12199b7a920aSLexi Winter struct timeval now, wait;
12209b7a920aSLexi Winter register int cc = 0;
12219b7a920aSLexi Winter register int error;
12229b7a920aSLexi Winter int fromlen = sizeof(*fromp);
12239b7a920aSLexi Winter
12249b7a920aSLexi Winter nfds = howmany(sock + 1, NFDBITS);
12259b7a920aSLexi Winter if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
12269b7a920aSLexi Winter err(1, "malloc");
12279b7a920aSLexi Winter memset(fdsp, 0, nfds * sizeof(fd_mask));
12289b7a920aSLexi Winter FD_SET(sock, fdsp);
12299b7a920aSLexi Winter
12309b7a920aSLexi Winter wait.tv_sec = tp->tv_sec + waittime;
12319b7a920aSLexi Winter wait.tv_usec = tp->tv_usec;
12329b7a920aSLexi Winter (void)gettimeofday(&now, NULL);
12339b7a920aSLexi Winter tvsub(&wait, &now);
12349b7a920aSLexi Winter if (wait.tv_sec < 0) {
12359b7a920aSLexi Winter wait.tv_sec = 0;
12369b7a920aSLexi Winter wait.tv_usec = 1;
12379b7a920aSLexi Winter }
12389b7a920aSLexi Winter
12399b7a920aSLexi Winter error = select(sock + 1, fdsp, NULL, NULL, &wait);
12409b7a920aSLexi Winter if (error == -1 && errno == EINVAL) {
12419b7a920aSLexi Winter Fprintf(stderr, "%s: botched select() args\n", prog);
12429b7a920aSLexi Winter exit(1);
12439b7a920aSLexi Winter }
12449b7a920aSLexi Winter if (error > 0)
12459b7a920aSLexi Winter cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
12469b7a920aSLexi Winter (struct sockaddr *)fromp, &fromlen);
12479b7a920aSLexi Winter
12489b7a920aSLexi Winter free(fdsp);
12499b7a920aSLexi Winter return (cc);
12509b7a920aSLexi Winter }
12519b7a920aSLexi Winter
12529b7a920aSLexi Winter void
send_probe(int seq,int ttl)12539b7a920aSLexi Winter send_probe(int seq, int ttl)
12549b7a920aSLexi Winter {
12559b7a920aSLexi Winter register int cc;
12569b7a920aSLexi Winter
12579b7a920aSLexi Winter outip->ip_ttl = ttl;
12589b7a920aSLexi Winter outip->ip_id = htons(ident + seq);
12599b7a920aSLexi Winter
12609b7a920aSLexi Winter /* XXX undocumented debugging hack */
12619b7a920aSLexi Winter if (verbose > 1) {
12629b7a920aSLexi Winter register const u_short *sp;
12639b7a920aSLexi Winter register int nshorts, i;
12649b7a920aSLexi Winter
12659b7a920aSLexi Winter sp = (u_short *)outip;
12669b7a920aSLexi Winter nshorts = (u_int)packlen / sizeof(u_short);
12679b7a920aSLexi Winter i = 0;
12689b7a920aSLexi Winter Printf("[ %d bytes", packlen);
12699b7a920aSLexi Winter while (--nshorts >= 0) {
12709b7a920aSLexi Winter if ((i++ % 8) == 0)
12719b7a920aSLexi Winter Printf("\n\t");
12729b7a920aSLexi Winter Printf(" %04x", ntohs(*sp++));
12739b7a920aSLexi Winter }
12749b7a920aSLexi Winter if (packlen & 1) {
12759b7a920aSLexi Winter if ((i % 8) == 0)
12769b7a920aSLexi Winter Printf("\n\t");
12779b7a920aSLexi Winter Printf(" %02x", *(u_char *)sp);
12789b7a920aSLexi Winter }
12799b7a920aSLexi Winter Printf("]\n");
12809b7a920aSLexi Winter }
12819b7a920aSLexi Winter
12829b7a920aSLexi Winter #if !defined(IP_HDRINCL) && defined(IP_TTL)
12839b7a920aSLexi Winter if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
12849b7a920aSLexi Winter (char *)&ttl, sizeof(ttl)) < 0) {
12859b7a920aSLexi Winter Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
12869b7a920aSLexi Winter prog, ttl, strerror(errno));
12879b7a920aSLexi Winter exit(1);
12889b7a920aSLexi Winter }
12899b7a920aSLexi Winter #endif
12909b7a920aSLexi Winter
12919b7a920aSLexi Winter cc = send(sndsock, (char *)outip, packlen, 0);
12929b7a920aSLexi Winter if (cc < 0 || cc != packlen) {
12939b7a920aSLexi Winter if (cc < 0)
12949b7a920aSLexi Winter Fprintf(stderr, "%s: sendto: %s\n",
12959b7a920aSLexi Winter prog, strerror(errno));
12969b7a920aSLexi Winter Printf("%s: wrote %s %d chars, ret=%d\n",
12979b7a920aSLexi Winter prog, hostname, packlen, cc);
12989b7a920aSLexi Winter (void)fflush(stdout);
12999b7a920aSLexi Winter }
13009b7a920aSLexi Winter }
13019b7a920aSLexi Winter
13029b7a920aSLexi Winter #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
13039b7a920aSLexi Winter int
setpolicy(int so,char * policy)13049b7a920aSLexi Winter setpolicy(int so, char *policy)
13059b7a920aSLexi Winter {
13069b7a920aSLexi Winter char *buf;
13079b7a920aSLexi Winter
13089b7a920aSLexi Winter buf = ipsec_set_policy(policy, strlen(policy));
13099b7a920aSLexi Winter if (buf == NULL) {
13109b7a920aSLexi Winter warnx("%s", ipsec_strerror());
13119b7a920aSLexi Winter return (-1);
13129b7a920aSLexi Winter }
13139b7a920aSLexi Winter (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
13149b7a920aSLexi Winter buf, ipsec_get_policylen(buf));
13159b7a920aSLexi Winter
13169b7a920aSLexi Winter free(buf);
13179b7a920aSLexi Winter
13189b7a920aSLexi Winter return (0);
13199b7a920aSLexi Winter }
13209b7a920aSLexi Winter #endif
13219b7a920aSLexi Winter
13229b7a920aSLexi Winter double
deltaT(struct timeval * t1p,struct timeval * t2p)13239b7a920aSLexi Winter deltaT(struct timeval *t1p, struct timeval *t2p)
13249b7a920aSLexi Winter {
13259b7a920aSLexi Winter register double dt;
13269b7a920aSLexi Winter
13279b7a920aSLexi Winter dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
13289b7a920aSLexi Winter (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
13299b7a920aSLexi Winter return (dt);
13309b7a920aSLexi Winter }
13319b7a920aSLexi Winter
13329b7a920aSLexi Winter /*
13339b7a920aSLexi Winter * Convert an ICMP "type" field to a printable string.
13349b7a920aSLexi Winter */
13359b7a920aSLexi Winter char *
pr_type(register u_char t)13369b7a920aSLexi Winter pr_type(register u_char t)
13379b7a920aSLexi Winter {
13389b7a920aSLexi Winter static char *ttab[] = {
13399b7a920aSLexi Winter "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
13409b7a920aSLexi Winter "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
13419b7a920aSLexi Winter "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
13429b7a920aSLexi Winter "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
13439b7a920aSLexi Winter "Info Reply"
13449b7a920aSLexi Winter };
13459b7a920aSLexi Winter
13469b7a920aSLexi Winter if (t > 16)
13479b7a920aSLexi Winter return ("OUT-OF-RANGE");
13489b7a920aSLexi Winter
13499b7a920aSLexi Winter return (ttab[t]);
13509b7a920aSLexi Winter }
13519b7a920aSLexi Winter
13529b7a920aSLexi Winter int
packet_ok(register u_char * buf,int cc,register struct sockaddr_in * from,register int seq)13539b7a920aSLexi Winter packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
13549b7a920aSLexi Winter register int seq)
13559b7a920aSLexi Winter {
13569b7a920aSLexi Winter register struct icmp *icp;
13579b7a920aSLexi Winter register u_char type, code;
13589b7a920aSLexi Winter register int hlen;
13599b7a920aSLexi Winter #ifndef ARCHAIC
13609b7a920aSLexi Winter register struct ip *ip;
13619b7a920aSLexi Winter
13629b7a920aSLexi Winter ip = (struct ip *) buf;
13639b7a920aSLexi Winter hlen = ip->ip_hl << 2;
13649b7a920aSLexi Winter if (cc < hlen + ICMP_MINLEN) {
13659b7a920aSLexi Winter if (verbose)
13669b7a920aSLexi Winter Printf("packet too short (%d bytes) from %s\n", cc,
13679b7a920aSLexi Winter inet_ntoa(from->sin_addr));
13689b7a920aSLexi Winter return (0);
13699b7a920aSLexi Winter }
13709b7a920aSLexi Winter cc -= hlen;
13719b7a920aSLexi Winter icp = (struct icmp *)(buf + hlen);
13729b7a920aSLexi Winter #else
13739b7a920aSLexi Winter icp = (struct icmp *)buf;
13749b7a920aSLexi Winter #endif
13759b7a920aSLexi Winter type = icp->icmp_type;
13769b7a920aSLexi Winter code = icp->icmp_code;
13779b7a920aSLexi Winter /* Path MTU Discovery (RFC1191) */
13789b7a920aSLexi Winter if (code != ICMP_UNREACH_NEEDFRAG)
13799b7a920aSLexi Winter pmtu = 0;
13809b7a920aSLexi Winter else {
13819b7a920aSLexi Winter pmtu = ntohs(icp->icmp_nextmtu);
13829b7a920aSLexi Winter }
13839b7a920aSLexi Winter if (type == ICMP_ECHOREPLY
13849b7a920aSLexi Winter && proto->num == IPPROTO_ICMP
13859b7a920aSLexi Winter && (*proto->check)((u_char *)icp, (u_char)seq))
13869b7a920aSLexi Winter return (-2);
13879b7a920aSLexi Winter if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
13889b7a920aSLexi Winter type == ICMP_UNREACH) {
13899b7a920aSLexi Winter u_char *inner;
13909b7a920aSLexi Winter
13919b7a920aSLexi Winter hip = &icp->icmp_ip;
13929b7a920aSLexi Winter hiplen = ((u_char *)icp + cc) - (u_char *)hip;
13939b7a920aSLexi Winter hlen = hip->ip_hl << 2;
13949b7a920aSLexi Winter inner = (u_char *)((u_char *)hip + hlen);
13959b7a920aSLexi Winter if (hlen + 16 <= cc
13969b7a920aSLexi Winter && hip->ip_p == proto->num
13979b7a920aSLexi Winter && (*proto->check)(inner, (u_char)seq))
13989b7a920aSLexi Winter return (type == ICMP_TIMXCEED ? -1 : code + 1);
13999b7a920aSLexi Winter }
14009b7a920aSLexi Winter #ifndef ARCHAIC
14019b7a920aSLexi Winter if (verbose) {
14029b7a920aSLexi Winter register int i;
14039b7a920aSLexi Winter u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
14049b7a920aSLexi Winter
14059b7a920aSLexi Winter Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
14069b7a920aSLexi Winter Printf("%s: icmp type %d (%s) code %d\n",
14079b7a920aSLexi Winter inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
14089b7a920aSLexi Winter for (i = 4; i <= cc - ICMP_MINLEN; i += sizeof(*lp))
14099b7a920aSLexi Winter Printf("%2d: %8.8x\n", i, ntohl(*lp++));
14109b7a920aSLexi Winter }
14119b7a920aSLexi Winter #endif
14129b7a920aSLexi Winter return (0);
14139b7a920aSLexi Winter }
14149b7a920aSLexi Winter
14159b7a920aSLexi Winter void
icmp_prep(struct outdata * outdata)14169b7a920aSLexi Winter icmp_prep(struct outdata *outdata)
14179b7a920aSLexi Winter {
14189b7a920aSLexi Winter struct icmp *const icmpheader = (struct icmp *) outp;
14199b7a920aSLexi Winter
14209b7a920aSLexi Winter icmpheader->icmp_type = ICMP_ECHO;
14219b7a920aSLexi Winter icmpheader->icmp_id = htons(ident);
14229b7a920aSLexi Winter icmpheader->icmp_seq = htons(outdata->seq);
14239b7a920aSLexi Winter icmpheader->icmp_cksum = 0;
14249b7a920aSLexi Winter icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen);
14259b7a920aSLexi Winter if (icmpheader->icmp_cksum == 0)
14269b7a920aSLexi Winter icmpheader->icmp_cksum = 0xffff;
14279b7a920aSLexi Winter }
14289b7a920aSLexi Winter
14299b7a920aSLexi Winter int
icmp_check(const u_char * data,int seq)14309b7a920aSLexi Winter icmp_check(const u_char *data, int seq)
14319b7a920aSLexi Winter {
14329b7a920aSLexi Winter struct icmp *const icmpheader = (struct icmp *) data;
14339b7a920aSLexi Winter
14349b7a920aSLexi Winter return (icmpheader->icmp_id == htons(ident)
14359b7a920aSLexi Winter && icmpheader->icmp_seq == htons(seq));
14369b7a920aSLexi Winter }
14379b7a920aSLexi Winter
14389b7a920aSLexi Winter void
udp_prep(struct outdata * outdata)14399b7a920aSLexi Winter udp_prep(struct outdata *outdata)
14409b7a920aSLexi Winter {
14419b7a920aSLexi Winter struct udphdr *const outudp = (struct udphdr *) outp;
14429b7a920aSLexi Winter
14439b7a920aSLexi Winter outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0));
14449b7a920aSLexi Winter outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq));
14459b7a920aSLexi Winter outudp->uh_ulen = htons((u_short)protlen);
14469b7a920aSLexi Winter outudp->uh_sum = 0;
14479b7a920aSLexi Winter if (doipcksum) {
14489b7a920aSLexi Winter u_short sum = p_cksum(outip, (u_short *)outudp, protlen, protlen);
14499b7a920aSLexi Winter outudp->uh_sum = (sum) ? sum : 0xffff;
14509b7a920aSLexi Winter }
14519b7a920aSLexi Winter
14529b7a920aSLexi Winter return;
14539b7a920aSLexi Winter }
14549b7a920aSLexi Winter
14559b7a920aSLexi Winter int
udp_check(const u_char * data,int seq)14569b7a920aSLexi Winter udp_check(const u_char *data, int seq)
14579b7a920aSLexi Winter {
14589b7a920aSLexi Winter struct udphdr *const udp = (struct udphdr *) data;
14599b7a920aSLexi Winter
14609b7a920aSLexi Winter return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
14619b7a920aSLexi Winter ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
14629b7a920aSLexi Winter }
14639b7a920aSLexi Winter
14649b7a920aSLexi Winter void
udplite_prep(struct outdata * outdata)14659b7a920aSLexi Winter udplite_prep(struct outdata *outdata)
14669b7a920aSLexi Winter {
14679b7a920aSLexi Winter struct udphdr *const outudp = (struct udphdr *) outp;
14689b7a920aSLexi Winter
14699b7a920aSLexi Winter outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0));
14709b7a920aSLexi Winter outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq));
14719b7a920aSLexi Winter outudp->uh_ulen = htons(8);
14729b7a920aSLexi Winter outudp->uh_sum = 0;
14739b7a920aSLexi Winter if (doipcksum) {
14749b7a920aSLexi Winter u_short sum = p_cksum(outip, (u_short *)outudp, protlen, 8);
14759b7a920aSLexi Winter outudp->uh_sum = (sum) ? sum : 0xffff;
14769b7a920aSLexi Winter }
14779b7a920aSLexi Winter
14789b7a920aSLexi Winter return;
14799b7a920aSLexi Winter }
14809b7a920aSLexi Winter
14819b7a920aSLexi Winter int
udplite_check(const u_char * data,int seq)14829b7a920aSLexi Winter udplite_check(const u_char *data, int seq)
14839b7a920aSLexi Winter {
14849b7a920aSLexi Winter struct udphdr *const udp = (struct udphdr *) data;
14859b7a920aSLexi Winter
14869b7a920aSLexi Winter return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
14879b7a920aSLexi Winter ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
14889b7a920aSLexi Winter }
14899b7a920aSLexi Winter
14909b7a920aSLexi Winter void
tcp_prep(struct outdata * outdata)14919b7a920aSLexi Winter tcp_prep(struct outdata *outdata)
14929b7a920aSLexi Winter {
14939b7a920aSLexi Winter struct tcphdr *const tcp = (struct tcphdr *) outp;
14949b7a920aSLexi Winter
14959b7a920aSLexi Winter tcp->th_sport = htons(ident);
14969b7a920aSLexi Winter tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq));
14979b7a920aSLexi Winter tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
14989b7a920aSLexi Winter tcp->th_ack = 0;
14999b7a920aSLexi Winter tcp->th_off = 5;
1500*0fc7bdc9SRichard Scheffenegger __tcp_set_flags(tcp, TH_SYN);
15019b7a920aSLexi Winter tcp->th_sum = 0;
15029b7a920aSLexi Winter
15039b7a920aSLexi Winter if (doipcksum)
15049b7a920aSLexi Winter tcp->th_sum = p_cksum(outip, (u_short *)tcp, protlen, protlen);
15059b7a920aSLexi Winter }
15069b7a920aSLexi Winter
15079b7a920aSLexi Winter int
tcp_check(const u_char * data,int seq)15089b7a920aSLexi Winter tcp_check(const u_char *data, int seq)
15099b7a920aSLexi Winter {
15109b7a920aSLexi Winter struct tcphdr *const tcp = (struct tcphdr *) data;
15119b7a920aSLexi Winter
15129b7a920aSLexi Winter return (ntohs(tcp->th_sport) == ident
15139b7a920aSLexi Winter && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq)
15149b7a920aSLexi Winter && tcp->th_seq == (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport));
15159b7a920aSLexi Winter }
15169b7a920aSLexi Winter
15179b7a920aSLexi Winter void
sctp_prep(struct outdata * outdata)15189b7a920aSLexi Winter sctp_prep(struct outdata *outdata)
15199b7a920aSLexi Winter {
15209b7a920aSLexi Winter struct sctphdr *const sctp = (struct sctphdr *) outp;
15219b7a920aSLexi Winter struct sctp_chunkhdr *chk;
15229b7a920aSLexi Winter struct sctp_init_chunk *init;
15239b7a920aSLexi Winter struct sctp_paramhdr *param;
15249b7a920aSLexi Winter
15259b7a920aSLexi Winter sctp->src_port = htons(ident);
15269b7a920aSLexi Winter sctp->dest_port = htons(port + (fixedPort ? 0 : outdata->seq));
15279b7a920aSLexi Winter if (protlen >= (int)(sizeof(struct sctphdr) +
15289b7a920aSLexi Winter sizeof(struct sctp_init_chunk))) {
15299b7a920aSLexi Winter sctp->v_tag = 0;
15309b7a920aSLexi Winter } else {
15319b7a920aSLexi Winter sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
15329b7a920aSLexi Winter }
15339b7a920aSLexi Winter sctp->checksum = htonl(0);
15349b7a920aSLexi Winter if (protlen >= (int)(sizeof(struct sctphdr) +
15359b7a920aSLexi Winter sizeof(struct sctp_init_chunk))) {
15369b7a920aSLexi Winter /*
15379b7a920aSLexi Winter * Send a packet containing an INIT chunk. This works
15389b7a920aSLexi Winter * better in case of firewalls on the path, but
15399b7a920aSLexi Winter * results in a probe packet containing at least
15409b7a920aSLexi Winter * 32 bytes of payload. For shorter payloads, use
15419b7a920aSLexi Winter * SHUTDOWN-ACK chunks.
15429b7a920aSLexi Winter */
15439b7a920aSLexi Winter init = (struct sctp_init_chunk *)(sctp + 1);
15449b7a920aSLexi Winter init->ch.chunk_type = SCTP_INITIATION;
15459b7a920aSLexi Winter init->ch.chunk_flags = 0;
15469b7a920aSLexi Winter init->ch.chunk_length = htons((u_int16_t)(protlen -
15479b7a920aSLexi Winter sizeof(struct sctphdr)));
15489b7a920aSLexi Winter init->init.initiate_tag = (sctp->src_port << 16) |
15499b7a920aSLexi Winter sctp->dest_port;
15509b7a920aSLexi Winter init->init.a_rwnd = htonl(1500);
15519b7a920aSLexi Winter init->init.num_outbound_streams = htons(1);
15529b7a920aSLexi Winter init->init.num_inbound_streams = htons(1);
15539b7a920aSLexi Winter init->init.initial_tsn = htonl(0);
15549b7a920aSLexi Winter if (protlen >= (int)(sizeof(struct sctphdr) +
15559b7a920aSLexi Winter sizeof(struct sctp_init_chunk) +
15569b7a920aSLexi Winter sizeof(struct sctp_paramhdr))) {
15579b7a920aSLexi Winter param = (struct sctp_paramhdr *)(init + 1);
15589b7a920aSLexi Winter param->param_type = htons(SCTP_PAD);
15599b7a920aSLexi Winter param->param_length =
15609b7a920aSLexi Winter htons((u_int16_t)(protlen -
15619b7a920aSLexi Winter sizeof(struct sctphdr) -
15629b7a920aSLexi Winter sizeof(struct sctp_init_chunk)));
15639b7a920aSLexi Winter }
15649b7a920aSLexi Winter } else {
15659b7a920aSLexi Winter /*
15669b7a920aSLexi Winter * Send a packet containing a SHUTDOWN-ACK chunk,
15679b7a920aSLexi Winter * possibly followed by a PAD chunk.
15689b7a920aSLexi Winter */
15699b7a920aSLexi Winter if (protlen >=
15709b7a920aSLexi Winter (int)(sizeof(struct sctphdr) +
15719b7a920aSLexi Winter sizeof(struct sctp_chunkhdr))) {
15729b7a920aSLexi Winter chk = (struct sctp_chunkhdr *)(sctp + 1);
15739b7a920aSLexi Winter chk->chunk_type = SCTP_SHUTDOWN_ACK;
15749b7a920aSLexi Winter chk->chunk_flags = 0;
15759b7a920aSLexi Winter chk->chunk_length = htons(4);
15769b7a920aSLexi Winter }
15779b7a920aSLexi Winter if (protlen >=
15789b7a920aSLexi Winter (int)(sizeof(struct sctphdr) +
15799b7a920aSLexi Winter 2 * sizeof(struct sctp_chunkhdr))) {
15809b7a920aSLexi Winter chk = chk + 1;
15819b7a920aSLexi Winter chk->chunk_type = SCTP_PAD_CHUNK;
15829b7a920aSLexi Winter chk->chunk_flags = 0;
15839b7a920aSLexi Winter chk->chunk_length = htons(protlen -
15849b7a920aSLexi Winter (sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
15859b7a920aSLexi Winter }
15869b7a920aSLexi Winter }
15879b7a920aSLexi Winter if (doipcksum) {
15889b7a920aSLexi Winter sctp->checksum = sctp_crc32c(sctp, protlen);
15899b7a920aSLexi Winter }
15909b7a920aSLexi Winter }
15919b7a920aSLexi Winter
15929b7a920aSLexi Winter int
sctp_check(const u_char * data,int seq)15939b7a920aSLexi Winter sctp_check(const u_char *data, int seq)
15949b7a920aSLexi Winter {
15959b7a920aSLexi Winter struct sctphdr *const sctp = (struct sctphdr *) data;
15969b7a920aSLexi Winter
15979b7a920aSLexi Winter if (ntohs(sctp->src_port) != ident ||
15989b7a920aSLexi Winter ntohs(sctp->dest_port) != port + (fixedPort ? 0 : seq))
15999b7a920aSLexi Winter return (0);
16009b7a920aSLexi Winter if (protlen < (int)(sizeof(struct sctphdr) +
16019b7a920aSLexi Winter sizeof(struct sctp_init_chunk))) {
16029b7a920aSLexi Winter return (sctp->v_tag ==
16039b7a920aSLexi Winter (u_int32_t)((sctp->src_port << 16) | sctp->dest_port));
16049b7a920aSLexi Winter } else {
16059b7a920aSLexi Winter /*
16069b7a920aSLexi Winter * Don't verify the initiate_tag, since it is not available,
16079b7a920aSLexi Winter * most of the time.
16089b7a920aSLexi Winter */
16099b7a920aSLexi Winter return (sctp->v_tag == 0);
16109b7a920aSLexi Winter }
16119b7a920aSLexi Winter }
16129b7a920aSLexi Winter
16139b7a920aSLexi Winter void
gre_prep(struct outdata * outdata)16149b7a920aSLexi Winter gre_prep(struct outdata *outdata)
16159b7a920aSLexi Winter {
16169b7a920aSLexi Winter struct grehdr *const gre = (struct grehdr *) outp;
16179b7a920aSLexi Winter
16189b7a920aSLexi Winter gre->flags = htons(0x2001);
16199b7a920aSLexi Winter gre->proto = htons(port);
16209b7a920aSLexi Winter gre->length = 0;
16219b7a920aSLexi Winter gre->callId = htons(ident + outdata->seq);
16229b7a920aSLexi Winter }
16239b7a920aSLexi Winter
16249b7a920aSLexi Winter int
gre_check(const u_char * data,int seq)16259b7a920aSLexi Winter gre_check(const u_char *data, int seq)
16269b7a920aSLexi Winter {
16279b7a920aSLexi Winter struct grehdr *const gre = (struct grehdr *) data;
16289b7a920aSLexi Winter
16299b7a920aSLexi Winter return (ntohs(gre->proto) == port
16309b7a920aSLexi Winter && ntohs(gre->callId) == ident + seq);
16319b7a920aSLexi Winter }
16329b7a920aSLexi Winter
16339b7a920aSLexi Winter void
gen_prep(struct outdata * outdata)16349b7a920aSLexi Winter gen_prep(struct outdata *outdata)
16359b7a920aSLexi Winter {
16369b7a920aSLexi Winter u_int16_t *const ptr = (u_int16_t *) outp;
16379b7a920aSLexi Winter
16389b7a920aSLexi Winter ptr[0] = htons(ident);
16399b7a920aSLexi Winter ptr[1] = htons(port + outdata->seq);
16409b7a920aSLexi Winter }
16419b7a920aSLexi Winter
16429b7a920aSLexi Winter int
gen_check(const u_char * data,int seq)16439b7a920aSLexi Winter gen_check(const u_char *data, int seq)
16449b7a920aSLexi Winter {
16459b7a920aSLexi Winter u_int16_t *const ptr = (u_int16_t *) data;
16469b7a920aSLexi Winter
16479b7a920aSLexi Winter return (ntohs(ptr[0]) == ident
16489b7a920aSLexi Winter && ntohs(ptr[1]) == port + seq);
16499b7a920aSLexi Winter }
16509b7a920aSLexi Winter
16519b7a920aSLexi Winter void
print(register u_char * buf,register int cc,register struct sockaddr_in * from)16529b7a920aSLexi Winter print(register u_char *buf, register int cc, register struct sockaddr_in *from)
16539b7a920aSLexi Winter {
16549b7a920aSLexi Winter register struct ip *ip;
16559b7a920aSLexi Winter register int hlen;
16569b7a920aSLexi Winter char addr[INET_ADDRSTRLEN];
16579b7a920aSLexi Winter
16589b7a920aSLexi Winter ip = (struct ip *) buf;
16599b7a920aSLexi Winter hlen = ip->ip_hl << 2;
16609b7a920aSLexi Winter cc -= hlen;
16619b7a920aSLexi Winter
16629b7a920aSLexi Winter strlcpy(addr, inet_ntoa(from->sin_addr), sizeof(addr));
16639b7a920aSLexi Winter
16649b7a920aSLexi Winter if (as_path)
16659b7a920aSLexi Winter Printf(" [AS%u]", as_lookup(asn, addr, AF_INET));
16669b7a920aSLexi Winter
16679b7a920aSLexi Winter if (nflag)
16689b7a920aSLexi Winter Printf(" %s", addr);
16699b7a920aSLexi Winter else
16709b7a920aSLexi Winter Printf(" %s (%s)", inetname(from->sin_addr), addr);
16719b7a920aSLexi Winter
16729b7a920aSLexi Winter if (verbose)
16739b7a920aSLexi Winter Printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst));
16749b7a920aSLexi Winter }
16759b7a920aSLexi Winter
16769b7a920aSLexi Winter /*
16779b7a920aSLexi Winter * Checksum routine for UDP and TCP headers.
16789b7a920aSLexi Winter */
16799b7a920aSLexi Winter u_short
p_cksum(struct ip * ip,u_short * data,int len,int cov)16809b7a920aSLexi Winter p_cksum(struct ip *ip, u_short *data, int len, int cov)
16819b7a920aSLexi Winter {
16829b7a920aSLexi Winter static struct ipovly ipo;
16839b7a920aSLexi Winter u_short sum[2];
16849b7a920aSLexi Winter
16859b7a920aSLexi Winter ipo.ih_pr = ip->ip_p;
16869b7a920aSLexi Winter ipo.ih_len = htons(len);
16879b7a920aSLexi Winter ipo.ih_src = ip->ip_src;
16889b7a920aSLexi Winter ipo.ih_dst = ip->ip_dst;
16899b7a920aSLexi Winter
16909b7a920aSLexi Winter sum[1] = in_cksum((u_short *)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
16919b7a920aSLexi Winter sum[0] = in_cksum(data, cov); /* payload data cksum */
16929b7a920aSLexi Winter
16939b7a920aSLexi Winter return (~in_cksum(sum, sizeof(sum)));
16949b7a920aSLexi Winter }
16959b7a920aSLexi Winter
16969b7a920aSLexi Winter /*
16979b7a920aSLexi Winter * Checksum routine for Internet Protocol family headers (C Version)
16989b7a920aSLexi Winter */
16999b7a920aSLexi Winter u_short
in_cksum(register u_short * addr,register int len)17009b7a920aSLexi Winter in_cksum(register u_short *addr, register int len)
17019b7a920aSLexi Winter {
17029b7a920aSLexi Winter register int nleft = len;
17039b7a920aSLexi Winter register u_short *w = addr;
17049b7a920aSLexi Winter register u_short answer;
17059b7a920aSLexi Winter register int sum = 0;
17069b7a920aSLexi Winter
17079b7a920aSLexi Winter /*
17089b7a920aSLexi Winter * Our algorithm is simple, using a 32 bit accumulator (sum),
17099b7a920aSLexi Winter * we add sequential 16 bit words to it, and at the end, fold
17109b7a920aSLexi Winter * back all the carry bits from the top 16 bits into the lower
17119b7a920aSLexi Winter * 16 bits.
17129b7a920aSLexi Winter */
17139b7a920aSLexi Winter while (nleft > 1) {
17149b7a920aSLexi Winter sum += *w++;
17159b7a920aSLexi Winter nleft -= 2;
17169b7a920aSLexi Winter }
17179b7a920aSLexi Winter
17189b7a920aSLexi Winter /* mop up an odd byte, if necessary */
17199b7a920aSLexi Winter if (nleft == 1)
17209b7a920aSLexi Winter sum += *(u_char *)w;
17219b7a920aSLexi Winter
17229b7a920aSLexi Winter /*
17239b7a920aSLexi Winter * add back carry outs from top 16 bits to low 16 bits
17249b7a920aSLexi Winter */
17259b7a920aSLexi Winter sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
17269b7a920aSLexi Winter sum += (sum >> 16); /* add carry */
17279b7a920aSLexi Winter answer = ~sum; /* truncate to 16 bits */
17289b7a920aSLexi Winter return (answer);
17299b7a920aSLexi Winter }
17309b7a920aSLexi Winter
17319b7a920aSLexi Winter /*
17329b7a920aSLexi Winter * CRC32C routine for the Stream Control Transmission Protocol
17339b7a920aSLexi Winter */
17349b7a920aSLexi Winter
17359b7a920aSLexi Winter #define CRC32C(c, d) (c = (c >> 8) ^ crc_c[(c ^ (d)) & 0xFF])
17369b7a920aSLexi Winter
17379b7a920aSLexi Winter static u_int32_t crc_c[256] = {
17389b7a920aSLexi Winter 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
17399b7a920aSLexi Winter 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
17409b7a920aSLexi Winter 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
17419b7a920aSLexi Winter 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
17429b7a920aSLexi Winter 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
17439b7a920aSLexi Winter 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
17449b7a920aSLexi Winter 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
17459b7a920aSLexi Winter 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
17469b7a920aSLexi Winter 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
17479b7a920aSLexi Winter 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
17489b7a920aSLexi Winter 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
17499b7a920aSLexi Winter 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
17509b7a920aSLexi Winter 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
17519b7a920aSLexi Winter 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
17529b7a920aSLexi Winter 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
17539b7a920aSLexi Winter 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
17549b7a920aSLexi Winter 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
17559b7a920aSLexi Winter 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
17569b7a920aSLexi Winter 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
17579b7a920aSLexi Winter 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
17589b7a920aSLexi Winter 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
17599b7a920aSLexi Winter 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
17609b7a920aSLexi Winter 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
17619b7a920aSLexi Winter 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
17629b7a920aSLexi Winter 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
17639b7a920aSLexi Winter 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
17649b7a920aSLexi Winter 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
17659b7a920aSLexi Winter 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
17669b7a920aSLexi Winter 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
17679b7a920aSLexi Winter 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
17689b7a920aSLexi Winter 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
17699b7a920aSLexi Winter 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
17709b7a920aSLexi Winter 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
17719b7a920aSLexi Winter 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
17729b7a920aSLexi Winter 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
17739b7a920aSLexi Winter 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
17749b7a920aSLexi Winter 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
17759b7a920aSLexi Winter 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
17769b7a920aSLexi Winter 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
17779b7a920aSLexi Winter 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
17789b7a920aSLexi Winter 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
17799b7a920aSLexi Winter 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
17809b7a920aSLexi Winter 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
17819b7a920aSLexi Winter 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
17829b7a920aSLexi Winter 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
17839b7a920aSLexi Winter 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
17849b7a920aSLexi Winter 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
17859b7a920aSLexi Winter 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
17869b7a920aSLexi Winter 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
17879b7a920aSLexi Winter 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
17889b7a920aSLexi Winter 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
17899b7a920aSLexi Winter 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
17909b7a920aSLexi Winter 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
17919b7a920aSLexi Winter 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
17929b7a920aSLexi Winter 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
17939b7a920aSLexi Winter 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
17949b7a920aSLexi Winter 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
17959b7a920aSLexi Winter 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
17969b7a920aSLexi Winter 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
17979b7a920aSLexi Winter 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
17989b7a920aSLexi Winter 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
17999b7a920aSLexi Winter 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
18009b7a920aSLexi Winter 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
18019b7a920aSLexi Winter 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
18029b7a920aSLexi Winter };
18039b7a920aSLexi Winter
18049b7a920aSLexi Winter u_int32_t
sctp_crc32c(const void * packet,u_int32_t len)18059b7a920aSLexi Winter sctp_crc32c(const void *packet, u_int32_t len)
18069b7a920aSLexi Winter {
18079b7a920aSLexi Winter u_int32_t i, crc32c;
18089b7a920aSLexi Winter u_int8_t byte0, byte1, byte2, byte3;
18099b7a920aSLexi Winter const u_int8_t *buf = (const u_int8_t *)packet;
18109b7a920aSLexi Winter
18119b7a920aSLexi Winter crc32c = ~0;
18129b7a920aSLexi Winter for (i = 0; i < len; i++)
18139b7a920aSLexi Winter CRC32C(crc32c, buf[i]);
18149b7a920aSLexi Winter crc32c = ~crc32c;
18159b7a920aSLexi Winter byte0 = crc32c & 0xff;
18169b7a920aSLexi Winter byte1 = (crc32c >> 8) & 0xff;
18179b7a920aSLexi Winter byte2 = (crc32c >> 16) & 0xff;
18189b7a920aSLexi Winter byte3 = (crc32c >> 24) & 0xff;
18199b7a920aSLexi Winter crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
18209b7a920aSLexi Winter return (htonl(crc32c));
18219b7a920aSLexi Winter }
18229b7a920aSLexi Winter
18239b7a920aSLexi Winter /*
18249b7a920aSLexi Winter * Subtract 2 timeval structs: out = out - in.
18259b7a920aSLexi Winter * Out is assumed to be within about LONG_MAX seconds of in.
18269b7a920aSLexi Winter */
18279b7a920aSLexi Winter void
tvsub(register struct timeval * out,register struct timeval * in)18289b7a920aSLexi Winter tvsub(register struct timeval *out, register struct timeval *in)
18299b7a920aSLexi Winter {
18309b7a920aSLexi Winter
18319b7a920aSLexi Winter if ((out->tv_usec -= in->tv_usec) < 0) {
18329b7a920aSLexi Winter --out->tv_sec;
18339b7a920aSLexi Winter out->tv_usec += 1000000;
18349b7a920aSLexi Winter }
18359b7a920aSLexi Winter out->tv_sec -= in->tv_sec;
18369b7a920aSLexi Winter }
18379b7a920aSLexi Winter
18389b7a920aSLexi Winter /*
18399b7a920aSLexi Winter * Construct an Internet address representation.
18409b7a920aSLexi Winter * If the nflag has been supplied, give
18419b7a920aSLexi Winter * numeric value, otherwise try for symbolic name.
18429b7a920aSLexi Winter */
18439b7a920aSLexi Winter char *
inetname(struct in_addr in)18449b7a920aSLexi Winter inetname(struct in_addr in)
18459b7a920aSLexi Winter {
18469b7a920aSLexi Winter register char *cp;
18479b7a920aSLexi Winter register struct hostent *hp;
18489b7a920aSLexi Winter static int first = 1;
18499b7a920aSLexi Winter static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
18509b7a920aSLexi Winter
18519b7a920aSLexi Winter if (first && !nflag) {
18529b7a920aSLexi Winter first = 0;
18539b7a920aSLexi Winter if (gethostname(domain, sizeof(domain) - 1) < 0)
18549b7a920aSLexi Winter domain[0] = '\0';
18559b7a920aSLexi Winter else {
18569b7a920aSLexi Winter cp = strchr(domain, '.');
18579b7a920aSLexi Winter if (cp == NULL) {
18589b7a920aSLexi Winter #ifdef WITH_CASPER
18599b7a920aSLexi Winter if (capdns != NULL)
18609b7a920aSLexi Winter hp = cap_gethostbyname(capdns, domain);
18619b7a920aSLexi Winter else
18629b7a920aSLexi Winter #endif
18639b7a920aSLexi Winter hp = gethostbyname(domain);
18649b7a920aSLexi Winter if (hp != NULL)
18659b7a920aSLexi Winter cp = strchr(hp->h_name, '.');
18669b7a920aSLexi Winter }
18679b7a920aSLexi Winter if (cp == NULL)
18689b7a920aSLexi Winter domain[0] = '\0';
18699b7a920aSLexi Winter else {
18709b7a920aSLexi Winter ++cp;
18719b7a920aSLexi Winter (void)strncpy(domain, cp, sizeof(domain) - 1);
18729b7a920aSLexi Winter domain[sizeof(domain) - 1] = '\0';
18739b7a920aSLexi Winter }
18749b7a920aSLexi Winter }
18759b7a920aSLexi Winter }
18769b7a920aSLexi Winter if (!nflag && in.s_addr != INADDR_ANY) {
18779b7a920aSLexi Winter #ifdef WITH_CASPER
18789b7a920aSLexi Winter if (capdns != NULL)
18799b7a920aSLexi Winter hp = cap_gethostbyaddr(capdns, (char *)&in, sizeof(in),
18809b7a920aSLexi Winter AF_INET);
18819b7a920aSLexi Winter else
18829b7a920aSLexi Winter #endif
18839b7a920aSLexi Winter hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
18849b7a920aSLexi Winter if (hp != NULL) {
18859b7a920aSLexi Winter if ((cp = strchr(hp->h_name, '.')) != NULL &&
18869b7a920aSLexi Winter strcmp(cp + 1, domain) == 0)
18879b7a920aSLexi Winter *cp = '\0';
18889b7a920aSLexi Winter (void)strncpy(line, hp->h_name, sizeof(line) - 1);
18899b7a920aSLexi Winter line[sizeof(line) - 1] = '\0';
18909b7a920aSLexi Winter return (line);
18919b7a920aSLexi Winter }
18929b7a920aSLexi Winter }
18939b7a920aSLexi Winter return (inet_ntoa(in));
18949b7a920aSLexi Winter }
18959b7a920aSLexi Winter
18969b7a920aSLexi Winter struct hostinfo *
gethostinfo(register char * hostname)18979b7a920aSLexi Winter gethostinfo(register char *hostname)
18989b7a920aSLexi Winter {
18999b7a920aSLexi Winter register int n;
19009b7a920aSLexi Winter register struct hostent *hp;
19019b7a920aSLexi Winter register struct hostinfo *hi;
19029b7a920aSLexi Winter register char **p;
19039b7a920aSLexi Winter register u_int32_t addr, *ap;
19049b7a920aSLexi Winter
19059b7a920aSLexi Winter if (strlen(hostname) >= MAXHOSTNAMELEN) {
19069b7a920aSLexi Winter Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
19079b7a920aSLexi Winter prog, hostname);
19089b7a920aSLexi Winter exit(1);
19099b7a920aSLexi Winter }
19109b7a920aSLexi Winter hi = calloc(1, sizeof(*hi));
19119b7a920aSLexi Winter if (hi == NULL) {
19129b7a920aSLexi Winter Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
19139b7a920aSLexi Winter exit(1);
19149b7a920aSLexi Winter }
19159b7a920aSLexi Winter addr = inet_addr(hostname);
19169b7a920aSLexi Winter if ((int32_t)addr != -1) {
19179b7a920aSLexi Winter hi->name = strdup(hostname);
19189b7a920aSLexi Winter hi->n = 1;
19199b7a920aSLexi Winter hi->addrs = calloc(1, sizeof(hi->addrs[0]));
19209b7a920aSLexi Winter if (hi->addrs == NULL) {
19219b7a920aSLexi Winter Fprintf(stderr, "%s: calloc %s\n",
19229b7a920aSLexi Winter prog, strerror(errno));
19239b7a920aSLexi Winter exit(1);
19249b7a920aSLexi Winter }
19259b7a920aSLexi Winter hi->addrs[0] = addr;
19269b7a920aSLexi Winter return (hi);
19279b7a920aSLexi Winter }
19289b7a920aSLexi Winter
19299b7a920aSLexi Winter #ifdef WITH_CASPER
19309b7a920aSLexi Winter if (capdns != NULL)
19319b7a920aSLexi Winter hp = cap_gethostbyname(capdns, hostname);
19329b7a920aSLexi Winter else
19339b7a920aSLexi Winter #endif
19349b7a920aSLexi Winter hp = gethostbyname(hostname);
19359b7a920aSLexi Winter if (hp == NULL) {
19369b7a920aSLexi Winter Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
19379b7a920aSLexi Winter exit(1);
19389b7a920aSLexi Winter }
19399b7a920aSLexi Winter if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
19409b7a920aSLexi Winter Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
19419b7a920aSLexi Winter exit(1);
19429b7a920aSLexi Winter }
19439b7a920aSLexi Winter hi->name = strdup(hp->h_name);
19449b7a920aSLexi Winter for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
19459b7a920aSLexi Winter continue;
19469b7a920aSLexi Winter hi->n = n;
19479b7a920aSLexi Winter hi->addrs = calloc(n, sizeof(hi->addrs[0]));
19489b7a920aSLexi Winter if (hi->addrs == NULL) {
19499b7a920aSLexi Winter Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
19509b7a920aSLexi Winter exit(1);
19519b7a920aSLexi Winter }
19529b7a920aSLexi Winter for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
19539b7a920aSLexi Winter memcpy(ap, *p, sizeof(*ap));
19549b7a920aSLexi Winter return (hi);
19559b7a920aSLexi Winter }
19569b7a920aSLexi Winter
19579b7a920aSLexi Winter void
freehostinfo(register struct hostinfo * hi)19589b7a920aSLexi Winter freehostinfo(register struct hostinfo *hi)
19599b7a920aSLexi Winter {
19609b7a920aSLexi Winter if (hi->name != NULL) {
19619b7a920aSLexi Winter free(hi->name);
19629b7a920aSLexi Winter hi->name = NULL;
19639b7a920aSLexi Winter }
19649b7a920aSLexi Winter free((char *)hi->addrs);
19659b7a920aSLexi Winter free((char *)hi);
19669b7a920aSLexi Winter }
19679b7a920aSLexi Winter
19689b7a920aSLexi Winter void
getaddr(register u_int32_t * ap,register char * hostname)19699b7a920aSLexi Winter getaddr(register u_int32_t *ap, register char *hostname)
19709b7a920aSLexi Winter {
19719b7a920aSLexi Winter register struct hostinfo *hi;
19729b7a920aSLexi Winter
19739b7a920aSLexi Winter hi = gethostinfo(hostname);
19749b7a920aSLexi Winter *ap = hi->addrs[0];
19759b7a920aSLexi Winter freehostinfo(hi);
19769b7a920aSLexi Winter }
19779b7a920aSLexi Winter
19789b7a920aSLexi Winter void
setsin(register struct sockaddr_in * sin,register u_int32_t addr)19799b7a920aSLexi Winter setsin(register struct sockaddr_in *sin, register u_int32_t addr)
19809b7a920aSLexi Winter {
19819b7a920aSLexi Winter
19829b7a920aSLexi Winter memset(sin, 0, sizeof(*sin));
19839b7a920aSLexi Winter sin->sin_len = sizeof(*sin);
19849b7a920aSLexi Winter sin->sin_family = AF_INET;
19859b7a920aSLexi Winter sin->sin_addr.s_addr = addr;
19869b7a920aSLexi Winter }
19879b7a920aSLexi Winter
19889b7a920aSLexi Winter /* String to value with optional min and max. Handles decimal and hex. */
19899b7a920aSLexi Winter int
str2val(register const char * str,register const char * what,register int mi,register int ma)19909b7a920aSLexi Winter str2val(register const char *str, register const char *what,
19919b7a920aSLexi Winter register int mi, register int ma)
19929b7a920aSLexi Winter {
19939b7a920aSLexi Winter register const char *cp;
19949b7a920aSLexi Winter register int val;
19959b7a920aSLexi Winter char *ep;
19969b7a920aSLexi Winter
19979b7a920aSLexi Winter if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
19989b7a920aSLexi Winter cp = str + 2;
19999b7a920aSLexi Winter val = (int)strtol(cp, &ep, 16);
20009b7a920aSLexi Winter } else
20019b7a920aSLexi Winter val = (int)strtol(str, &ep, 10);
20029b7a920aSLexi Winter if (*ep != '\0') {
20039b7a920aSLexi Winter Fprintf(stderr, "%s: \"%s\" bad value for %s\n",
20049b7a920aSLexi Winter prog, str, what);
20059b7a920aSLexi Winter exit(1);
20069b7a920aSLexi Winter }
20079b7a920aSLexi Winter if (val < mi && mi >= 0) {
20089b7a920aSLexi Winter if (mi == 0)
20099b7a920aSLexi Winter Fprintf(stderr, "%s: %s must be >= %d\n",
20109b7a920aSLexi Winter prog, what, mi);
20119b7a920aSLexi Winter else
20129b7a920aSLexi Winter Fprintf(stderr, "%s: %s must be > %d\n",
20139b7a920aSLexi Winter prog, what, mi - 1);
20149b7a920aSLexi Winter exit(1);
20159b7a920aSLexi Winter }
20169b7a920aSLexi Winter if (val > ma && ma >= 0) {
20179b7a920aSLexi Winter Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
20189b7a920aSLexi Winter exit(1);
20199b7a920aSLexi Winter }
20209b7a920aSLexi Winter return (val);
20219b7a920aSLexi Winter }
20229b7a920aSLexi Winter
20239b7a920aSLexi Winter struct outproto *
setproto(char * pname)20249b7a920aSLexi Winter setproto(char *pname)
20259b7a920aSLexi Winter {
20269b7a920aSLexi Winter struct outproto *proto;
20279b7a920aSLexi Winter int i;
20289b7a920aSLexi Winter
20299b7a920aSLexi Winter for (i = 0; protos[i].name != NULL; i++) {
20309b7a920aSLexi Winter if (strcasecmp(protos[i].name, pname) == 0) {
20319b7a920aSLexi Winter break;
20329b7a920aSLexi Winter }
20339b7a920aSLexi Winter }
20349b7a920aSLexi Winter proto = &protos[i];
20359b7a920aSLexi Winter if (proto->name == NULL) { /* generic handler */
20369b7a920aSLexi Winter struct protoent *pe;
20379b7a920aSLexi Winter u_long pnum;
20389b7a920aSLexi Winter
20399b7a920aSLexi Winter /* Determine the IP protocol number */
20409b7a920aSLexi Winter if ((pe = getprotobyname(pname)) != NULL)
20419b7a920aSLexi Winter pnum = pe->p_proto;
20429b7a920aSLexi Winter else
20439b7a920aSLexi Winter pnum = str2val(optarg, "proto number", 1, 255);
20449b7a920aSLexi Winter proto->num = pnum;
20459b7a920aSLexi Winter }
20469b7a920aSLexi Winter return (proto);
20479b7a920aSLexi Winter }
20489b7a920aSLexi Winter
20499b7a920aSLexi Winter void
pkt_compare(const u_char * a,int la,const u_char * b,int lb)20509b7a920aSLexi Winter pkt_compare(const u_char *a, int la, const u_char *b, int lb) {
20519b7a920aSLexi Winter int l;
20529b7a920aSLexi Winter int i;
20539b7a920aSLexi Winter
20549b7a920aSLexi Winter for (i = 0; i < la; i++)
20559b7a920aSLexi Winter Printf("%02x", (unsigned int)a[i]);
20569b7a920aSLexi Winter Printf("\n");
20579b7a920aSLexi Winter l = (la <= lb) ? la : lb;
20589b7a920aSLexi Winter for (i = 0; i < l; i++)
20599b7a920aSLexi Winter if (a[i] == b[i])
20609b7a920aSLexi Winter Printf("__");
20619b7a920aSLexi Winter else
20629b7a920aSLexi Winter Printf("%02x", (unsigned int)b[i]);
20639b7a920aSLexi Winter for (; i < lb; i++)
20649b7a920aSLexi Winter Printf("%02x", (unsigned int)b[i]);
20659b7a920aSLexi Winter Printf("\n");
20669b7a920aSLexi Winter }
20679b7a920aSLexi Winter
20689b7a920aSLexi Winter
20699b7a920aSLexi Winter void
usage(void)20709b7a920aSLexi Winter usage(void)
20719b7a920aSLexi Winter {
20729b7a920aSLexi Winter Fprintf(stderr,
20739b7a920aSLexi Winter "Usage: %s [-adDeEFInrSvx] [-A as_server] [-f first_ttl] [-g gateway]\n"
20749b7a920aSLexi Winter "\t[-i iface] [-m max_ttl] [-M first_ttl] [-p port] [-P proto]\n"
20759b7a920aSLexi Winter "\t[-q nprobes] [-s src_addr] [-t tos] [-w waittime]\n"
20769b7a920aSLexi Winter "\t[-z pausemsecs] host [packetlen]\n", prog);
20779b7a920aSLexi Winter exit(1);
20789b7a920aSLexi Winter }
2079