118579Sfenner/* 2100787Sfenner * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000 318579Sfenner * The Regents of the University of California. All rights reserved. 418579Sfenner * 518579Sfenner * Redistribution and use in source and binary forms, with or without 618579Sfenner * modification, are permitted provided that: (1) source code distributions 718579Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 818579Sfenner * distributions including binary code include the above copyright notice and 918579Sfenner * this paragraph in its entirety in the documentation or other materials 1018579Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1118579Sfenner * features or use of this software display the following acknowledgement: 1218579Sfenner * ``This product includes software developed by the University of California, 1318579Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1418579Sfenner * the University nor the names of its contributors may be used to endorse 1518579Sfenner * or promote products derived from this software without specific prior 1618579Sfenner * written permission. 1718579Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1818579Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1918579Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2018579Sfenner */ 2118579Sfenner 2218579Sfenner#ifndef lint 2318579Sfennerstatic const char copyright[] = 24100787Sfenner "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\ 2518579SfennerThe Regents of the University of California. All rights reserved.\n"; 2658835Sshin#if 0 2718579Sfennerstatic const char rcsid[] = 28100787Sfenner "@(#)$Id: traceroute.c,v 1.68 2000/12/14 08:04:33 leres Exp $ (LBL)"; 2918579Sfenner#endif 3058835Sshinstatic const char rcsid[] = 3158835Sshin "$FreeBSD: stable/11/contrib/traceroute/traceroute.c 339045 2018-10-01 14:39:59Z oshogbo $"; 3258835Sshin#endif 3318579Sfenner 3418579Sfenner/* 3518579Sfenner * traceroute host - trace the route ip packets follow going to "host". 3618579Sfenner * 3718579Sfenner * Attempt to trace the route an ip packet would follow to some 3818579Sfenner * internet host. We find out intermediate hops by launching probe 3918579Sfenner * packets with a small ttl (time to live) then listening for an 4018579Sfenner * icmp "time exceeded" reply from a gateway. We start our probes 4118579Sfenner * with a ttl of one and increase by one until we get an icmp "port 4218579Sfenner * unreachable" (which means we got to "host") or hit a max (which 4377816Sru * defaults to net.inet.ip.ttl hops & can be changed with the -m flag). 4477816Sru * Three probes (change with -q flag) are sent at each ttl setting and 4577816Sru * a line is printed showing the ttl, address of the gateway and 4618579Sfenner * round trip time of each probe. If the probe answers come from 4718579Sfenner * different gateways, the address of each responding system will 4818579Sfenner * be printed. If there is no response within a 5 sec. timeout 4918579Sfenner * interval (changed with the -w flag), a "*" is printed for that 5018579Sfenner * probe. 5118579Sfenner * 5218579Sfenner * Probe packets are UDP format. We don't want the destination 5318579Sfenner * host to process them so the destination port is set to an 5418579Sfenner * unlikely value (if some clod on the destination is using that 5518579Sfenner * value, it can be changed with the -p flag). 5618579Sfenner * 5718579Sfenner * A sample use might be: 5818579Sfenner * 5918579Sfenner * [yak 71]% traceroute nis.nsf.net. 6077816Sru * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet 6118579Sfenner * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms 6218579Sfenner * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 6318579Sfenner * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 6418579Sfenner * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms 6518579Sfenner * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms 6618579Sfenner * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms 6718579Sfenner * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms 6818579Sfenner * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms 6918579Sfenner * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms 7018579Sfenner * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms 7118579Sfenner * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms 7218579Sfenner * 7318579Sfenner * Note that lines 2 & 3 are the same. This is due to a buggy 7418579Sfenner * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards 7518579Sfenner * packets with a zero ttl. 7618579Sfenner * 7718579Sfenner * A more interesting example is: 7818579Sfenner * 7918579Sfenner * [yak 72]% traceroute allspice.lcs.mit.edu. 8077816Sru * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max 8118579Sfenner * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 8218579Sfenner * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms 8318579Sfenner * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms 8418579Sfenner * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms 8518579Sfenner * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms 8618579Sfenner * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms 8718579Sfenner * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms 8818579Sfenner * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms 8918579Sfenner * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms 9018579Sfenner * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms 9118579Sfenner * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms 9218579Sfenner * 12 * * * 9318579Sfenner * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms 9418579Sfenner * 14 * * * 9518579Sfenner * 15 * * * 9618579Sfenner * 16 * * * 9718579Sfenner * 17 * * * 9818579Sfenner * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms 9918579Sfenner * 10018579Sfenner * (I start to see why I'm having so much trouble with mail to 10118579Sfenner * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away 10218579Sfenner * either don't send ICMP "time exceeded" messages or send them 10318579Sfenner * with a ttl too small to reach us. 14 - 17 are running the 10418579Sfenner * MIT C Gateway code that doesn't send "time exceeded"s. God 10518579Sfenner * only knows what's going on with 12. 10618579Sfenner * 10718579Sfenner * The silent gateway 12 in the above may be the result of a bug in 10818579Sfenner * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) 10918579Sfenner * sends an unreachable message using whatever ttl remains in the 11018579Sfenner * original datagram. Since, for gateways, the remaining ttl is 11118579Sfenner * zero, the icmp "time exceeded" is guaranteed to not make it back 11218579Sfenner * to us. The behavior of this bug is slightly more interesting 11318579Sfenner * when it appears on the destination system: 11418579Sfenner * 11518579Sfenner * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 11618579Sfenner * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms 11718579Sfenner * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms 11818579Sfenner * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms 11918579Sfenner * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms 12018579Sfenner * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms 12118579Sfenner * 7 * * * 12218579Sfenner * 8 * * * 12318579Sfenner * 9 * * * 12418579Sfenner * 10 * * * 12518579Sfenner * 11 * * * 12618579Sfenner * 12 * * * 12718579Sfenner * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! 12818579Sfenner * 12918579Sfenner * Notice that there are 12 "gateways" (13 is the final 13018579Sfenner * destination) and exactly the last half of them are "missing". 13118579Sfenner * What's really happening is that rip (a Sun-3 running Sun OS3.5) 13218579Sfenner * is using the ttl from our arriving datagram as the ttl in its 13318579Sfenner * icmp reply. So, the reply will time out on the return path 13418579Sfenner * (with no notice sent to anyone since icmp's aren't sent for 13518579Sfenner * icmp's) until we probe with a ttl that's at least twice the path 13618579Sfenner * length. I.e., rip is really only 7 hops away. A reply that 13718579Sfenner * returns with a ttl of 1 is a clue this problem exists. 13818579Sfenner * Traceroute prints a "!" after the time if the ttl is <= 1. 13918579Sfenner * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or 14018579Sfenner * non-standard (HPUX) software, expect to see this problem 14118579Sfenner * frequently and/or take care picking the target host of your 14218579Sfenner * probes. 14318579Sfenner * 14418579Sfenner * Other possible annotations after the time are !H, !N, !P (got a host, 14518579Sfenner * network or protocol unreachable, respectively), !S or !F (source 14618579Sfenner * route failed or fragmentation needed -- neither of these should 14718579Sfenner * ever occur and the associated gateway is busted if you see one). If 14818579Sfenner * almost all the probes result in some kind of unreachable, traceroute 14918579Sfenner * will give up and exit. 15018579Sfenner * 15118579Sfenner * Notes 15218579Sfenner * ----- 15318579Sfenner * This program must be run by root or be setuid. (I suggest that 15418579Sfenner * you *don't* make it setuid -- casual use could result in a lot 15518579Sfenner * of unnecessary traffic on our poor, congested nets.) 15618579Sfenner * 15718579Sfenner * This program requires a kernel mod that does not appear in any 15818579Sfenner * system available from Berkeley: A raw ip socket using proto 15918579Sfenner * IPPROTO_RAW must interpret the data sent as an ip datagram (as 16018579Sfenner * opposed to data to be wrapped in a ip datagram). See the README 16118579Sfenner * file that came with the source to this program for a description 16218579Sfenner * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may 16318579Sfenner * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE 16418579Sfenner * MODIFIED TO RUN THIS PROGRAM. 16518579Sfenner * 16618579Sfenner * The udp port usage may appear bizarre (well, ok, it is bizarre). 16718579Sfenner * The problem is that an icmp message only contains 8 bytes of 16818579Sfenner * data from the original datagram. 8 bytes is the size of a udp 16918579Sfenner * header so, if we want to associate replies with the original 17018579Sfenner * datagram, the necessary information must be encoded into the 17118579Sfenner * udp header (the ip id could be used but there's no way to 17218579Sfenner * interlock with the kernel's assignment of ip id's and, anyway, 17318579Sfenner * it would have taken a lot more kernel hacking to allow this 17418579Sfenner * code to set the ip id). So, to allow two or more users to 17518579Sfenner * use traceroute simultaneously, we use this task's pid as the 17618579Sfenner * source port (the high bit is set to move the port number out 17718579Sfenner * of the "likely" range). To keep track of which probe is being 17818579Sfenner * replied to (so times and/or hop counts don't get confused by a 17918579Sfenner * reply that was delayed in transit), we increment the destination 18018579Sfenner * port number before each probe. 18118579Sfenner * 18218579Sfenner * Don't use this as a coding example. I was trying to find a 18318579Sfenner * routing problem and this code sort-of popped out after 48 hours 18418579Sfenner * without sleep. I was amazed it ever compiled, much less ran. 18518579Sfenner * 18618579Sfenner * I stole the idea for this program from Steve Deering. Since 18718579Sfenner * the first release, I've learned that had I attended the right 18818579Sfenner * IETF working group meetings, I also could have stolen it from Guy 18918579Sfenner * Almes or Matt Mathis. I don't know (or care) who came up with 19018579Sfenner * the idea first. I envy the originators' perspicacity and I'm 19118579Sfenner * glad they didn't keep the idea a secret. 19218579Sfenner * 19318579Sfenner * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or 19418579Sfenner * enhancements to the original distribution. 19518579Sfenner * 19618579Sfenner * I've hacked up a round-trip-route version of this that works by 19718579Sfenner * sending a loose-source-routed udp datagram through the destination 19818579Sfenner * back to yourself. Unfortunately, SO many gateways botch source 19918579Sfenner * routing, the thing is almost worthless. Maybe one day... 20018579Sfenner * 20118579Sfenner * -- Van Jacobson (van@ee.lbl.gov) 20218579Sfenner * Tue Dec 20 03:50:13 PST 1988 20318579Sfenner */ 20418579Sfenner 20518579Sfenner#include <sys/param.h> 206338475Soshogbo#include <sys/capsicum.h> 20718579Sfenner#include <sys/file.h> 20818579Sfenner#include <sys/ioctl.h> 20918579Sfenner#ifdef HAVE_SYS_SELECT_H 21018579Sfenner#include <sys/select.h> 21118579Sfenner#endif 21218579Sfenner#include <sys/socket.h> 21377816Sru#ifdef HAVE_SYS_SYSCTL_H 21477816Sru#include <sys/sysctl.h> 21577816Sru#endif 21618579Sfenner#include <sys/time.h> 21718579Sfenner 21818579Sfenner#include <netinet/in_systm.h> 21918579Sfenner#include <netinet/in.h> 22018579Sfenner#include <netinet/ip.h> 22118579Sfenner#include <netinet/ip_var.h> 22218579Sfenner#include <netinet/ip_icmp.h> 223283808Stuexen#include <netinet/sctp.h> 224332237Stuexen#include <netinet/sctp_header.h> 22518579Sfenner#include <netinet/udp.h> 22646542Sarchie#include <netinet/tcp.h> 227100789Sfenner#include <netinet/tcpip.h> 22818579Sfenner 22918579Sfenner#include <arpa/inet.h> 23018579Sfenner 231338475Soshogbo#ifdef HAVE_LIBCASPER 232338475Soshogbo#include <libcasper.h> 233338475Soshogbo#include <casper/cap_dns.h> 234338475Soshogbo#endif 235338475Soshogbo 23658804Sshin#ifdef IPSEC 23758804Sshin#include <net/route.h> 238171135Sgnn#include <netipsec/ipsec.h> /* XXX */ 23958804Sshin#endif /* IPSEC */ 24058804Sshin 24118579Sfenner#include <ctype.h> 242100787Sfenner#include <err.h> 24318579Sfenner#include <errno.h> 244100787Sfenner#include <fcntl.h> 24518579Sfenner#ifdef HAVE_MALLOC_H 24618579Sfenner#include <malloc.h> 24718579Sfenner#endif 24818579Sfenner#include <memory.h> 24918579Sfenner#include <netdb.h> 25018579Sfenner#include <stdio.h> 25118579Sfenner#include <stdlib.h> 25218579Sfenner#include <string.h> 25318579Sfenner#include <unistd.h> 25418579Sfenner 255100787Sfenner/* rfc1716 */ 256100787Sfenner#ifndef ICMP_UNREACH_FILTER_PROHIB 257100787Sfenner#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ 258100787Sfenner#endif 259100787Sfenner#ifndef ICMP_UNREACH_HOST_PRECEDENCE 260100787Sfenner#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */ 261100787Sfenner#endif 262100787Sfenner#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF 263100787Sfenner#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ 264100787Sfenner#endif 265100787Sfenner 266100787Sfenner#include "findsaddr.h" 267100787Sfenner#include "ifaddrlist.h" 268176428Srpaulo#include "as.h" 269100787Sfenner#include "traceroute.h" 270100787Sfenner 27118579Sfenner/* Maximum number of gateways (include room for one noop) */ 27218579Sfenner#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t))) 27318579Sfenner 27418579Sfenner#ifndef MAXHOSTNAMELEN 27518579Sfenner#define MAXHOSTNAMELEN 64 27618579Sfenner#endif 27718579Sfenner 27818579Sfenner#define Fprintf (void)fprintf 27918579Sfenner#define Printf (void)printf 28018579Sfenner 28146542Sarchie/* What a GRE packet header looks like */ 28246542Sarchiestruct grehdr { 28346542Sarchie u_int16_t flags; 28446542Sarchie u_int16_t proto; 28546542Sarchie u_int16_t length; /* PPTP version of these fields */ 28646542Sarchie u_int16_t callId; 28746542Sarchie}; 28846542Sarchie#ifndef IPPROTO_GRE 28946542Sarchie#define IPPROTO_GRE 47 29046542Sarchie#endif 29146542Sarchie 29246542Sarchie/* For GRE, we prepare what looks like a PPTP packet */ 29346542Sarchie#define GRE_PPTP_PROTO 0x880b 29446542Sarchie 295100787Sfenner/* Host name and address list */ 296100787Sfennerstruct hostinfo { 297100787Sfenner char *name; 298100787Sfenner int n; 299100787Sfenner u_int32_t *addrs; 300100787Sfenner}; 301100787Sfenner 30218579Sfenner/* Data section of the probe packet */ 30318579Sfennerstruct outdata { 30418579Sfenner u_char seq; /* sequence number of this packet */ 30518579Sfenner u_char ttl; /* ttl packet left with */ 30618579Sfenner struct timeval tv; /* time packet left */ 30718579Sfenner}; 30818579Sfenner 309100787Sfenner#ifndef HAVE_ICMP_NEXTMTU 310100787Sfenner/* Path MTU Discovery (RFC1191) */ 311100787Sfennerstruct my_pmtu { 312100787Sfenner u_short ipm_void; 313100787Sfenner u_short ipm_nextmtu; 31446542Sarchie}; 315100787Sfenner#endif 31646542Sarchie 31718579Sfenneru_char packet[512]; /* last inbound (icmp) packet */ 31818579Sfenner 31946542Sarchiestruct ip *outip; /* last output ip packet */ 320100787Sfenneru_char *outp; /* last output inner protocol packet */ 32118579Sfenner 322163387Sdwmalonestruct ip *hip = NULL; /* Quoted IP header */ 323163387Sdwmaloneint hiplen = 0; 324163387Sdwmalone 32518579Sfenner/* loose source route gateway list (including room for final destination) */ 32618579Sfenneru_int32_t gwlist[NGATEWAYS + 1]; 32718579Sfenner 32818579Sfennerint s; /* receive (icmp) socket file descriptor */ 32918579Sfennerint sndsock; /* send (udp) socket file descriptor */ 33018579Sfenner 33118579Sfennerstruct sockaddr whereto; /* Who to try to reach */ 332100787Sfennerstruct sockaddr wherefrom; /* Who we are */ 33318579Sfennerint packlen; /* total length of packet */ 33446542Sarchieint protlen; /* length of protocol part of packet */ 335100787Sfennerint minpacket; /* min ip packet size */ 33618579Sfennerint maxpacket = 32 * 1024; /* max ip packet size */ 337100787Sfennerint pmtu; /* Path MTU Discovery (RFC1191) */ 338100787Sfenneru_int pausemsecs; 33918579Sfenner 34018579Sfennerchar *prog; 34118579Sfennerchar *source; 34218579Sfennerchar *hostname; 343100787Sfennerchar *device; 344100787Sfennerstatic const char devnull[] = "/dev/null"; 34518579Sfenner 346163387Sdwmaloneint nprobes = -1; 34777816Sruint max_ttl; 348100787Sfennerint first_ttl = 1; 34918579Sfenneru_short ident; 35046542Sarchieu_short port; /* protocol specific base "port" */ 35118579Sfenner 35218579Sfennerint options; /* socket options */ 35318579Sfennerint verbose; 35418579Sfennerint waittime = 5; /* time to wait for response (in seconds) */ 35518579Sfennerint nflag; /* print addresses numerically */ 356176428Srpauloint as_path; /* print as numbers for each hop */ 357176428Srpaulochar *as_server = NULL; 358176428Srpaulovoid *asn; 359100787Sfenner#ifdef CANT_HACK_IPCKSUM 360100787Sfennerint doipcksum = 0; /* don't calculate ip checksums by default */ 361100787Sfenner#else 362100787Sfennerint doipcksum = 1; /* calculate ip checksums by default */ 363100787Sfenner#endif 364100787Sfennerint optlen; /* length of ip options */ 365158424Scjcint fixedPort = 0; /* Use fixed destination port for TCP and UDP */ 366163387Sdwmaloneint printdiff = 0; /* Print the difference between sent and quoted */ 36718579Sfenner 36818579Sfennerextern int optind; 36918579Sfennerextern int opterr; 37018579Sfennerextern char *optarg; 37118579Sfenner 372338475Soshogbo#ifdef HAVE_LIBCASPER 373338475Soshogbostatic cap_channel_t *capdns; 374338475Soshogbo#endif 375338475Soshogbo 37618579Sfenner/* Forwards */ 37718579Sfennerdouble deltaT(struct timeval *, struct timeval *); 378100787Sfennervoid freehostinfo(struct hostinfo *); 379100787Sfennervoid getaddr(u_int32_t *, char *); 380100787Sfennerstruct hostinfo *gethostinfo(char *); 381100535Sfenneru_short in_cksum(u_short *, int); 382283808Stuexenu_int32_t sctp_crc32c(const void *, u_int32_t); 38318579Sfennerchar *inetname(struct in_addr); 38418579Sfennerint main(int, char **); 385283817Stuexenu_short p_cksum(struct ip *, u_short *, int, int); 38618579Sfennerint packet_ok(u_char *, int, struct sockaddr_in *, int); 38718579Sfennerchar *pr_type(u_char); 38818579Sfennervoid print(u_char *, int, struct sockaddr_in *); 38958804Sshin#ifdef IPSEC 39058804Sshinint setpolicy __P((int so, char *policy)); 39158804Sshin#endif 39246542Sarchievoid send_probe(int, int); 393100787Sfennerstruct outproto *setproto(char *); 394100787Sfennerint str2val(const char *, const char *, int, int); 39518579Sfennervoid tvsub(struct timeval *, struct timeval *); 39667682Sobrienvoid usage(void); 397100787Sfennerint wait_for_reply(int, struct sockaddr_in *, const struct timeval *); 398163387Sdwmalonevoid pkt_compare(const u_char *, int, const u_char *, int); 399100787Sfenner#ifndef HAVE_USLEEP 400100787Sfennerint usleep(u_int); 401100787Sfenner#endif 40218579Sfenner 40346542Sarchievoid udp_prep(struct outdata *); 40446542Sarchieint udp_check(const u_char *, int); 405283817Stuexenvoid udplite_prep(struct outdata *); 406283817Stuexenint udplite_check(const u_char *, int); 40746542Sarchievoid tcp_prep(struct outdata *); 40846542Sarchieint tcp_check(const u_char *, int); 409283808Stuexenvoid sctp_prep(struct outdata *); 410283808Stuexenint sctp_check(const u_char *, int); 41146542Sarchievoid gre_prep(struct outdata *); 41246542Sarchieint gre_check(const u_char *, int); 41346542Sarchievoid gen_prep(struct outdata *); 41446542Sarchieint gen_check(const u_char *, int); 415100535Sfennervoid icmp_prep(struct outdata *); 416100535Sfennerint icmp_check(const u_char *, int); 41746542Sarchie 418100787Sfenner/* Descriptor structure for each outgoing protocol we support */ 419100787Sfennerstruct outproto { 420100787Sfenner char *name; /* name of protocol */ 421163387Sdwmalone const char *key; /* An ascii key for the bytes of the header */ 422100787Sfenner u_char num; /* IP protocol number */ 423100787Sfenner u_short hdrlen; /* max size of protocol header */ 424100787Sfenner u_short port; /* default base protocol-specific "port" */ 425100787Sfenner void (*prepare)(struct outdata *); 426100787Sfenner /* finish preparing an outgoing packet */ 427100787Sfenner int (*check)(const u_char *, int); 428100787Sfenner /* check an incoming packet */ 429100787Sfenner}; 430100787Sfenner 43146542Sarchie/* List of supported protocols. The first one is the default. The last 43246542Sarchie one is the handler for generic protocols not explicitly listed. */ 43346542Sarchiestruct outproto protos[] = { 43446542Sarchie { 43546542Sarchie "udp", 436163387Sdwmalone "spt dpt len sum", 43746542Sarchie IPPROTO_UDP, 43846542Sarchie sizeof(struct udphdr), 43946542Sarchie 32768 + 666, 44046542Sarchie udp_prep, 44146542Sarchie udp_check 44246542Sarchie }, 44346542Sarchie { 444283817Stuexen "udplite", 445283817Stuexen "spt dpt cov sum", 446283817Stuexen IPPROTO_UDPLITE, 447283817Stuexen sizeof(struct udphdr), 448283817Stuexen 32768 + 666, 449283817Stuexen udplite_prep, 450283817Stuexen udplite_check 451283817Stuexen }, 452283817Stuexen { 45346542Sarchie "tcp", 454163387Sdwmalone "spt dpt seq ack xxflwin sum urp", 45546542Sarchie IPPROTO_TCP, 45646542Sarchie sizeof(struct tcphdr), 45746542Sarchie 32768 + 666, 45846542Sarchie tcp_prep, 45946542Sarchie tcp_check 46046542Sarchie }, 46146542Sarchie { 462283808Stuexen "sctp", 463283808Stuexen "spt dpt vtag crc tyfllen tyfllen ", 464283808Stuexen IPPROTO_SCTP, 465283808Stuexen sizeof(struct sctphdr), 466283808Stuexen 32768 + 666, 467283808Stuexen sctp_prep, 468283808Stuexen sctp_check 469283808Stuexen }, 470283808Stuexen { 47146542Sarchie "gre", 472163387Sdwmalone "flg pro len clid", 47346542Sarchie IPPROTO_GRE, 47446542Sarchie sizeof(struct grehdr), 47546542Sarchie GRE_PPTP_PROTO, 47646542Sarchie gre_prep, 47746542Sarchie gre_check 47846542Sarchie }, 47946542Sarchie { 480100535Sfenner "icmp", 481163387Sdwmalone "typ cod sum ", 482100535Sfenner IPPROTO_ICMP, 483100535Sfenner sizeof(struct icmp), 484100535Sfenner 0, 485100535Sfenner icmp_prep, 486100535Sfenner icmp_check 487100535Sfenner }, 488100535Sfenner { 48946542Sarchie NULL, 490283813Stuexen "", 49146542Sarchie 0, 49246542Sarchie 2 * sizeof(u_short), 49346542Sarchie 0, 49446542Sarchie gen_prep, 49546542Sarchie gen_check 49646542Sarchie }, 49746542Sarchie}; 49846542Sarchiestruct outproto *proto = &protos[0]; 49946542Sarchie 500163387Sdwmaloneconst char *ip_hdr_key = "vhtslen id off tlprsum srcip dstip opts"; 501163387Sdwmalone 50218579Sfennerint 50318579Sfennermain(int argc, char **argv) 50418579Sfenner{ 505100787Sfenner register int op, code, n; 50618579Sfenner register char *cp; 507100787Sfenner register const char *err; 508100787Sfenner register u_int32_t *ap; 509100787Sfenner register struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom; 51018579Sfenner register struct sockaddr_in *to = (struct sockaddr_in *)&whereto; 511100787Sfenner register struct hostinfo *hi; 51218579Sfenner int on = 1; 51318579Sfenner register struct protoent *pe; 51418579Sfenner register int ttl, probe, i; 51518579Sfenner register int seq = 0; 516100787Sfenner int tos = 0, settos = 0; 51718579Sfenner register int lsrr = 0; 518100787Sfenner register u_short off = 0; 519100787Sfenner struct ifaddrlist *al; 520100787Sfenner char errbuf[132]; 52148221Sarchie int requestPort = -1; 52218803Ssef int sump = 0; 52318583Sfenner int sockerrno; 524338475Soshogbo#ifdef HAVE_LIBCASPER 525338475Soshogbo const char *types[] = { "NAME", "ADDR" }; 526338475Soshogbo int families[1]; 527338475Soshogbo cap_channel_t *casper; 528338475Soshogbo#endif 529338475Soshogbo cap_rights_t rights; 530338475Soshogbo bool cansandbox; 53118579Sfenner 532100787Sfenner /* Insure the socket fds won't be 0, 1 or 2 */ 533100787Sfenner if (open(devnull, O_RDONLY) < 0 || 534100787Sfenner open(devnull, O_RDONLY) < 0 || 535100787Sfenner open(devnull, O_RDONLY) < 0) { 536100787Sfenner Fprintf(stderr, "%s: open \"%s\": %s\n", 537100787Sfenner prog, devnull, strerror(errno)); 538100787Sfenner exit(1); 539100787Sfenner } 54018583Sfenner /* 54118583Sfenner * Do the setuid-required stuff first, then lose priveleges ASAP. 54218583Sfenner * Do error checking for these two calls where they appeared in 54318583Sfenner * the original code. 54418583Sfenner */ 54518583Sfenner cp = "icmp"; 54618583Sfenner pe = getprotobyname(cp); 54718583Sfenner if (pe) { 54818583Sfenner if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) 54918583Sfenner sockerrno = errno; 55018583Sfenner else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 55118583Sfenner sockerrno = errno; 55218583Sfenner } 55318583Sfenner 554220968Ssimon if (setuid(getuid()) != 0) { 555220968Ssimon perror("setuid()"); 556220968Ssimon exit(1); 557220968Ssimon } 55818583Sfenner 559338475Soshogbo#ifdef HAVE_LIBCASPER 560338475Soshogbo casper = cap_init(); 561338475Soshogbo if (casper == NULL) 562338475Soshogbo errx(1, "unable to create casper process"); 563338475Soshogbo capdns = cap_service_open(casper, "system.dns"); 564338475Soshogbo if (capdns == NULL) 565338475Soshogbo errx(1, "unable to open system.dns service"); 566338475Soshogbo if (cap_dns_type_limit(capdns, types, 2) < 0) 567338475Soshogbo errx(1, "unable to limit access to system.dns service"); 568338475Soshogbo families[0] = AF_INET; 569338475Soshogbo if (cap_dns_family_limit(capdns, families, 1) < 0) 570338475Soshogbo errx(1, "unable to limit access to system.dns service"); 571338475Soshogbo#endif /* HAVE_LIBCASPER */ 572338475Soshogbo 57377816Sru#ifdef IPCTL_DEFTTL 57477816Sru { 57577816Sru int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; 57677816Sru size_t sz = sizeof(max_ttl); 57777816Sru 578100787Sfenner if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) { 579100787Sfenner perror("sysctl(net.inet.ip.ttl)"); 580100787Sfenner exit(1); 581100787Sfenner } 58277816Sru } 583338475Soshogbo#else /* !IPCTL_DEFTTL */ 58477816Sru max_ttl = 30; 58577816Sru#endif 58677816Sru 587338475Soshogbo#ifdef HAVE_LIBCASPER 588338475Soshogbo cap_close(casper); 589338475Soshogbo#endif 590338475Soshogbo 591100787Sfenner if (argv[0] == NULL) 592100787Sfenner prog = "traceroute"; 593100787Sfenner else if ((cp = strrchr(argv[0], '/')) != NULL) 59418579Sfenner prog = cp + 1; 59518579Sfenner else 59618579Sfenner prog = argv[0]; 59718579Sfenner 59818579Sfenner opterr = 0; 599176428Srpaulo while ((op = getopt(argc, argv, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) 60018579Sfenner switch (op) { 601176428Srpaulo case 'a': 602176428Srpaulo as_path = 1; 603176428Srpaulo break; 604283784Stuexen 605176428Srpaulo case 'A': 606176428Srpaulo as_path = 1; 607176428Srpaulo as_server = optarg; 608176428Srpaulo break; 609283784Stuexen 61018579Sfenner case 'd': 61118579Sfenner options |= SO_DEBUG; 61218579Sfenner break; 61318579Sfenner 614163387Sdwmalone case 'D': 615163387Sdwmalone printdiff = 1; 616163387Sdwmalone break; 617163387Sdwmalone 618158424Scjc case 'e': 619158424Scjc fixedPort = 1; 620158424Scjc break; 621158424Scjc 622100787Sfenner case 'f': 623100787Sfenner case 'M': /* FreeBSD compat. */ 624100787Sfenner first_ttl = str2val(optarg, "first ttl", 1, 255); 625100787Sfenner break; 626100787Sfenner 627100787Sfenner case 'F': 628100787Sfenner off = IP_DF; 629100787Sfenner break; 630100787Sfenner 63118579Sfenner case 'g': 63218579Sfenner if (lsrr >= NGATEWAYS) { 63318579Sfenner Fprintf(stderr, 63418579Sfenner "%s: No more than %d gateways\n", 63518579Sfenner prog, NGATEWAYS); 63618579Sfenner exit(1); 63718579Sfenner } 638100787Sfenner getaddr(gwlist + lsrr, optarg); 63918579Sfenner ++lsrr; 64018579Sfenner break; 64118579Sfenner 642100787Sfenner case 'i': 643100787Sfenner device = optarg; 64447071Sarchie break; 64547071Sarchie 646100787Sfenner case 'I': 647100787Sfenner proto = setproto("icmp"); 648100787Sfenner break; 649100787Sfenner 65018579Sfenner case 'm': 651100787Sfenner max_ttl = str2val(optarg, "max ttl", 1, 255); 65218579Sfenner break; 65318579Sfenner 65418579Sfenner case 'n': 65518579Sfenner ++nflag; 65618579Sfenner break; 65718579Sfenner 65846542Sarchie case 'P': 659100787Sfenner proto = setproto(optarg); 66046542Sarchie break; 66146542Sarchie 66218579Sfenner case 'p': 663100787Sfenner requestPort = (u_short)str2val(optarg, "port", 664100787Sfenner 1, (1 << 16) - 1); 66518579Sfenner break; 66618579Sfenner 66718579Sfenner case 'q': 668100787Sfenner nprobes = str2val(optarg, "nprobes", 1, -1); 66918579Sfenner break; 67018579Sfenner 67118579Sfenner case 'r': 67218579Sfenner options |= SO_DONTROUTE; 67318579Sfenner break; 67418579Sfenner 67518579Sfenner case 's': 67618579Sfenner /* 67718579Sfenner * set the ip source address of the outbound 67818579Sfenner * probe (e.g., on a multi-homed host). 67918579Sfenner */ 68018579Sfenner source = optarg; 68118579Sfenner break; 68218579Sfenner 683100787Sfenner case 'S': 684100787Sfenner sump = 1; 685100787Sfenner break; 686100787Sfenner 68718579Sfenner case 't': 688100787Sfenner tos = str2val(optarg, "tos", 0, 255); 689100787Sfenner ++settos; 69018579Sfenner break; 69118579Sfenner 69218579Sfenner case 'v': 69318579Sfenner ++verbose; 69418579Sfenner break; 69518579Sfenner 696100787Sfenner case 'x': 697100787Sfenner doipcksum = (doipcksum == 0); 698100787Sfenner break; 699100787Sfenner 70018579Sfenner case 'w': 701100787Sfenner waittime = str2val(optarg, "wait time", 702169144Smaxim 1, 24 * 60 * 60); 70318579Sfenner break; 70418579Sfenner 705100787Sfenner case 'z': 706100787Sfenner pausemsecs = str2val(optarg, "pause msecs", 707100787Sfenner 0, 60 * 60 * 1000); 708100787Sfenner break; 709100787Sfenner 71018579Sfenner default: 71118579Sfenner usage(); 71218579Sfenner } 71318579Sfenner 71448221Sarchie /* Set requested port, if any, else default for this protocol */ 71548221Sarchie port = (requestPort != -1) ? requestPort : proto->port; 71648221Sarchie 717163387Sdwmalone if (nprobes == -1) 718163387Sdwmalone nprobes = printdiff ? 1 : 3; 719163387Sdwmalone 720100787Sfenner if (first_ttl > max_ttl) { 721100787Sfenner Fprintf(stderr, 722100787Sfenner "%s: first ttl (%d) may not be greater than max ttl (%d)\n", 723100787Sfenner prog, first_ttl, max_ttl); 72447071Sarchie exit(1); 72547071Sarchie } 72647071Sarchie 727100787Sfenner if (!doipcksum) 728100787Sfenner Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog); 729100787Sfenner 730100787Sfenner if (lsrr > 0) 731100787Sfenner optlen = (lsrr + 1) * sizeof(gwlist[0]); 732283786Stuexen minpacket = sizeof(*outip) + proto->hdrlen + optlen; 733283786Stuexen if (minpacket > 40) 734283786Stuexen packlen = minpacket; 735283786Stuexen else 736283786Stuexen packlen = 40; 737100787Sfenner 73818579Sfenner /* Process destination and optional packet size */ 73918579Sfenner switch (argc - optind) { 74018579Sfenner 74118579Sfenner case 2: 742100787Sfenner packlen = str2val(argv[optind + 1], 743100787Sfenner "packet length", minpacket, maxpacket); 744100787Sfenner /* Fall through */ 74518579Sfenner 74618579Sfenner case 1: 747100787Sfenner hostname = argv[optind]; 748100787Sfenner hi = gethostinfo(hostname); 749100787Sfenner setsin(to, hi->addrs[0]); 750100787Sfenner if (hi->n > 1) 751100787Sfenner Fprintf(stderr, 752100787Sfenner "%s: Warning: %s has multiple addresses; using %s\n", 753100787Sfenner prog, hostname, inet_ntoa(to->sin_addr)); 754100787Sfenner hostname = hi->name; 755100787Sfenner hi->name = NULL; 756100787Sfenner freehostinfo(hi); 75718579Sfenner break; 75818579Sfenner 75918579Sfenner default: 76018579Sfenner usage(); 76118579Sfenner } 76218579Sfenner 76318579Sfenner#ifdef HAVE_SETLINEBUF 76418579Sfenner setlinebuf (stdout); 76518579Sfenner#else 76618579Sfenner setvbuf(stdout, NULL, _IOLBF, 0); 76718579Sfenner#endif 76818579Sfenner 76946542Sarchie protlen = packlen - sizeof(*outip) - optlen; 770283808Stuexen if ((proto->num == IPPROTO_SCTP) && (packlen & 3)) { 771283808Stuexen Fprintf(stderr, "%s: packet length must be a multiple of 4\n", 772283808Stuexen prog); 773283808Stuexen exit(1); 774283808Stuexen } 77518579Sfenner 77618579Sfenner outip = (struct ip *)malloc((unsigned)packlen); 77718579Sfenner if (outip == NULL) { 77818579Sfenner Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno)); 77918579Sfenner exit(1); 78018579Sfenner } 78118579Sfenner memset((char *)outip, 0, packlen); 78218579Sfenner 78318579Sfenner outip->ip_v = IPVERSION; 784100787Sfenner if (settos) 785100787Sfenner outip->ip_tos = tos; 786100787Sfenner#ifdef BYTESWAP_IP_HDR 78718579Sfenner outip->ip_len = htons(packlen); 788100787Sfenner outip->ip_off = htons(off); 78918579Sfenner#else 79018579Sfenner outip->ip_len = packlen; 791100787Sfenner outip->ip_off = off; 79218579Sfenner#endif 79346542Sarchie outip->ip_p = proto->num; 794100787Sfenner outp = (u_char *)(outip + 1); 79518579Sfenner#ifdef HAVE_RAW_OPTIONS 79618579Sfenner if (lsrr > 0) { 79718579Sfenner register u_char *optlist; 79818579Sfenner 799100787Sfenner optlist = outp; 800100787Sfenner outp += optlen; 80118579Sfenner 80218579Sfenner /* final hop */ 80318579Sfenner gwlist[lsrr] = to->sin_addr.s_addr; 80418579Sfenner 80518579Sfenner outip->ip_dst.s_addr = gwlist[0]; 80618579Sfenner 80718579Sfenner /* force 4 byte alignment */ 80818579Sfenner optlist[0] = IPOPT_NOP; 80918579Sfenner /* loose source route option */ 81018579Sfenner optlist[1] = IPOPT_LSRR; 81118579Sfenner i = lsrr * sizeof(gwlist[0]); 81218579Sfenner optlist[2] = i + 3; 81318579Sfenner /* Pointer to LSRR addresses */ 81418579Sfenner optlist[3] = IPOPT_MINOFF; 81518579Sfenner memcpy(optlist + 4, gwlist + 1, i); 81618579Sfenner } else 81718579Sfenner#endif 81818579Sfenner outip->ip_dst = to->sin_addr; 81918579Sfenner 820100787Sfenner outip->ip_hl = (outp - (u_char *)outip) >> 2; 82118579Sfenner ident = (getpid() & 0xffff) | 0x8000; 82218579Sfenner 82318583Sfenner if (pe == NULL) { 82418579Sfenner Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 82518579Sfenner exit(1); 82618579Sfenner } 82718583Sfenner if (s < 0) { 82818583Sfenner errno = sockerrno; 82918579Sfenner Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno)); 83018579Sfenner exit(1); 83118579Sfenner } 83218579Sfenner if (options & SO_DEBUG) 83318579Sfenner (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, 83418579Sfenner sizeof(on)); 83518579Sfenner if (options & SO_DONTROUTE) 83618579Sfenner (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 83718579Sfenner sizeof(on)); 83818579Sfenner 83958804Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 84058804Sshin if (setpolicy(s, "in bypass") < 0) 84166809Skris errx(1, "%s", ipsec_strerror()); 84258804Sshin 84358804Sshin if (setpolicy(s, "out bypass") < 0) 84466809Skris errx(1, "%s", ipsec_strerror()); 84558804Sshin#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */ 84658804Sshin 84718583Sfenner if (sndsock < 0) { 84818583Sfenner errno = sockerrno; 84918579Sfenner Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno)); 85018579Sfenner exit(1); 85118579Sfenner } 85218579Sfenner 85318579Sfenner#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS) 85418579Sfenner if (lsrr > 0) { 85518579Sfenner u_char optlist[MAX_IPOPTLEN]; 85618579Sfenner 85718579Sfenner cp = "ip"; 85818579Sfenner if ((pe = getprotobyname(cp)) == NULL) { 85918579Sfenner Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 86018579Sfenner exit(1); 86118579Sfenner } 86218579Sfenner 86318579Sfenner /* final hop */ 86418579Sfenner gwlist[lsrr] = to->sin_addr.s_addr; 86518579Sfenner ++lsrr; 86618579Sfenner 86718579Sfenner /* force 4 byte alignment */ 86818579Sfenner optlist[0] = IPOPT_NOP; 86918579Sfenner /* loose source route option */ 87018579Sfenner optlist[1] = IPOPT_LSRR; 87118579Sfenner i = lsrr * sizeof(gwlist[0]); 87218579Sfenner optlist[2] = i + 3; 87318579Sfenner /* Pointer to LSRR addresses */ 87418579Sfenner optlist[3] = IPOPT_MINOFF; 87518579Sfenner memcpy(optlist + 4, gwlist, i); 87618579Sfenner 877100787Sfenner if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, 878100787Sfenner (char *)optlist, i + sizeof(gwlist[0]))) < 0) { 87918579Sfenner Fprintf(stderr, "%s: IP_OPTIONS: %s\n", 88018579Sfenner prog, strerror(errno)); 88118579Sfenner exit(1); 88218579Sfenner } 88318579Sfenner } 88418579Sfenner#endif 88518579Sfenner 88618579Sfenner#ifdef SO_SNDBUF 88718579Sfenner if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen, 88818579Sfenner sizeof(packlen)) < 0) { 88918579Sfenner Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno)); 89018579Sfenner exit(1); 89118579Sfenner } 89218579Sfenner#endif 89318579Sfenner#ifdef IP_HDRINCL 89418579Sfenner if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, 89518579Sfenner sizeof(on)) < 0) { 89618579Sfenner Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno)); 89718579Sfenner exit(1); 89818579Sfenner } 899100787Sfenner#else 900100787Sfenner#ifdef IP_TOS 901100787Sfenner if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS, 902100787Sfenner (char *)&tos, sizeof(tos)) < 0) { 903100787Sfenner Fprintf(stderr, "%s: setsockopt tos %d: %s\n", 904100787Sfenner prog, tos, strerror(errno)); 905100787Sfenner exit(1); 906100787Sfenner } 90718579Sfenner#endif 908100787Sfenner#endif 90918579Sfenner if (options & SO_DEBUG) 91018579Sfenner (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, 91118579Sfenner sizeof(on)); 91218579Sfenner if (options & SO_DONTROUTE) 91318579Sfenner (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 91418579Sfenner sizeof(on)); 91518579Sfenner 916100787Sfenner /* Get the interface address list */ 917100787Sfenner n = ifaddrlist(&al, errbuf); 918100787Sfenner if (n < 0) { 919100787Sfenner Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf); 920100787Sfenner exit(1); 921100787Sfenner } 922100787Sfenner if (n == 0) { 923100787Sfenner Fprintf(stderr, 924100787Sfenner "%s: Can't find any network interfaces\n", prog); 925100787Sfenner exit(1); 926100787Sfenner } 927100787Sfenner 928100787Sfenner /* Look for a specific device */ 929100787Sfenner if (device != NULL) { 930100787Sfenner for (i = n; i > 0; --i, ++al) 931100787Sfenner if (strcmp(device, al->device) == 0) 932100787Sfenner break; 933100787Sfenner if (i <= 0) { 934100787Sfenner Fprintf(stderr, "%s: Can't find interface %.32s\n", 935100787Sfenner prog, device); 936100787Sfenner exit(1); 93718579Sfenner } 93818579Sfenner } 93918579Sfenner 940100787Sfenner /* Determine our source address */ 941100787Sfenner if (source == NULL) { 942100787Sfenner /* 943100787Sfenner * If a device was specified, use the interface address. 944100787Sfenner * Otherwise, try to determine our source address. 945100787Sfenner */ 946100787Sfenner if (device != NULL) 947100787Sfenner setsin(from, al->addr); 948100787Sfenner else if ((err = findsaddr(to, from)) != NULL) { 949100787Sfenner Fprintf(stderr, "%s: findsaddr: %s\n", 950100787Sfenner prog, err); 951100787Sfenner exit(1); 952100787Sfenner } 953100787Sfenner } else { 954100787Sfenner hi = gethostinfo(source); 955100787Sfenner source = hi->name; 956100787Sfenner hi->name = NULL; 957100787Sfenner /* 958100787Sfenner * If the device was specified make sure it 959100787Sfenner * corresponds to the source address specified. 960100787Sfenner * Otherwise, use the first address (and warn if 961100787Sfenner * there are more than one). 962100787Sfenner */ 963100787Sfenner if (device != NULL) { 964100787Sfenner for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) 965100787Sfenner if (*ap == al->addr) 966100787Sfenner break; 967100787Sfenner if (i <= 0) { 968100787Sfenner Fprintf(stderr, 969100787Sfenner "%s: %s is not on interface %.32s\n", 970100787Sfenner prog, source, device); 971100787Sfenner exit(1); 972100787Sfenner } 973100787Sfenner setsin(from, *ap); 974100787Sfenner } else { 975100787Sfenner setsin(from, hi->addrs[0]); 976100787Sfenner if (hi->n > 1) 977100787Sfenner Fprintf(stderr, 978100787Sfenner "%s: Warning: %s has multiple addresses; using %s\n", 979100787Sfenner prog, source, inet_ntoa(from->sin_addr)); 980100787Sfenner } 981100787Sfenner freehostinfo(hi); 982100787Sfenner } 983100787Sfenner 984100787Sfenner outip->ip_src = from->sin_addr; 985128365Spb 986128365Spb /* Check the source address (-s), if any, is valid */ 987100787Sfenner if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) { 988100787Sfenner Fprintf(stderr, "%s: bind: %s\n", 989100787Sfenner prog, strerror(errno)); 990100787Sfenner exit (1); 991100787Sfenner } 992100787Sfenner 993176428Srpaulo if (as_path) { 994176428Srpaulo asn = as_setup(as_server); 995176428Srpaulo if (asn == NULL) { 996176428Srpaulo Fprintf(stderr, "%s: as_setup failed, AS# lookups" 997176428Srpaulo " disabled\n", prog); 998176428Srpaulo (void)fflush(stderr); 999176428Srpaulo as_path = 0; 1000176428Srpaulo } 1001176428Srpaulo } 1002283784Stuexen 1003338475Soshogbo if (connect(sndsock, (struct sockaddr *)&whereto, 1004338475Soshogbo sizeof(whereto)) != 0) { 1005338475Soshogbo Fprintf(stderr, "%s: connect: %s\n", prog, strerror(errno)); 1006338475Soshogbo exit(1); 1007338475Soshogbo } 1008338475Soshogbo 1009338475Soshogbo#ifdef HAVE_LIBCASPER 1010338475Soshogbo cansandbox = true; 1011338475Soshogbo#else 1012338475Soshogbo if (nflag) 1013338475Soshogbo cansandbox = true; 1014338475Soshogbo else 1015338475Soshogbo cansandbox = false; 1016338475Soshogbo#endif 1017338475Soshogbo 1018338475Soshogbo /* 1019338475Soshogbo * Here we enter capability mode. Further down access to global 1020338475Soshogbo * namespaces (e.g filesystem) is restricted (see capsicum(4)). 1021338475Soshogbo * We must connect(2) our socket before this point. 1022338475Soshogbo */ 1023338475Soshogbo if (cansandbox && cap_enter() < 0) { 1024339045Soshogbo if (errno != ENOSYS) { 1025339045Soshogbo Fprintf(stderr, "%s: cap_enter: %s\n", prog, 1026339045Soshogbo strerror(errno)); 1027339045Soshogbo exit(1); 1028339045Soshogbo } else { 1029339045Soshogbo cansandbox = false; 1030339045Soshogbo } 1031338475Soshogbo } 1032338475Soshogbo 1033338475Soshogbo cap_rights_init(&rights, CAP_SEND, CAP_SETSOCKOPT); 1034338475Soshogbo if (cansandbox && cap_rights_limit(sndsock, &rights) < 0) { 1035338475Soshogbo Fprintf(stderr, "%s: cap_rights_limit sndsock: %s\n", prog, 1036338475Soshogbo strerror(errno)); 1037338475Soshogbo exit(1); 1038338475Soshogbo } 1039338475Soshogbo 1040338475Soshogbo cap_rights_init(&rights, CAP_RECV, CAP_EVENT); 1041338475Soshogbo if (cansandbox && cap_rights_limit(s, &rights) < 0) { 1042338475Soshogbo Fprintf(stderr, "%s: cap_rights_limit s: %s\n", prog, 1043338475Soshogbo strerror(errno)); 1044338475Soshogbo exit(1); 1045338475Soshogbo } 1046338475Soshogbo 104758804Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 104858804Sshin if (setpolicy(sndsock, "in bypass") < 0) 104966809Skris errx(1, "%s", ipsec_strerror()); 105058804Sshin 105158804Sshin if (setpolicy(sndsock, "out bypass") < 0) 105266809Skris errx(1, "%s", ipsec_strerror()); 105358804Sshin#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */ 105458804Sshin 105518579Sfenner Fprintf(stderr, "%s to %s (%s)", 105618579Sfenner prog, hostname, inet_ntoa(to->sin_addr)); 105718579Sfenner if (source) 105818579Sfenner Fprintf(stderr, " from %s", source); 105918579Sfenner Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen); 106018579Sfenner (void)fflush(stderr); 106118579Sfenner 1062100787Sfenner for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { 106318579Sfenner u_int32_t lastaddr = 0; 1064100787Sfenner int gotlastaddr = 0; 106518579Sfenner int got_there = 0; 106618579Sfenner int unreachable = 0; 1067100787Sfenner int sentfirst = 0; 106818695Ssef int loss; 106918579Sfenner 107018579Sfenner Printf("%2d ", ttl); 107118695Ssef for (probe = 0, loss = 0; probe < nprobes; ++probe) { 107218579Sfenner register int cc; 107318579Sfenner struct timeval t1, t2; 107418579Sfenner register struct ip *ip; 107546542Sarchie struct outdata outdata; 107618579Sfenner 1077100787Sfenner if (sentfirst && pausemsecs > 0) 1078100787Sfenner usleep(pausemsecs * 1000); 107946542Sarchie /* Prepare outgoing data */ 108046542Sarchie outdata.seq = ++seq; 108146542Sarchie outdata.ttl = ttl; 108246542Sarchie 108346542Sarchie /* Avoid alignment problems by copying bytewise: */ 1084211062Sed (void)gettimeofday(&t1, NULL); 108546542Sarchie memcpy(&outdata.tv, &t1, sizeof(outdata.tv)); 108646542Sarchie 108746542Sarchie /* Finalize and send packet */ 108846542Sarchie (*proto->prepare)(&outdata); 108946542Sarchie send_probe(seq, ttl); 1090100787Sfenner ++sentfirst; 109146542Sarchie 109246542Sarchie /* Wait for a reply */ 1093100787Sfenner while ((cc = wait_for_reply(s, from, &t1)) != 0) { 109418583Sfenner double T; 109518583Sfenner int precis; 109618583Sfenner 1097211062Sed (void)gettimeofday(&t2, NULL); 1098100787Sfenner i = packet_ok(packet, cc, from, seq); 109918579Sfenner /* Skip short packet */ 110018579Sfenner if (i == 0) 110118579Sfenner continue; 1102100787Sfenner if (!gotlastaddr || 1103100787Sfenner from->sin_addr.s_addr != lastaddr) { 1104154192Spav if (gotlastaddr) printf("\n "); 1105100787Sfenner print(packet, cc, from); 1106100787Sfenner lastaddr = from->sin_addr.s_addr; 1107100787Sfenner ++gotlastaddr; 110818579Sfenner } 110918583Sfenner T = deltaT(&t1, &t2); 111018583Sfenner#ifdef SANE_PRECISION 111118583Sfenner if (T >= 1000.0) 111218583Sfenner precis = 0; 111318583Sfenner else if (T >= 100.0) 111418583Sfenner precis = 1; 111518583Sfenner else if (T >= 10.0) 111618583Sfenner precis = 2; 111718583Sfenner else 111818583Sfenner#endif 111918583Sfenner precis = 3; 112018583Sfenner Printf(" %.*f ms", precis, T); 1121163387Sdwmalone if (printdiff) { 1122163387Sdwmalone Printf("\n"); 1123163387Sdwmalone Printf("%*.*s%s\n", 1124163387Sdwmalone -(outip->ip_hl << 3), 1125163387Sdwmalone outip->ip_hl << 3, 1126163387Sdwmalone ip_hdr_key, 1127163387Sdwmalone proto->key); 1128163387Sdwmalone pkt_compare((void *)outip, packlen, 1129163387Sdwmalone (void *)hip, hiplen); 1130163387Sdwmalone } 1131100535Sfenner if (i == -2) { 1132100567Sdcs#ifndef ARCHAIC 1133100535Sfenner ip = (struct ip *)packet; 1134100535Sfenner if (ip->ip_ttl <= 1) 1135100535Sfenner Printf(" !"); 1136100535Sfenner#endif 1137100535Sfenner ++got_there; 1138100535Sfenner break; 1139100535Sfenner } 114018579Sfenner /* time exceeded in transit */ 114118579Sfenner if (i == -1) 114218579Sfenner break; 114318579Sfenner code = i - 1; 114418579Sfenner switch (code) { 114518579Sfenner 114618579Sfenner case ICMP_UNREACH_PORT: 114718579Sfenner#ifndef ARCHAIC 114818579Sfenner ip = (struct ip *)packet; 114918579Sfenner if (ip->ip_ttl <= 1) 115018579Sfenner Printf(" !"); 115118579Sfenner#endif 115218579Sfenner ++got_there; 115318579Sfenner break; 115418579Sfenner 115518579Sfenner case ICMP_UNREACH_NET: 115618579Sfenner ++unreachable; 115718579Sfenner Printf(" !N"); 115818579Sfenner break; 115918579Sfenner 116018579Sfenner case ICMP_UNREACH_HOST: 116118579Sfenner ++unreachable; 116218579Sfenner Printf(" !H"); 116318579Sfenner break; 116418579Sfenner 116518579Sfenner case ICMP_UNREACH_PROTOCOL: 116618579Sfenner ++got_there; 116718579Sfenner Printf(" !P"); 116818579Sfenner break; 116918579Sfenner 117018579Sfenner case ICMP_UNREACH_NEEDFRAG: 117118579Sfenner ++unreachable; 1172100787Sfenner Printf(" !F-%d", pmtu); 117318579Sfenner break; 117418579Sfenner 117518579Sfenner case ICMP_UNREACH_SRCFAIL: 117618579Sfenner ++unreachable; 117718579Sfenner Printf(" !S"); 117818579Sfenner break; 117918579Sfenner 1180159576Sdwmalone case ICMP_UNREACH_NET_UNKNOWN: 1181159576Sdwmalone ++unreachable; 1182159576Sdwmalone Printf(" !U"); 1183159576Sdwmalone break; 1184159576Sdwmalone 1185159576Sdwmalone case ICMP_UNREACH_HOST_UNKNOWN: 1186159576Sdwmalone ++unreachable; 1187159576Sdwmalone Printf(" !W"); 1188159576Sdwmalone break; 1189159576Sdwmalone 1190159576Sdwmalone case ICMP_UNREACH_ISOLATED: 1191159576Sdwmalone ++unreachable; 1192159576Sdwmalone Printf(" !I"); 1193159576Sdwmalone break; 1194159576Sdwmalone 1195159576Sdwmalone case ICMP_UNREACH_NET_PROHIB: 1196159576Sdwmalone ++unreachable; 1197159576Sdwmalone Printf(" !A"); 1198159576Sdwmalone break; 1199159576Sdwmalone 1200159576Sdwmalone case ICMP_UNREACH_HOST_PROHIB: 1201159576Sdwmalone ++unreachable; 1202159576Sdwmalone Printf(" !Z"); 1203159576Sdwmalone break; 1204159576Sdwmalone 1205159576Sdwmalone case ICMP_UNREACH_TOSNET: 1206159576Sdwmalone ++unreachable; 1207159576Sdwmalone Printf(" !Q"); 1208159576Sdwmalone break; 1209159576Sdwmalone 1210159576Sdwmalone case ICMP_UNREACH_TOSHOST: 1211159576Sdwmalone ++unreachable; 1212159576Sdwmalone Printf(" !T"); 1213159576Sdwmalone break; 1214159576Sdwmalone 121518579Sfenner case ICMP_UNREACH_FILTER_PROHIB: 121618579Sfenner ++unreachable; 121718579Sfenner Printf(" !X"); 121818579Sfenner break; 121918579Sfenner 1220100787Sfenner case ICMP_UNREACH_HOST_PRECEDENCE: 1221100787Sfenner ++unreachable; 1222100787Sfenner Printf(" !V"); 1223100787Sfenner break; 1224100787Sfenner 1225100787Sfenner case ICMP_UNREACH_PRECEDENCE_CUTOFF: 1226100787Sfenner ++unreachable; 1227100787Sfenner Printf(" !C"); 1228100787Sfenner break; 1229100787Sfenner 123018579Sfenner default: 123118579Sfenner ++unreachable; 123218579Sfenner Printf(" !<%d>", code); 123318579Sfenner break; 123418579Sfenner } 123518579Sfenner break; 123618579Sfenner } 123718695Ssef if (cc == 0) { 123818695Ssef loss++; 123918579Sfenner Printf(" *"); 124018695Ssef } 124118579Sfenner (void)fflush(stdout); 124218579Sfenner } 124318803Ssef if (sump) { 124418811Ssef Printf(" (%d%% loss)", (loss * 100) / nprobes); 124518803Ssef } 124618579Sfenner putchar('\n'); 124718579Sfenner if (got_there || 124818579Sfenner (unreachable > 0 && unreachable >= nprobes - 1)) 124918579Sfenner break; 125018579Sfenner } 1251176428Srpaulo if (as_path) 1252176428Srpaulo as_shutdown(asn); 125318579Sfenner exit(0); 125418579Sfenner} 125518579Sfenner 125618579Sfennerint 125718579Sfennerwait_for_reply(register int sock, register struct sockaddr_in *fromp, 1258100787Sfenner register const struct timeval *tp) 125918579Sfenner{ 126066810Skris fd_set *fdsp; 126166810Skris size_t nfds; 126218579Sfenner struct timeval now, wait; 126318579Sfenner register int cc = 0; 126444086Sdes register int error; 126518579Sfenner int fromlen = sizeof(*fromp); 126618579Sfenner 126766810Skris nfds = howmany(sock + 1, NFDBITS); 126898709Srobert if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL) 126966810Skris err(1, "malloc"); 127098709Srobert memset(fdsp, 0, nfds * sizeof(fd_mask)); 127166810Skris FD_SET(sock, fdsp); 127218579Sfenner 127318579Sfenner wait.tv_sec = tp->tv_sec + waittime; 127418579Sfenner wait.tv_usec = tp->tv_usec; 1275211062Sed (void)gettimeofday(&now, NULL); 127618579Sfenner tvsub(&wait, &now); 127744086Sdes if (wait.tv_sec < 0) { 127844086Sdes wait.tv_sec = 0; 127944086Sdes wait.tv_usec = 1; 128044086Sdes } 128118579Sfenner 128266810Skris error = select(sock + 1, fdsp, NULL, NULL, &wait); 128344086Sdes if (error == -1 && errno == EINVAL) { 128444086Sdes Fprintf(stderr, "%s: botched select() args\n", prog); 128544086Sdes exit(1); 128644086Sdes } 128744086Sdes if (error > 0) 1288100787Sfenner cc = recvfrom(sock, (char *)packet, sizeof(packet), 0, 128918579Sfenner (struct sockaddr *)fromp, &fromlen); 129018579Sfenner 129166810Skris free(fdsp); 129218579Sfenner return(cc); 129318579Sfenner} 129418579Sfenner 1295100787Sfennervoid 1296100787Sfennersend_probe(int seq, int ttl) 1297100787Sfenner{ 1298100787Sfenner register int cc; 1299100787Sfenner 1300100787Sfenner outip->ip_ttl = ttl; 1301100787Sfenner outip->ip_id = htons(ident + seq); 1302100787Sfenner 1303100787Sfenner /* XXX undocumented debugging hack */ 1304100787Sfenner if (verbose > 1) { 1305100787Sfenner register const u_short *sp; 1306100787Sfenner register int nshorts, i; 1307100787Sfenner 1308100787Sfenner sp = (u_short *)outip; 1309100787Sfenner nshorts = (u_int)packlen / sizeof(u_short); 1310100787Sfenner i = 0; 1311100787Sfenner Printf("[ %d bytes", packlen); 1312100787Sfenner while (--nshorts >= 0) { 1313100787Sfenner if ((i++ % 8) == 0) 1314100787Sfenner Printf("\n\t"); 1315100787Sfenner Printf(" %04x", ntohs(*sp++)); 1316100787Sfenner } 1317100787Sfenner if (packlen & 1) { 1318100787Sfenner if ((i % 8) == 0) 1319100787Sfenner Printf("\n\t"); 1320100787Sfenner Printf(" %02x", *(u_char *)sp); 1321100787Sfenner } 1322100787Sfenner Printf("]\n"); 1323100787Sfenner } 1324100787Sfenner 1325100787Sfenner#if !defined(IP_HDRINCL) && defined(IP_TTL) 1326100787Sfenner if (setsockopt(sndsock, IPPROTO_IP, IP_TTL, 1327100787Sfenner (char *)&ttl, sizeof(ttl)) < 0) { 1328100787Sfenner Fprintf(stderr, "%s: setsockopt ttl %d: %s\n", 1329100787Sfenner prog, ttl, strerror(errno)); 1330100787Sfenner exit(1); 1331100787Sfenner } 1332100787Sfenner#endif 1333100787Sfenner 1334338475Soshogbo cc = send(sndsock, (char *)outip, packlen, 0); 1335100787Sfenner if (cc < 0 || cc != packlen) { 1336100787Sfenner if (cc < 0) 1337100787Sfenner Fprintf(stderr, "%s: sendto: %s\n", 1338100787Sfenner prog, strerror(errno)); 1339100787Sfenner Printf("%s: wrote %s %d chars, ret=%d\n", 1340100787Sfenner prog, hostname, packlen, cc); 1341100787Sfenner (void)fflush(stdout); 1342100787Sfenner } 1343100787Sfenner} 1344100787Sfenner 134558804Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 134658804Sshinint 134758804Sshinsetpolicy(so, policy) 134858804Sshin int so; 134958804Sshin char *policy; 135058804Sshin{ 135158804Sshin char *buf; 135258804Sshin 135358804Sshin buf = ipsec_set_policy(policy, strlen(policy)); 135458804Sshin if (buf == NULL) { 135566809Skris warnx("%s", ipsec_strerror()); 135658804Sshin return -1; 135758804Sshin } 135858804Sshin (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY, 135958804Sshin buf, ipsec_get_policylen(buf)); 136058804Sshin 136158804Sshin free(buf); 136258804Sshin 136358804Sshin return 0; 136458804Sshin} 136558804Sshin#endif 136658804Sshin 136718579Sfennerdouble 136818579SfennerdeltaT(struct timeval *t1p, struct timeval *t2p) 136918579Sfenner{ 137018579Sfenner register double dt; 137118579Sfenner 137218579Sfenner dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 137318579Sfenner (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 137418579Sfenner return (dt); 137518579Sfenner} 137618579Sfenner 137718579Sfenner/* 137818579Sfenner * Convert an ICMP "type" field to a printable string. 137918579Sfenner */ 138018579Sfennerchar * 138118579Sfennerpr_type(register u_char t) 138218579Sfenner{ 138318579Sfenner static char *ttab[] = { 138418579Sfenner "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", 138518579Sfenner "Source Quench", "Redirect", "ICMP 6", "ICMP 7", 138618579Sfenner "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", 138718579Sfenner "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", 138818579Sfenner "Info Reply" 138918579Sfenner }; 139018579Sfenner 139118579Sfenner if (t > 16) 139218579Sfenner return("OUT-OF-RANGE"); 139318579Sfenner 139418579Sfenner return(ttab[t]); 139518579Sfenner} 139618579Sfenner 139718579Sfennerint 139818579Sfennerpacket_ok(register u_char *buf, int cc, register struct sockaddr_in *from, 139918579Sfenner register int seq) 140018579Sfenner{ 140118579Sfenner register struct icmp *icp; 140218579Sfenner register u_char type, code; 140318579Sfenner register int hlen; 140418579Sfenner#ifndef ARCHAIC 140518579Sfenner register struct ip *ip; 140618579Sfenner 140718579Sfenner ip = (struct ip *) buf; 140818579Sfenner hlen = ip->ip_hl << 2; 140918579Sfenner if (cc < hlen + ICMP_MINLEN) { 141018579Sfenner if (verbose) 141118579Sfenner Printf("packet too short (%d bytes) from %s\n", cc, 141218579Sfenner inet_ntoa(from->sin_addr)); 141318579Sfenner return (0); 141418579Sfenner } 141518579Sfenner cc -= hlen; 141618579Sfenner icp = (struct icmp *)(buf + hlen); 141718579Sfenner#else 141818579Sfenner icp = (struct icmp *)buf; 141918579Sfenner#endif 142018579Sfenner type = icp->icmp_type; 142118579Sfenner code = icp->icmp_code; 1422100787Sfenner /* Path MTU Discovery (RFC1191) */ 1423100787Sfenner if (code != ICMP_UNREACH_NEEDFRAG) 1424100787Sfenner pmtu = 0; 1425100787Sfenner else { 1426100787Sfenner#ifdef HAVE_ICMP_NEXTMTU 1427100787Sfenner pmtu = ntohs(icp->icmp_nextmtu); 1428100787Sfenner#else 1429100787Sfenner pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu); 1430100787Sfenner#endif 1431100787Sfenner } 1432100535Sfenner if (type == ICMP_ECHOREPLY 1433100535Sfenner && proto->num == IPPROTO_ICMP 1434124859Scperciva && (*proto->check)((u_char *)icp, (u_char)seq)) 1435100535Sfenner return -2; 143618579Sfenner if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 143718579Sfenner type == ICMP_UNREACH) { 143846542Sarchie u_char *inner; 143918579Sfenner 144018579Sfenner hip = &icp->icmp_ip; 1441163387Sdwmalone hiplen = ((u_char *)icp + cc) - (u_char *)hip; 144218579Sfenner hlen = hip->ip_hl << 2; 144346542Sarchie inner = (u_char *)((u_char *)hip + hlen); 1444283785Stuexen if (hlen + 16 <= cc 144546542Sarchie && hip->ip_p == proto->num 1446124859Scperciva && (*proto->check)(inner, (u_char)seq)) 144718579Sfenner return (type == ICMP_TIMXCEED ? -1 : code + 1); 144818579Sfenner } 144918579Sfenner#ifndef ARCHAIC 145018579Sfenner if (verbose) { 145118579Sfenner register int i; 145218579Sfenner u_int32_t *lp = (u_int32_t *)&icp->icmp_ip; 145318579Sfenner 145418579Sfenner Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr)); 145518579Sfenner Printf("%s: icmp type %d (%s) code %d\n", 145618579Sfenner inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); 1457283806Stuexen for (i = 4; i <= cc - ICMP_MINLEN; i += sizeof(*lp)) 1458283806Stuexen Printf("%2d: %8.8x\n", i, ntohl(*lp++)); 145918579Sfenner } 146018579Sfenner#endif 146118579Sfenner return(0); 146218579Sfenner} 146318579Sfenner 146446542Sarchievoid 1465100535Sfennericmp_prep(struct outdata *outdata) 1466100535Sfenner{ 1467100787Sfenner struct icmp *const icmpheader = (struct icmp *) outp; 1468100535Sfenner 1469100535Sfenner icmpheader->icmp_type = ICMP_ECHO; 1470100535Sfenner icmpheader->icmp_id = htons(ident); 1471100535Sfenner icmpheader->icmp_seq = htons(outdata->seq); 1472100535Sfenner icmpheader->icmp_cksum = 0; 1473100789Sfenner icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen); 1474100535Sfenner if (icmpheader->icmp_cksum == 0) 1475100535Sfenner icmpheader->icmp_cksum = 0xffff; 1476100535Sfenner} 1477100535Sfenner 1478100535Sfennerint 1479100535Sfennericmp_check(const u_char *data, int seq) 1480100535Sfenner{ 1481100535Sfenner struct icmp *const icmpheader = (struct icmp *) data; 1482100535Sfenner 1483100535Sfenner return (icmpheader->icmp_id == htons(ident) 1484100535Sfenner && icmpheader->icmp_seq == htons(seq)); 1485100535Sfenner} 1486100535Sfenner 1487100535Sfennervoid 148846542Sarchieudp_prep(struct outdata *outdata) 148946542Sarchie{ 1490100787Sfenner struct udphdr *const outudp = (struct udphdr *) outp; 149118579Sfenner 1492158424Scjc outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0)); 1493158424Scjc outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq)); 1494100787Sfenner outudp->uh_ulen = htons((u_short)protlen); 1495100789Sfenner outudp->uh_sum = 0; 1496100787Sfenner if (doipcksum) { 1497283817Stuexen u_short sum = p_cksum(outip, (u_short*)outudp, protlen, protlen); 1498100789Sfenner outudp->uh_sum = (sum) ? sum : 0xffff; 1499100787Sfenner } 1500100789Sfenner 1501100789Sfenner return; 150246542Sarchie} 150346542Sarchie 150446542Sarchieint 150546542Sarchieudp_check(const u_char *data, int seq) 150646542Sarchie{ 150746542Sarchie struct udphdr *const udp = (struct udphdr *) data; 150846542Sarchie 1509158424Scjc return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) && 1510158424Scjc ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq)); 151146542Sarchie} 151246542Sarchie 151318579Sfennervoid 1514283817Stuexenudplite_prep(struct outdata *outdata) 1515283817Stuexen{ 1516283817Stuexen struct udphdr *const outudp = (struct udphdr *) outp; 1517283817Stuexen 1518283817Stuexen outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0)); 1519283817Stuexen outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq)); 1520283817Stuexen outudp->uh_ulen = htons(8); 1521283817Stuexen outudp->uh_sum = 0; 1522283817Stuexen if (doipcksum) { 1523283817Stuexen u_short sum = p_cksum(outip, (u_short*)outudp, protlen, 8); 1524283817Stuexen outudp->uh_sum = (sum) ? sum : 0xffff; 1525283817Stuexen } 1526283817Stuexen 1527283817Stuexen return; 1528283817Stuexen} 1529283817Stuexen 1530283817Stuexenint 1531283817Stuexenudplite_check(const u_char *data, int seq) 1532283817Stuexen{ 1533283817Stuexen struct udphdr *const udp = (struct udphdr *) data; 1534283817Stuexen 1535283817Stuexen return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) && 1536283817Stuexen ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq)); 1537283817Stuexen} 1538283817Stuexen 1539283817Stuexenvoid 154046542Sarchietcp_prep(struct outdata *outdata) 154146542Sarchie{ 1542100787Sfenner struct tcphdr *const tcp = (struct tcphdr *) outp; 154346542Sarchie 154446542Sarchie tcp->th_sport = htons(ident); 1545158424Scjc tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq)); 1546234701Stuexen tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport; 154746542Sarchie tcp->th_ack = 0; 154846542Sarchie tcp->th_off = 5; 154946542Sarchie tcp->th_flags = TH_SYN; 1550100789Sfenner tcp->th_sum = 0; 1551100789Sfenner 1552283819Stuexen if (doipcksum) 1553283819Stuexen tcp->th_sum = p_cksum(outip, (u_short*)tcp, protlen, protlen); 155446542Sarchie} 155546542Sarchie 155646542Sarchieint 155746542Sarchietcp_check(const u_char *data, int seq) 155846542Sarchie{ 155946542Sarchie struct tcphdr *const tcp = (struct tcphdr *) data; 156046542Sarchie 156146542Sarchie return (ntohs(tcp->th_sport) == ident 1562234701Stuexen && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq) 1563234701Stuexen && tcp->th_seq == (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport)); 156446542Sarchie} 156546542Sarchie 156646542Sarchievoid 1567283808Stuexensctp_prep(struct outdata *outdata) 1568283808Stuexen{ 1569283808Stuexen struct sctphdr *const sctp = (struct sctphdr *) outp; 1570283808Stuexen struct sctp_chunkhdr *chk; 1571332237Stuexen struct sctp_init_chunk *init; 1572332237Stuexen struct sctp_paramhdr *param; 1573283808Stuexen 1574283808Stuexen sctp->src_port = htons(ident); 1575283808Stuexen sctp->dest_port = htons(port + (fixedPort ? 0 : outdata->seq)); 1576332237Stuexen if (protlen >= (int)(sizeof(struct sctphdr) + 1577332237Stuexen sizeof(struct sctp_init_chunk))) { 1578332237Stuexen sctp->v_tag = 0; 1579332237Stuexen } else { 1580332237Stuexen sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port; 1581332237Stuexen } 1582283808Stuexen sctp->checksum = htonl(0); 1583332237Stuexen if (protlen >= (int)(sizeof(struct sctphdr) + 1584332237Stuexen sizeof(struct sctp_init_chunk))) { 1585332237Stuexen /* 1586332237Stuexen * Send a packet containing an INIT chunk. This works 1587332237Stuexen * better in case of firewalls on the path, but 1588332237Stuexen * results in a probe packet containing at least 1589332237Stuexen * 32 bytes of payload. For shorter payloads, use 1590332237Stuexen * SHUTDOWN-ACK chunks. 1591332237Stuexen */ 1592332237Stuexen init = (struct sctp_init_chunk *)(sctp + 1); 1593332237Stuexen init->ch.chunk_type = SCTP_INITIATION; 1594332237Stuexen init->ch.chunk_flags = 0; 1595332237Stuexen init->ch.chunk_length = htons((u_int16_t)(protlen - 1596332237Stuexen sizeof(struct sctphdr))); 1597332237Stuexen init->init.initiate_tag = (sctp->src_port << 16) | 1598332237Stuexen sctp->dest_port; 1599332237Stuexen init->init.a_rwnd = htonl(1500); 1600332237Stuexen init->init.num_outbound_streams = htons(1); 1601332237Stuexen init->init.num_inbound_streams = htons(1); 1602332237Stuexen init->init.initial_tsn = htonl(0); 1603332237Stuexen if (protlen >= (int)(sizeof(struct sctphdr) + 1604332237Stuexen sizeof(struct sctp_init_chunk) + 1605332237Stuexen sizeof(struct sctp_paramhdr))) { 1606332237Stuexen param = (struct sctp_paramhdr *)(init + 1); 1607332237Stuexen param->param_type = htons(SCTP_PAD); 1608332237Stuexen param->param_length = 1609332237Stuexen htons((u_int16_t)(protlen - 1610332237Stuexen sizeof(struct sctphdr) - 1611332237Stuexen sizeof(struct sctp_init_chunk))); 1612332237Stuexen } 1613332237Stuexen } else { 1614332237Stuexen /* 1615332237Stuexen * Send a packet containing a SHUTDOWN-ACK chunk, 1616332237Stuexen * possibly followed by a PAD chunk. 1617332237Stuexen */ 1618332237Stuexen if (protlen >= 1619332237Stuexen (int)(sizeof(struct sctphdr) + 1620332237Stuexen sizeof(struct sctp_chunkhdr))) { 1621332237Stuexen chk = (struct sctp_chunkhdr *)(sctp + 1); 1622332237Stuexen chk->chunk_type = SCTP_SHUTDOWN_ACK; 1623332237Stuexen chk->chunk_flags = 0; 1624332237Stuexen chk->chunk_length = htons(4); 1625332237Stuexen } 1626332237Stuexen if (protlen >= 1627332237Stuexen (int)(sizeof(struct sctphdr) + 1628332237Stuexen 2 * sizeof(struct sctp_chunkhdr))) { 1629332237Stuexen chk = chk + 1; 1630332237Stuexen chk->chunk_type = SCTP_PAD_CHUNK; 1631332237Stuexen chk->chunk_flags = 0; 1632332237Stuexen chk->chunk_length = htons(protlen - 1633332237Stuexen (sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))); 1634332237Stuexen } 1635283808Stuexen } 1636283808Stuexen if (doipcksum) { 1637283808Stuexen sctp->checksum = sctp_crc32c(sctp, protlen); 1638283808Stuexen } 1639283808Stuexen} 1640283808Stuexen 1641283808Stuexenint 1642283808Stuexensctp_check(const u_char *data, int seq) 1643283808Stuexen{ 1644283808Stuexen struct sctphdr *const sctp = (struct sctphdr *) data; 1645283808Stuexen 1646332237Stuexen if (ntohs(sctp->src_port) != ident || 1647332237Stuexen ntohs(sctp->dest_port) != port + (fixedPort ? 0 : seq)) 1648332237Stuexen return (0); 1649332237Stuexen if (protlen < (int)(sizeof(struct sctphdr) + 1650332237Stuexen sizeof(struct sctp_init_chunk))) { 1651332237Stuexen return (sctp->v_tag == 1652332237Stuexen (u_int32_t)((sctp->src_port << 16) | sctp->dest_port)); 1653332237Stuexen } else { 1654332237Stuexen /* 1655332237Stuexen * Don't verify the initiate_tag, since it is not available, 1656332237Stuexen * most of the time. 1657332237Stuexen */ 1658332237Stuexen return (sctp->v_tag == 0); 1659332237Stuexen } 1660283808Stuexen} 1661283808Stuexen 1662283808Stuexenvoid 166346542Sarchiegre_prep(struct outdata *outdata) 166446542Sarchie{ 1665100787Sfenner struct grehdr *const gre = (struct grehdr *) outp; 166646542Sarchie 166746542Sarchie gre->flags = htons(0x2001); 166846542Sarchie gre->proto = htons(port); 166946542Sarchie gre->length = 0; 167046542Sarchie gre->callId = htons(ident + outdata->seq); 167146542Sarchie} 167246542Sarchie 167346542Sarchieint 167446542Sarchiegre_check(const u_char *data, int seq) 167546542Sarchie{ 167646542Sarchie struct grehdr *const gre = (struct grehdr *) data; 167746542Sarchie 167846542Sarchie return(ntohs(gre->proto) == port 167946542Sarchie && ntohs(gre->callId) == ident + seq); 168046542Sarchie} 168146542Sarchie 168246542Sarchievoid 168346542Sarchiegen_prep(struct outdata *outdata) 168446542Sarchie{ 1685100787Sfenner u_int16_t *const ptr = (u_int16_t *) outp; 168646542Sarchie 168746542Sarchie ptr[0] = htons(ident); 168846542Sarchie ptr[1] = htons(port + outdata->seq); 168946542Sarchie} 169046542Sarchie 169146542Sarchieint 169246542Sarchiegen_check(const u_char *data, int seq) 169346542Sarchie{ 169446542Sarchie u_int16_t *const ptr = (u_int16_t *) data; 169546542Sarchie 169646542Sarchie return(ntohs(ptr[0]) == ident 169746542Sarchie && ntohs(ptr[1]) == port + seq); 169846542Sarchie} 169946542Sarchie 170046542Sarchievoid 170118579Sfennerprint(register u_char *buf, register int cc, register struct sockaddr_in *from) 170218579Sfenner{ 170318579Sfenner register struct ip *ip; 170418579Sfenner register int hlen; 1705196475Sume char addr[INET_ADDRSTRLEN]; 170618579Sfenner 170718579Sfenner ip = (struct ip *) buf; 170818579Sfenner hlen = ip->ip_hl << 2; 170918579Sfenner cc -= hlen; 171018579Sfenner 1711196475Sume strlcpy(addr, inet_ntoa(from->sin_addr), sizeof(addr)); 1712196475Sume 1713176428Srpaulo if (as_path) 1714196475Sume Printf(" [AS%u]", as_lookup(asn, addr, AF_INET)); 1715176428Srpaulo 171618579Sfenner if (nflag) 1717196475Sume Printf(" %s", addr); 171818579Sfenner else 1719196475Sume Printf(" %s (%s)", inetname(from->sin_addr), addr); 172018579Sfenner 172118579Sfenner if (verbose) 172218579Sfenner Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); 172318579Sfenner} 172418579Sfenner 172518579Sfenner/* 1726100789Sfenner * Checksum routine for UDP and TCP headers. 1727100789Sfenner */ 1728283784Stuexenu_short 1729283817Stuexenp_cksum(struct ip *ip, u_short *data, int len, int cov) 1730100789Sfenner{ 1731100789Sfenner static struct ipovly ipo; 1732216184Suqs u_short sum[2]; 1733100789Sfenner 1734100789Sfenner ipo.ih_pr = ip->ip_p; 1735100789Sfenner ipo.ih_len = htons(len); 1736100789Sfenner ipo.ih_src = ip->ip_src; 1737100789Sfenner ipo.ih_dst = ip->ip_dst; 1738100789Sfenner 1739216184Suqs sum[1] = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */ 1740283817Stuexen sum[0] = in_cksum(data, cov); /* payload data cksum */ 1741100789Sfenner 1742216184Suqs return ~in_cksum(sum, sizeof(sum)); 1743100789Sfenner} 1744100789Sfenner 1745100789Sfenner/* 174618579Sfenner * Checksum routine for Internet Protocol family headers (C Version) 174718579Sfenner */ 1748100535Sfenneru_short 174918579Sfennerin_cksum(register u_short *addr, register int len) 175018579Sfenner{ 175118579Sfenner register int nleft = len; 175218579Sfenner register u_short *w = addr; 175318579Sfenner register u_short answer; 175418579Sfenner register int sum = 0; 175518579Sfenner 175618579Sfenner /* 175718579Sfenner * Our algorithm is simple, using a 32 bit accumulator (sum), 175818579Sfenner * we add sequential 16 bit words to it, and at the end, fold 175918579Sfenner * back all the carry bits from the top 16 bits into the lower 176018579Sfenner * 16 bits. 176118579Sfenner */ 176218579Sfenner while (nleft > 1) { 176318579Sfenner sum += *w++; 176418579Sfenner nleft -= 2; 176518579Sfenner } 176618579Sfenner 176718579Sfenner /* mop up an odd byte, if necessary */ 176818579Sfenner if (nleft == 1) 176918579Sfenner sum += *(u_char *)w; 177018579Sfenner 177118579Sfenner /* 177218579Sfenner * add back carry outs from top 16 bits to low 16 bits 177318579Sfenner */ 177418579Sfenner sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 177518579Sfenner sum += (sum >> 16); /* add carry */ 177618579Sfenner answer = ~sum; /* truncate to 16 bits */ 177718579Sfenner return (answer); 177818579Sfenner} 177918579Sfenner 178018579Sfenner/* 1781283808Stuexen * CRC32C routine for the Stream Control Transmission Protocol 1782283808Stuexen */ 1783283808Stuexen 1784283808Stuexen#define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF]) 1785283808Stuexen 1786283808Stuexenstatic u_int32_t crc_c[256] = { 1787283808Stuexen 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 1788283808Stuexen 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 1789283808Stuexen 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 1790283808Stuexen 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 1791283808Stuexen 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 1792283808Stuexen 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 1793283808Stuexen 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 1794283808Stuexen 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 1795283808Stuexen 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 1796283808Stuexen 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 1797283808Stuexen 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 1798283808Stuexen 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 1799283808Stuexen 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 1800283808Stuexen 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 1801283808Stuexen 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 1802283808Stuexen 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 1803283808Stuexen 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 1804283808Stuexen 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 1805283808Stuexen 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 1806283808Stuexen 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 1807283808Stuexen 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 1808283808Stuexen 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 1809283808Stuexen 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 1810283808Stuexen 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 1811283808Stuexen 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 1812283808Stuexen 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 1813283808Stuexen 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 1814283808Stuexen 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 1815283808Stuexen 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 1816283808Stuexen 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 1817283808Stuexen 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 1818283808Stuexen 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 1819283808Stuexen 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 1820283808Stuexen 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 1821283808Stuexen 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 1822283808Stuexen 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 1823283808Stuexen 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 1824283808Stuexen 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 1825283808Stuexen 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 1826283808Stuexen 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 1827283808Stuexen 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 1828283808Stuexen 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 1829283808Stuexen 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 1830283808Stuexen 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 1831283808Stuexen 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 1832283808Stuexen 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 1833283808Stuexen 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 1834283808Stuexen 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 1835283808Stuexen 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 1836283808Stuexen 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 1837283808Stuexen 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 1838283808Stuexen 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 1839283808Stuexen 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 1840283808Stuexen 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 1841283808Stuexen 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 1842283808Stuexen 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 1843283808Stuexen 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 1844283808Stuexen 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 1845283808Stuexen 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 1846283808Stuexen 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 1847283808Stuexen 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 1848283808Stuexen 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 1849283808Stuexen 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 1850283808Stuexen 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 1851283808Stuexen}; 1852283808Stuexen 1853283808Stuexenu_int32_t 1854283808Stuexensctp_crc32c(const void *packet, u_int32_t len) 1855283808Stuexen{ 1856283808Stuexen u_int32_t i, crc32c; 1857283808Stuexen u_int8_t byte0, byte1, byte2, byte3; 1858283808Stuexen const u_int8_t *buf = (const u_int8_t *)packet; 1859283808Stuexen 1860283808Stuexen crc32c = ~0; 1861283808Stuexen for (i = 0; i < len; i++) 1862283808Stuexen CRC32C(crc32c, buf[i]); 1863283808Stuexen crc32c = ~crc32c; 1864283808Stuexen byte0 = crc32c & 0xff; 1865283808Stuexen byte1 = (crc32c>>8) & 0xff; 1866283808Stuexen byte2 = (crc32c>>16) & 0xff; 1867283808Stuexen byte3 = (crc32c>>24) & 0xff; 1868283808Stuexen crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); 1869283808Stuexen return htonl(crc32c); 1870283808Stuexen} 1871283808Stuexen 1872283808Stuexen/* 187318579Sfenner * Subtract 2 timeval structs: out = out - in. 187444086Sdes * Out is assumed to be within about LONG_MAX seconds of in. 187518579Sfenner */ 187618579Sfennervoid 187718579Sfennertvsub(register struct timeval *out, register struct timeval *in) 187818579Sfenner{ 187918579Sfenner 188018579Sfenner if ((out->tv_usec -= in->tv_usec) < 0) { 188118579Sfenner --out->tv_sec; 188218579Sfenner out->tv_usec += 1000000; 188318579Sfenner } 188418579Sfenner out->tv_sec -= in->tv_sec; 188518579Sfenner} 188618579Sfenner 188718579Sfenner/* 188818579Sfenner * Construct an Internet address representation. 188918579Sfenner * If the nflag has been supplied, give 189018579Sfenner * numeric value, otherwise try for symbolic name. 189118579Sfenner */ 189218579Sfennerchar * 189318579Sfennerinetname(struct in_addr in) 189418579Sfenner{ 189518579Sfenner register char *cp; 189618579Sfenner register struct hostent *hp; 189718579Sfenner static int first = 1; 189818579Sfenner static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1]; 189918579Sfenner 190018579Sfenner if (first && !nflag) { 190118579Sfenner first = 0; 1902100787Sfenner if (gethostname(domain, sizeof(domain) - 1) < 0) 190318579Sfenner domain[0] = '\0'; 1904100787Sfenner else { 1905100787Sfenner cp = strchr(domain, '.'); 1906100787Sfenner if (cp == NULL) { 1907338475Soshogbo#ifdef HAVE_LIBCASPER 1908338475Soshogbo if (capdns != NULL) 1909338475Soshogbo hp = cap_gethostbyname(capdns, domain); 1910338475Soshogbo else 1911338475Soshogbo#endif 1912338475Soshogbo hp = gethostbyname(domain); 1913100787Sfenner if (hp != NULL) 1914100787Sfenner cp = strchr(hp->h_name, '.'); 1915100787Sfenner } 1916100787Sfenner if (cp == NULL) 1917100787Sfenner domain[0] = '\0'; 1918100787Sfenner else { 1919100787Sfenner ++cp; 1920100787Sfenner (void)strncpy(domain, cp, sizeof(domain) - 1); 1921100787Sfenner domain[sizeof(domain) - 1] = '\0'; 1922100787Sfenner } 1923100787Sfenner } 192418579Sfenner } 192518579Sfenner if (!nflag && in.s_addr != INADDR_ANY) { 1926338475Soshogbo#ifdef HAVE_LIBCASPER 1927338475Soshogbo if (capdns != NULL) 1928338475Soshogbo hp = cap_gethostbyaddr(capdns, (char *)&in, sizeof(in), 1929338475Soshogbo AF_INET); 1930338475Soshogbo else 1931338475Soshogbo#endif 1932338475Soshogbo hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); 193318579Sfenner if (hp != NULL) { 193418579Sfenner if ((cp = strchr(hp->h_name, '.')) != NULL && 193518579Sfenner strcmp(cp + 1, domain) == 0) 193618579Sfenner *cp = '\0'; 193718579Sfenner (void)strncpy(line, hp->h_name, sizeof(line) - 1); 193818579Sfenner line[sizeof(line) - 1] = '\0'; 193918579Sfenner return (line); 194018579Sfenner } 194118579Sfenner } 194218579Sfenner return (inet_ntoa(in)); 194318579Sfenner} 194418579Sfenner 1945100787Sfennerstruct hostinfo * 1946100787Sfennergethostinfo(register char *hostname) 194718579Sfenner{ 1948100787Sfenner register int n; 194918579Sfenner register struct hostent *hp; 1950100787Sfenner register struct hostinfo *hi; 1951100787Sfenner register char **p; 1952100787Sfenner register u_int32_t addr, *ap; 195318579Sfenner 1954223579Sdim if (strlen(hostname) >= MAXHOSTNAMELEN) { 1955100787Sfenner Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n", 1956100787Sfenner prog, hostname); 1957100787Sfenner exit(1); 1958100787Sfenner } 1959100787Sfenner hi = calloc(1, sizeof(*hi)); 1960100787Sfenner if (hi == NULL) { 1961100787Sfenner Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno)); 1962100787Sfenner exit(1); 1963100787Sfenner } 1964100787Sfenner addr = inet_addr(hostname); 1965100787Sfenner if ((int32_t)addr != -1) { 1966100787Sfenner hi->name = strdup(hostname); 1967100787Sfenner hi->n = 1; 1968100787Sfenner hi->addrs = calloc(1, sizeof(hi->addrs[0])); 1969100787Sfenner if (hi->addrs == NULL) { 1970100787Sfenner Fprintf(stderr, "%s: calloc %s\n", 1971100787Sfenner prog, strerror(errno)); 1972100787Sfenner exit(1); 1973100787Sfenner } 1974100787Sfenner hi->addrs[0] = addr; 1975100787Sfenner return (hi); 1976100787Sfenner } 197718579Sfenner 1978338475Soshogbo#ifdef HAVE_LIBCASPER 1979338475Soshogbo if (capdns != NULL) 1980338475Soshogbo hp = cap_gethostbyname(capdns, hostname); 1981338475Soshogbo else 1982338475Soshogbo#endif 1983338475Soshogbo hp = gethostbyname(hostname); 198418579Sfenner if (hp == NULL) { 198518579Sfenner Fprintf(stderr, "%s: unknown host %s\n", prog, hostname); 198618579Sfenner exit(1); 198718579Sfenner } 198818579Sfenner if (hp->h_addrtype != AF_INET || hp->h_length != 4) { 198918579Sfenner Fprintf(stderr, "%s: bad host %s\n", prog, hostname); 199018579Sfenner exit(1); 199118579Sfenner } 1992100787Sfenner hi->name = strdup(hp->h_name); 1993100787Sfenner for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p) 1994100787Sfenner continue; 1995100787Sfenner hi->n = n; 1996100787Sfenner hi->addrs = calloc(n, sizeof(hi->addrs[0])); 1997100787Sfenner if (hi->addrs == NULL) { 1998100787Sfenner Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno)); 1999100787Sfenner exit(1); 2000100787Sfenner } 2001100787Sfenner for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p) 2002100787Sfenner memcpy(ap, *p, sizeof(*ap)); 2003100787Sfenner return (hi); 200418579Sfenner} 200518579Sfenner 2006100787Sfennervoid 2007100787Sfennerfreehostinfo(register struct hostinfo *hi) 200818579Sfenner{ 2009100787Sfenner if (hi->name != NULL) { 2010100787Sfenner free(hi->name); 2011100787Sfenner hi->name = NULL; 2012100787Sfenner } 2013100787Sfenner free((char *)hi->addrs); 2014100787Sfenner free((char *)hi); 2015100787Sfenner} 201618579Sfenner 2017100787Sfennervoid 2018100787Sfennergetaddr(register u_int32_t *ap, register char *hostname) 2019100787Sfenner{ 2020100787Sfenner register struct hostinfo *hi; 2021100787Sfenner 2022100787Sfenner hi = gethostinfo(hostname); 2023100787Sfenner *ap = hi->addrs[0]; 2024100787Sfenner freehostinfo(hi); 2025100787Sfenner} 2026100787Sfenner 2027100787Sfennervoid 2028100787Sfennersetsin(register struct sockaddr_in *sin, register u_int32_t addr) 2029100787Sfenner{ 2030100787Sfenner 203118579Sfenner memset(sin, 0, sizeof(*sin)); 2032100787Sfenner#ifdef HAVE_SOCKADDR_SA_LEN 2033100787Sfenner sin->sin_len = sizeof(*sin); 2034100787Sfenner#endif 203518579Sfenner sin->sin_family = AF_INET; 2036100787Sfenner sin->sin_addr.s_addr = addr; 203718579Sfenner} 203818579Sfenner 2039100787Sfenner/* String to value with optional min and max. Handles decimal and hex. */ 2040100787Sfennerint 2041100787Sfennerstr2val(register const char *str, register const char *what, 2042100787Sfenner register int mi, register int ma) 204318579Sfenner{ 2044100787Sfenner register const char *cp; 2045100787Sfenner register int val; 2046100787Sfenner char *ep; 204718579Sfenner 2048100787Sfenner if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { 2049100787Sfenner cp = str + 2; 2050100787Sfenner val = (int)strtol(cp, &ep, 16); 2051100787Sfenner } else 2052100787Sfenner val = (int)strtol(str, &ep, 10); 2053100787Sfenner if (*ep != '\0') { 2054100787Sfenner Fprintf(stderr, "%s: \"%s\" bad value for %s \n", 2055100787Sfenner prog, str, what); 205618579Sfenner exit(1); 205718579Sfenner } 2058100787Sfenner if (val < mi && mi >= 0) { 2059100787Sfenner if (mi == 0) 2060100787Sfenner Fprintf(stderr, "%s: %s must be >= %d\n", 2061100787Sfenner prog, what, mi); 2062100787Sfenner else 2063100787Sfenner Fprintf(stderr, "%s: %s must be > %d\n", 2064100787Sfenner prog, what, mi - 1); 2065100787Sfenner exit(1); 2066100787Sfenner } 2067100787Sfenner if (val > ma && ma >= 0) { 2068100787Sfenner Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma); 2069100787Sfenner exit(1); 2070100787Sfenner } 2071100787Sfenner return (val); 207218579Sfenner} 207318579Sfenner 2074100787Sfennerstruct outproto * 2075100787Sfennersetproto(char *pname) 2076100787Sfenner{ 2077100787Sfenner struct outproto *proto; 2078100787Sfenner int i; 2079100787Sfenner 2080100787Sfenner for (i = 0; protos[i].name != NULL; i++) { 2081100787Sfenner if (strcasecmp(protos[i].name, pname) == 0) { 2082100787Sfenner break; 2083100787Sfenner } 2084100787Sfenner } 2085100787Sfenner proto = &protos[i]; 2086100787Sfenner if (proto->name == NULL) { /* generic handler */ 2087100787Sfenner struct protoent *pe; 2088100787Sfenner u_long pnum; 2089100787Sfenner 2090100787Sfenner /* Determine the IP protocol number */ 2091100787Sfenner if ((pe = getprotobyname(pname)) != NULL) 2092100787Sfenner pnum = pe->p_proto; 2093100787Sfenner else 2094100787Sfenner pnum = str2val(optarg, "proto number", 1, 255); 2095100787Sfenner proto->num = pnum; 2096100787Sfenner } 2097100787Sfenner return proto; 2098100787Sfenner} 2099100787Sfenner 210067682Sobrienvoid 2101163387Sdwmalonepkt_compare(const u_char *a, int la, const u_char *b, int lb) { 2102163387Sdwmalone int l; 2103163387Sdwmalone int i; 2104163387Sdwmalone 2105163387Sdwmalone for (i = 0; i < la; i++) 2106163387Sdwmalone Printf("%02x", (unsigned int)a[i]); 2107163387Sdwmalone Printf("\n"); 2108163387Sdwmalone l = (la <= lb) ? la : lb; 2109163387Sdwmalone for (i = 0; i < l; i++) 2110163387Sdwmalone if (a[i] == b[i]) 2111163387Sdwmalone Printf("__"); 2112163387Sdwmalone else 2113163387Sdwmalone Printf("%02x", (unsigned int)b[i]); 2114163387Sdwmalone for (; i < lb; i++) 2115163387Sdwmalone Printf("%02x", (unsigned int)b[i]); 2116163387Sdwmalone Printf("\n"); 2117163387Sdwmalone} 2118163387Sdwmalone 2119163387Sdwmalone 2120163387Sdwmalonevoid 212118579Sfennerusage(void) 212218579Sfenner{ 212318579Sfenner extern char version[]; 212418579Sfenner 212518579Sfenner Fprintf(stderr, "Version %s\n", version); 2126100787Sfenner Fprintf(stderr, 2127176428Srpaulo "Usage: %s [-adDeFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n" 2128100787Sfenner "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n" 2129176428Srpaulo "\t[-t tos] [-w waittime] [-A as_server] [-z pausemsecs] host [packetlen]\n", prog); 213018579Sfenner exit(1); 213118579Sfenner} 2132