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