xref: /freebsd/usr.sbin/traceroute/traceroute.c (revision 0fc7bdc978366abb4351b0b76b50a5848cc5d982)
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