From 72c5c8bcbdaf350e984abbb81390617a1e93426a Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Mon, 3 Jun 2013 10:54:08 +0000 Subject: [PATCH] netbsd ping & traceroute . remove minix ping . add support for socket(AF_INET, SOCK_RAW, {IPPROTO_ICMP,IPPROTO_UDP}) Change-Id: I124fa15efb967c1989aae457cafb973f072c76eb --- distrib/sets/lists/minix/mi | 12 +- minix/commands/Makefile | 2 +- minix/commands/ping/Makefile | 5 - minix/commands/ping/ping.c | 150 -- minix/include/net/gen/inet.h | 2 - minix/lib/libc/sys/recvfrom.c | 34 + minix/lib/libc/sys/sendto.c | 22 + minix/lib/libc/sys/socket.c | 63 + minix/man/man1/Makefile | 2 +- minix/man/man1/ping.1 | 31 - sbin/Makefile | 2 +- sbin/ping/Makefile | 22 + sbin/ping/ping.8 | 478 ++++++ sbin/ping/ping.c | 1923 ++++++++++++++++++++++ sbin/ping/ping_hostops.c | 53 + sbin/ping/ping_rumpops.c | 58 + sbin/ping/prog_ops.h | 79 + sys/net/Makefile | 2 + sys/netinet/Makefile | 4 +- sys/netinet/ip_icmp.h | 253 +++ usr.sbin/Makefile | 2 +- usr.sbin/traceroute/CHANGES | 149 ++ usr.sbin/traceroute/Makefile | 29 + usr.sbin/traceroute/as.c | 224 +++ usr.sbin/traceroute/as.h | 34 + usr.sbin/traceroute/gnuc.h | 36 + usr.sbin/traceroute/ifaddrlist.c | 146 ++ usr.sbin/traceroute/ifaddrlist.h | 31 + usr.sbin/traceroute/mean.awk | 14 + usr.sbin/traceroute/median.awk | 31 + usr.sbin/traceroute/prog_ops.h | 72 + usr.sbin/traceroute/traceroute | Bin 0 -> 382374 bytes usr.sbin/traceroute/traceroute.8 | 419 +++++ usr.sbin/traceroute/traceroute.c | 1905 +++++++++++++++++++++ usr.sbin/traceroute/traceroute_hostops.c | 55 + usr.sbin/traceroute/traceroute_rumpops.c | 59 + usr.sbin/traceroute/trrt2netbsd | 272 +++ usr.sbin/traceroute/version.c | 2 + 38 files changed, 6482 insertions(+), 195 deletions(-) delete mode 100644 minix/commands/ping/Makefile delete mode 100644 minix/commands/ping/ping.c delete mode 100644 minix/man/man1/ping.1 create mode 100644 sbin/ping/Makefile create mode 100644 sbin/ping/ping.8 create mode 100644 sbin/ping/ping.c create mode 100644 sbin/ping/ping_hostops.c create mode 100644 sbin/ping/ping_rumpops.c create mode 100644 sbin/ping/prog_ops.h create mode 100644 sys/netinet/ip_icmp.h create mode 100644 usr.sbin/traceroute/CHANGES create mode 100644 usr.sbin/traceroute/Makefile create mode 100644 usr.sbin/traceroute/as.c create mode 100644 usr.sbin/traceroute/as.h create mode 100644 usr.sbin/traceroute/gnuc.h create mode 100644 usr.sbin/traceroute/ifaddrlist.c create mode 100644 usr.sbin/traceroute/ifaddrlist.h create mode 100644 usr.sbin/traceroute/mean.awk create mode 100644 usr.sbin/traceroute/median.awk create mode 100644 usr.sbin/traceroute/prog_ops.h create mode 100755 usr.sbin/traceroute/traceroute create mode 100644 usr.sbin/traceroute/traceroute.8 create mode 100644 usr.sbin/traceroute/traceroute.c create mode 100644 usr.sbin/traceroute/traceroute_hostops.c create mode 100644 usr.sbin/traceroute/traceroute_rumpops.c create mode 100755 usr.sbin/traceroute/trrt2netbsd create mode 100644 usr.sbin/traceroute/version.c diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index 7f3b8e262..7721b7459 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -144,6 +144,7 @@ ./sbin/mknod minix-sys ./sbin/newfs_ext2fs minix-sys ./sbin/nologin minix-sys +./sbin/ping minix-sys ./sbin/poweroff minix-sys ./sbin/reboot minix-sys ./sbin/shutdown minix-sys @@ -435,7 +436,6 @@ ./usr/bin/paste minix-sys ./usr/bin/patch minix-sys ./usr/bin/pathchk minix-sys -./usr/bin/ping minix-sys ./usr/bin/pkgin_all minix-sys ./usr/bin/pkgin_cd minix-sys ./usr/bin/playwave minix-sys @@ -1440,6 +1440,8 @@ ./usr/include/net/if_ether.h minix-sys ./usr/include/net/if.h minix-sys ./usr/include/net/netlib.h minix-sys +./usr/include/net/radix.h minix-sys +./usr/include/net/route.h minix-sys ./usr/include/netconfig.h minix-sys ./usr/include/netdb.h minix-sys ./usr/include/netgroup.h minix-sys @@ -1447,7 +1449,11 @@ ./usr/include/netinet/in.h minix-sys ./usr/include/netinet/in_systm.h minix-sys ./usr/include/netinet/ip.h minix-sys +./usr/include/netinet/ip_icmp.h minix-sys +./usr/include/netinet/ip_var.h minix-sys ./usr/include/netinet/tcp.h minix-sys +./usr/include/netinet/udp.h minix-sys +./usr/include/netinet/udp_var.h minix-sys ./usr/include/netinet6 minix-sys ./usr/include/netinet6/in6.h minix-sys ./usr/include/nlist.h minix-sys @@ -2428,7 +2434,6 @@ ./usr/man/man1/patch.1 minix-sys ./usr/man/man1/pathchk.1 minix-sys ./usr/man/man1/pax.1 minix-sys -./usr/man/man1/ping.1 minix-sys ./usr/man/man1/pkg_view.1 minix-sys ./usr/man/man1/playwave.1 minix-sys ./usr/man/man1/pr.1 minix-sys @@ -5082,6 +5087,7 @@ ./usr/man/man8/ossdevlinks.8 minix-sys ./usr/man/man8/part.8 minix-sys ./usr/man/man8/partition.8 minix-sys +./usr/man/man8/ping.8 minix-sys ./usr/man/man8/postinstall.8 minix-sys ./usr/man/man8/poweroff.8 minix-sys ./usr/man/man8/printroot.8 minix-sys @@ -5106,6 +5112,7 @@ ./usr/man/man8/sync.8 minix-sys ./usr/man/man8/syslogd.8 minix-sys ./usr/man/man8/tcpd.8 minix-sys +./usr/man/man8/traceroute.8 minix-sys ./usr/man/man8/unix.8 minix-sys ./usr/man/man8/unlink.8 minix-sys ./usr/man/man8/unstr.8 minix-sys @@ -5155,6 +5162,7 @@ ./usr/sbin/postinstall minix-sys ./usr/sbin/pwd_mkdb minix-sys ./usr/sbin/rdate minix-sys +./usr/sbin/traceroute minix-sys ./usr/sbin/unlink minix-sys ./usr/sbin/user minix-sys ./usr/sbin/useradd minix-sys diff --git a/minix/commands/Makefile b/minix/commands/Makefile index 83a732241..78ec31920 100644 --- a/minix/commands/Makefile +++ b/minix/commands/Makefile @@ -18,7 +18,7 @@ SUBDIR= add_route arp ash at backup btrace \ mined \ mount mt netconf \ nonamed \ - ping postinstall prep printroot \ + postinstall prep printroot \ profile progressbar pr_routes ps pwdauth \ ramdisk rarpd rawspeed rcp readclock \ remsync rget rlogin \ diff --git a/minix/commands/ping/Makefile b/minix/commands/ping/Makefile deleted file mode 100644 index 9fb8d1f47..000000000 --- a/minix/commands/ping/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -PROG= ping -BINMODE= 4755 -MAN= - -.include diff --git a/minix/commands/ping/ping.c b/minix/commands/ping/ping.c deleted file mode 100644 index de6c66c00..000000000 --- a/minix/commands/ping/ping.c +++ /dev/null @@ -1,150 +0,0 @@ -/* -ping.c -*/ - -#define DEBUG 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WRITE_SIZE 30 -char buffer[16*1024]; - -int main(int argc, char *argv[]); - -#if DEBUG -#define where() fprintf(stderr, "%s %d:", __FILE__, __LINE__); -#endif - -#if __STDC__ -#define PROTO(x,y) x y -#else -#define PROTO(x,y) X () -#endif - -PROTO (int main, (int argc, char *argv[]) ); -static PROTO (void sig_hand, (int signal) ); - -main(argc, argv) -int argc; -char *argv[]; -{ - int fd, i; - int result, result1; - nwio_ipopt_t ipopt; - ip_hdr_t *ip_hdr; - int ihl; - icmp_hdr_t *icmp_hdr; - ipaddr_t dst_addr; - struct hostent *hostent; - int length; - - if (argc<2 || argc>3) - { - fprintf(stderr, "Usage: %s hostname [length]\n", argv[0]); - exit(1); - } - hostent= gethostbyname(argv[1]); - if (!hostent) - { - dst_addr= inet_addr(argv[1]); - if (dst_addr == -1) - { - fprintf(stderr, "%s: unknown host (%s)\n", - argv[0], argv[1]); - exit(1); - } - } - else - dst_addr= *(ipaddr_t *)(hostent->h_addr); - if (argc == 3) - { - length= strtol (argv[2], (char **)0, 0); - if (length< sizeof(icmp_hdr_t) + IP_MIN_HDR_SIZE) - { - fprintf(stderr, "%s: length too small (%s)\n", - argv[0], argv[2]); - exit(1); - } - } - else - length= WRITE_SIZE; - - fd= open ("/dev/ip", O_RDWR); - if (fd<0) - perror("open"), exit(1); - - ipopt.nwio_flags= NWIO_COPY | NWIO_PROTOSPEC; - ipopt.nwio_proto= 1; - - result= ioctl (fd, NWIOSIPOPT, &ipopt); - if (result<0) - perror("ioctl (NWIOSIPOPT)"), exit(1); - - result= ioctl (fd, NWIOGIPOPT, &ipopt); - if (result<0) - perror("ioctl (NWIOGIPOPT)"), exit(1); - - for (i= 0; i< 20; i++) - { - ip_hdr= (ip_hdr_t *)buffer; - ip_hdr->ih_dst= dst_addr; - - icmp_hdr= (icmp_hdr_t *)(buffer+20); - icmp_hdr->ih_type= 8; - icmp_hdr->ih_code= 0; - icmp_hdr->ih_chksum= 0; - icmp_hdr->ih_chksum= ~oneC_sum(0, (u16_t *)icmp_hdr, - WRITE_SIZE-20); - result= write(fd, buffer, length); - if (result<0) - { - perror("write"); - exit(1); - } - if (result != length) - { - where(); - fprintf(stderr, "result= %d\n", result); - exit(1); - } - - alarm(0); - signal (SIGALRM, sig_hand); - alarm(1); - - result= read(fd, buffer, sizeof(buffer)); - if (result>= 0 || errno != EINTR) - break; - } - if (i >= 20) - { - printf("no answer from %s\n", argv[1]); - exit(1); - } - if (result<0) - { - perror ("read"); - exit(1); - } - printf("%s is alive\n", argv[1]); - exit(0); -} - -static void sig_hand(signal) -int signal; -{ -} diff --git a/minix/include/net/gen/inet.h b/minix/include/net/gen/inet.h index 527ba6860..e70c5aa8f 100644 --- a/minix/include/net/gen/inet.h +++ b/minix/include/net/gen/inet.h @@ -9,7 +9,5 @@ server/ip/gen/inet.h ipaddr_t inet_addr( const char *addr ); ipaddr_t inet_network( const char *addr ); -char *inet_ntoa( ipaddr_t addr ); -int inet_aton( const char *cp, ipaddr_t *pin ); #endif /* __SERVER__IP__GEN__INET_H__ */ diff --git a/minix/lib/libc/sys/recvfrom.c b/minix/lib/libc/sys/recvfrom.c index 5f5a19b9e..01d3e48c9 100644 --- a/minix/lib/libc/sys/recvfrom.c +++ b/minix/lib/libc/sys/recvfrom.c @@ -20,6 +20,9 @@ #include #include +#include +#include + #define DEBUG 0 static ssize_t _tcp_recvfrom(int sock, void *__restrict buffer, size_t length, @@ -85,6 +88,37 @@ ssize_t recvfrom(int sock, void *__restrict buffer, size_t length, } } + { + ip_hdr_t *ip_hdr; + int ihl, rd; + icmp_hdr_t *icmp_hdr; + struct sockaddr_in sin; + + rd = read(sock, buffer, length); + + if(rd < 0) return rd; + + assert(rd >= sizeof(*ip_hdr)); + + ip_hdr= buffer; + + if (address != NULL) + { + int len; + memset(&sin, 0, sizeof(sin)); + sin.sin_family= AF_INET; + sin.sin_addr.s_addr= ip_hdr->ih_src; + sin.sin_len= sizeof(sin); + len= *address_len; + if (len > sizeof(sin)) + len= sizeof(sin); + memcpy(address, &sin, len); + *address_len= sizeof(sin); + } + + return rd; + } + #if DEBUG fprintf(stderr, "recvfrom: not implemented for fd %d\n", sock); #endif diff --git a/minix/lib/libc/sys/sendto.c b/minix/lib/libc/sys/sendto.c index 4f174bba2..f0d6a2811 100644 --- a/minix/lib/libc/sys/sendto.c +++ b/minix/lib/libc/sys/sendto.c @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include #include @@ -76,6 +78,26 @@ ssize_t sendto(int sock, const void *message, size_t length, int flags, } } + { + ip_hdr_t *ip_hdr; + int ihl; + icmp_hdr_t *icmp_hdr; + struct sockaddr_in *sinp; + + sinp = (struct sockaddr_in *) __UNCONST(dest_addr); + if (sinp->sin_family != AF_INET) + { + errno= EAFNOSUPPORT; + return -1; + } + + /* raw */ + ip_hdr= (ip_hdr_t *)message; + ip_hdr->ih_dst= sinp->sin_addr.s_addr; + + return write(sock, message, length); + } + #if DEBUG fprintf(stderr, "sendto: not implemented for fd %d\n", sock); #endif diff --git a/minix/lib/libc/sys/socket.c b/minix/lib/libc/sys/socket.c index 9f1883847..f73828a01 100644 --- a/minix/lib/libc/sys/socket.c +++ b/minix/lib/libc/sys/socket.c @@ -11,7 +11,19 @@ __weak_alias(socket, __socket30) #include #include #include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -21,6 +33,7 @@ __weak_alias(socket, __socket30) static int _tcp_socket(int type, int protocol); static int _udp_socket(int type, int protocol); static int _uds_socket(int type, int protocol); +static int _raw_socket(int type, int protocol); static void _socket_flags(int type, int *result); int socket(int domain, int type, int protocol) @@ -53,6 +66,12 @@ int socket(int domain, int type, int protocol) if (domain == AF_INET && sock_type == SOCK_DGRAM) return _udp_socket(type, protocol); + if (domain == AF_INET && sock_type == SOCK_RAW && protocol == IPPROTO_ICMP) + return _raw_socket(type, protocol); + + if (domain == AF_INET && sock_type == SOCK_RAW && protocol == IPPROTO_UDP) + return _raw_socket(type, protocol); + #if DEBUG fprintf(stderr, "socket: nothing for domain %d, type %d, protocol %d\n", domain, type, protocol); @@ -127,6 +146,50 @@ static int _udp_socket(int type, int protocol) return fd; } +static int _raw_socket(int type, int protocol) +{ + int r, fd, t_errno, flags = O_RDWR; + struct sockaddr_in sin; + nwio_ipopt_t ipopt; + int result; + + if (protocol != IPPROTO_ICMP && protocol != IPPROTO_UDP && protocol != 0) + { +#if DEBUG + fprintf(stderr, "socket(icmp): bad protocol %d\n", protocol); +#endif + errno= EPROTONOSUPPORT; + return -1; + } + _socket_flags(type, &flags); + fd= open(IP_DEVICE, flags); + if (fd == -1) + return fd; + + memset(&ipopt, 0, sizeof(ipopt)); + + ipopt.nwio_flags= NWIO_COPY; + + if(protocol) { + ipopt.nwio_flags |= NWIO_PROTOSPEC; + ipopt.nwio_proto = protocol; + } + + result = ioctl (fd, NWIOSIPOPT, &ipopt); + if (result<0) { + close(fd); + return -1; + } + + result = ioctl (fd, NWIOGIPOPT, &ipopt); + if (result<0) { + close(fd); + return -1; + } + + return fd; +} + static int _uds_socket(int type, int protocol) { int fd, r, flags = O_RDWR, sock_type; diff --git a/minix/man/man1/Makefile b/minix/man/man1/Makefile index 9c6f46237..8f8b8e14c 100644 --- a/minix/man/man1/Makefile +++ b/minix/man/man1/Makefile @@ -11,7 +11,7 @@ MAN= ash.1 at.1 \ look.1 lp.1 lspci.1 mail.1 \ mixer.1 \ mkproto.1 mount.1 mt.1 \ - ping.1 playwave.1 prep.1 \ + playwave.1 prep.1 \ profile.1 ps.1 rcp.1 recwave.1 \ remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \ spell.1 svc.1 svrctl.1 \ diff --git a/minix/man/man1/ping.1 b/minix/man/man1/ping.1 deleted file mode 100644 index 7a85db2bf..000000000 --- a/minix/man/man1/ping.1 +++ /dev/null @@ -1,31 +0,0 @@ -.TH PING 1 -.SH NAME -ping \- send ICMP ECHO_REQUEST packets to network hosts -.SH SYNOPSIS -.B /usr/bin/ping hostname [length] -.de EX -.TP 20 -\\fB\$1\\fR -# \\$2 -.. -.SH EXAMPLES -.TP 20 -.B ping 192.168.1.1 -# Ping host 192.168.1.1 -.TP 20 -.B ping www.minix3.org 500 -# Ping www.minix3.org with 500 byte IP packets -.SH DESCRIPTION -.PP -Sends ICMP ECHO_REQUEST packets to the specified host and waits for a ECHO_REPLY. -Optionally, the length (size) of the IP packet can be specified. The default is -30 bytes. (Note, the 14 byte Ethernet header will make this a 44 byte packet.) -.SH OPTIONS -.IP length -Size (in bytes) of the transmitted ICMP packet. The default length of the IP -packet is 30 bytes. (Adding the ethernet header will result in a 44 byte -packet being transmitted.) -.SH "SEE ALSO" -ifconfig(8) -.SH AUTHOR -Leith Brandeland diff --git a/sbin/Makefile b/sbin/Makefile index ee3735542..ed2ae4306 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -10,9 +10,9 @@ SUBDIR= \ chown \ fsck init \ mknod nologin \ + ping \ reboot \ shutdown \ - # support for various file systems SUBDIR+= newfs_ext2fs fsck_ext2fs diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile new file mode 100644 index 000000000..466f7a918 --- /dev/null +++ b/sbin/ping/Makefile @@ -0,0 +1,22 @@ +# $NetBSD: Makefile,v 1.17 2013/11/09 21:39:27 christos Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +USE_FORT?= yes # setuid +RUMPPRG=ping +MAN= ping.8 +BINOWN= root +BINMODE=4555 +LDADD= -lm +DPADD= ${LIBM} + +# BJG - no ipsec +#CPPFLAGS+= -DIPSEC + +#LDADD+= -lipsec +#DPADD+= ${LIBIPSEC} + +.if ${MACHINE_ARCH} == "vax" +COPTS.ping.c=-O0 +.endif + +.include diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8 new file mode 100644 index 000000000..b74b740d9 --- /dev/null +++ b/sbin/ping/ping.8 @@ -0,0 +1,478 @@ +.\" $NetBSD: ping.8,v 1.50 2011/09/10 20:47:33 wiz Exp $ +.\" +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ping.8 8.2 (Berkeley) 12/11/93 +.\" +.Dd September 10, 2011 +.Dt PING 8 +.Os +.Sh NAME +.Nm ping +.Nd send +.Tn ICMP ECHO_REQUEST +packets to network hosts +.Sh SYNOPSIS +.Nm +.Op Fl aCDdfLnoPQqRrv +.Op Fl c Ar count +.Op Fl E Ar policy +.Op Fl g Ar gateway +.Op Fl h Ar host +.Op Fl I Ar srcaddr +.Op Fl i Ar interval +.Op Fl l Ar preload +.Op Fl p Ar pattern +.Op Fl s Ar packetsize +.Op Fl T Ar ttl +.Op Fl t Ar tos +.Op Fl w Ar deadline +.Ar host +.Sh DESCRIPTION +.Nm +uses the +.Tn ICMP +protocol's mandatory +.Tn ECHO_REQUEST +datagram to elicit an +.Tn ICMP ECHO_RESPONSE +from a host or gateway. +.Tn ECHO_REQUEST +datagrams (``pings'') have an IP and +.Tn ICMP +header, +followed by a +.Dq struct timespec +and then an arbitrary number of ``pad'' bytes used to fill out the +packet. +The options are as follows: +.Bl -tag -width Ds +.It Fl a +Emit an audible beep (by sending an ascii BEL character to the +standard error output) after each non-duplicate response is received. +This is disabled for flood pings as it would probably cause temporary +insanity. +.It Fl C +Send timestamps in compat format; two 32 bit words in little endian format, +the first one representing seconds, and the second one representing +microseconds. +.It Fl c Ar count +Stop after sending (and waiting the specified delay to receive) +.Ar count +.Tn ECHO_RESPONSE +packets. +.It Fl D +Set the +.Dv Don't Fragment +bit in the IP header. +This can be used to determine the path MTU. +.It Fl d +Set the +.Dv SO_DEBUG +option on the socket being used. +.It Fl E Ar policy +Use IPsec policy specification string +.Ar policy +for packets. +For the format of specification string, please refer +.Xr ipsec_set_policy 3 . +Please note that this option is same as +.Fl P +in KAME/FreeBSD and KAME/BSDI +(as +.Fl P +was already occupied in +.Nx ) . +.It Fl f +Flood ping. +Outputs packets as fast as they come back or one hundred times per second, +whichever is more. +For every +.Tn ECHO_REQUEST +sent a period ``.'' is printed, while for every +.Tn ECHO_REPLY +received a backspace is printed. +This provides a rapid display of how many packets are being dropped. +Only the super-user may use this option. +.Bf -emphasis +This can be very hard on a network and should be used with caution. +.Ef +.It Fl g Ar gateway +Use Loose Source Routing to send the ECHO_REQUEST packets via +.Ar gateway . +.It Fl h Ar host +is an alternate way of specifying the target host instead of as the +last argument. +.It Fl I Ar srcaddr +Set the source IP address to +.Ar srcaddr +which can be a hostname or an IP number. +For multicast datagrams, it also specifies the outgoing interface. +.It Fl i Ar interval +Wait +.Ar interval +seconds +.Em between sending each packet . +The default is to wait for one second between each packet, +except when the -f option is used the wait interval is 0.01 seconds. +.It Fl L +Disable loopback when sending to multicast destinations, +so the transmitting host doesn't see the ICMP requests. +.It Fl l Ar preload +If +.Ar preload +is specified, +.Nm +sends that many packets as fast as possible before falling into its normal +mode of behavior. +Only the super-user may use this option. +.It Fl n +Numeric output only. +No attempt will be made to look up symbolic names for host addresses. +.It Fl o +Exit successfully after receiving one reply packet. +.It Fl P +Use a pseudo-random sequence for the data instead of the default, +fixed sequence of incrementing 8-bit integers. +This is useful to foil compression on PPP and other links. +.It Fl p Ar pattern +You may specify up to 16 ``pad'' bytes to fill out the packet you send. +This is useful for diagnosing data-dependent problems in a network. +For example, +.Dq Li \-p ff +will cause the sent packet to be filled with all +ones. +.It Fl Q +Do not display responses such as Network Unreachable ICMP messages +concerning the ECHO_REQUESTs sent. +.It Fl q +Quiet output. +Nothing is displayed except the summary lines at startup time and +when finished. +.It Fl R +Record Route. +Includes the +.Tn RECORD_ROUTE +option in the +.Tn ECHO_REQUEST +packet and displays the route buffer on returned packets. +This should show the path to the target host and back, which is +especially useful in the case of asymmetric routing. +Note that the IP header is only large enough for nine such addresses, +and only seven when using the +.Fl g +option. +This is why it was necessary to invent +.Xr traceroute 8 . +Many hosts ignore or discard this option. +.It Fl r +Bypass the normal routing tables and send directly to a host on an attached +network. +If the host is not on a directly-attached network, an error is returned. +This option can be used to ping a local host through an interface +that has no route through it (e.g., after the interface was dropped by +.Xr routed 8 ) . +.It Fl s Ar packetsize +Specifies the number of data bytes to be sent. +The default is 56, which translates into 64 +.Tn ICMP +data bytes when combined +with the 8 bytes of +.Tn ICMP +header data. +The maximum allowed value is 65467 bytes. +.It Fl T Ar ttl +Use the specified time-to-live. +.It Fl t Ar tos +Use the specified hexadecimal type of service. +.It Fl v +Verbose output. +.Tn ICMP +packets other than +.Tn ECHO_RESPONSE +that are received are listed. +.It Fl w Ar deadline +Specifies a timeout, in seconds, before ping exits regardless of +how many packets have been sent or received. +.El +.Pp +When using +.Nm +for fault isolation, it should first be run on the local host, to verify +that the local network interface is up and running. +Then, hosts and gateways further and further away should be ``pinged''. +.Pp +Round-trip times and packet loss statistics are computed. +If duplicate packets are received, they are not included in the packet +loss calculation, although the round trip time of these packets is used +in calculating the minimum/average/maximum round-trip time numbers. +.Pp +When the specified number of packets have been sent (and received) or +if the program is terminated with a +.Dv SIGINT , +a brief summary is displayed. +The summary information can be displayed while +.Nm +is running by sending it a +.Dv SIGINFO +signal (see the +.Dq status +argument for +.Xr stty 1 +for more information). +.Pp +.Nm +continually sends one datagram per second, and prints one line of +output for every ECHO_RESPONSE returned. +On a trusted system with IP +Security Options enabled, if the network idiom is not MONO, +.Nm +also prints a second line containing the hexadecimal representation +of the IP security option in the ECHO_RESPONSE. +If the +.Fl c +count option is given, only that number of requests is sent. +No output is produced if there is no response. +Round-trip times and packet loss statistics are computed. +If duplicate packets are received, +they are not included in the packet loss calculation, +although the round trip time of these packets is used in calculating +the minimum/average/maximum round-trip time numbers. +When the specified number of packets have been sent (and received) or if +the program is terminated with an interrupt (SIGINT), a brief +summary is displayed. +When not using the +.Fl f +(flood) option, the first interrupt, usually generated by control-C or DEL, +causes +.Nm +to wait for its outstanding requests to return. +It will wait no longer than the longest round trip time +encountered by previous, successful pings. +The second interrupt stops ping immediately. +.Pp +This program is intended for use in network testing, measurement and +management. +Because of the load it can impose on the network, it is unwise to use +.Nm +during normal operations or from automated scripts. +.Sh ICMP PACKET DETAILS +An IP header without options is 20 bytes. +An +.Tn ICMP +.Tn ECHO_REQUEST +packet contains an additional 8 bytes worth of +.Tn ICMP +header followed by an arbitrary amount of data. +When a +.Ar packetsize +is given, this indicated the size of this extra piece of data (the +default is 56). +Thus the amount of data received inside of an IP packet of type +.Tn ICMP +.Tn ECHO_REPLY +will always be 8 bytes more than the requested data space (the +.Tn ICMP +header). +.Pp +If the data space is at least +.Dv sizeof(struct timespec) +(16) large, +.Nm +uses the first +.Dv sizeof(struct timespec) +bytes to include a timestamp to compute round trip times. +Otherwise if the data space is at least eight bytes large (or the +.Fl C +flag is specified), +.Nm +uses the first eight bytes of this space to include a timestamp to compute +round trip times. +If there are not enough bytes of pad no round trip times are given. +.Sh DUPLICATE AND DAMAGED PACKETS +.Nm +will report duplicate and damaged packets. +Duplicate packets should never occur, and seem to be caused by +inappropriate link-level retransmissions. +Duplicates may occur in many situations and are rarely (if ever) a +good sign, although the presence of low levels of duplicates may not +always be cause for alarm. +.Pp +Damaged packets are obviously serious cause for alarm and often +indicate broken hardware somewhere in the +.Nm +packet's path (in the network or in the hosts). +.Sh TRYING DIFFERENT DATA PATTERNS +The (inter)network layer should never treat packets differently depending +on the data contained in the data portion. +Unfortunately, data-dependent problems have been known to sneak into +networks and remain undetected for long periods of time. +In many cases the particular pattern that will have problems is something +that doesn't have sufficient ``transitions'', such as all ones or all +zeros, or a pattern right at the edge, such as almost all zeros. +It isn't necessarily enough to specify a data pattern of all zeros (for +example) on the command line because the pattern that is of interest is +at the data link level, and the relationship between what you type and +what the controllers transmit can be complicated. +.Pp +This means that if you have a data-dependent problem you will probably +have to do a lot of testing to find it. +If you are lucky, you may manage to find a file that either can't be sent +across your network or that takes much longer to transfer than other +similar length files. +You can then examine this file for repeated patterns that you can test +using the +.Fl p +option of +.Nm . +.Sh TTL DETAILS +The +.Tn TTL +value of an IP packet represents the maximum number of IP routers +that the packet can go through before being thrown away. +In current practice you can expect each router in the Internet to decrement +the +.Tn TTL +field by exactly one. +.Pp +The +.Tn TCP/IP +specification states that the +.Tn TTL +field for +.Tn TCP +packets should +be set to 60, but many systems use smaller values +.Po +.Bx 4.3 +uses 30, +.Bx 4.2 +used 15 +.Pc . +.Pp +The maximum possible value of this field is 255, and most +.Ux +systems set the +.Tn TTL +field of +.Tn ICMP ECHO_REQUEST +packets to 255. +This is why you will find you can ``ping'' some hosts, but not reach them +with +.Xr telnet 1 +or +.Xr ftp 1 . +.Pp +In normal operation ping prints the ttl value from the packet it receives. +When a remote system receives a ping packet, it can do one of three things +with the +.Tn TTL +field in its response: +.Bl -bullet +.It +Not change it; this is what Berkeley +.Ux +systems did before the +.Bx 4.3 tahoe +release. +In this case the +.Tn TTL +value in the received packet will be 255 minus the +number of routers in the round-trip path. +.It +Set it to 255; this is what current Berkeley +.Ux +systems do. +In this case the +.Tn TTL +value in the received packet will be 255 minus the +number of routers in the path +.Em from +the remote system +.Em to +the +.Nm Ns Em ing +host. +.It +Set it to some other value. +Some machines use the same value for +.Tn ICMP +packets that they use for +.Tn TCP +packets, for example either 30 or 60. +Others may use completely wild values. +.El +.Sh EXIT STATUS +.Nm +returns 0 on success (the host is alive), +and non-zero if the arguments are incorrect or the host is not responding. +.Sh SEE ALSO +.Xr netstat 1 , +.Xr icmp 4 , +.Xr inet 4 , +.Xr ip 4 , +.Xr ifconfig 8 , +.Xr routed 8 , +.Xr spray 8 , +.Xr traceroute 8 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . +IPsec support was added by WIDE/KAME project. +.Sh BUGS +Flood pinging is not recommended in general, and flood pinging a broadcast +or multicast address should only be done under very controlled conditions. +.Pp +The +.Nm +program has evolved differently under different operating systems, +and in some cases the same flag performs a different function +under different operating systems. +The +.Fl t +flag conflicts with +.Fx . +The +.Fl a , c , I , i , +.Fl l , P , p , s , +and +.Fl t +flags conflict with +.Sy Solaris . +.Pp +Some hosts and gateways ignore the +.Tn RECORD_ROUTE +option. +.Pp +The maximum IP header length is too small for options like +.Tn RECORD_ROUTE +to +be completely useful. +There's not much that that can be done about this, however. diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c new file mode 100644 index 000000000..f3d47e04e --- /dev/null +++ b/sbin/ping/ping.c @@ -0,0 +1,1923 @@ +/* $NetBSD: ping.c,v 1.107 2013/10/19 01:08:25 christos Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Muuss. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * P I N G . C + * + * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, + * measure round-trip-delays and packet loss across network paths. + * + * Author - + * Mike Muuss + * U. S. Army Ballistic Research Laboratory + * December, 1983 + * Modified at Uc Berkeley + * Record Route and verbose headers - Phil Dykstra, BRL, March 1988. + * Multicast options (ttl, if, loop) - Steve Deering, Stanford, August 1988. + * ttl, duplicate detection - Cliff Frost, UCB, April 1989 + * Pad pattern - Cliff Frost (from Tom Ferrin, UCSF), April 1989 + * + * Status - + * Public Domain. Distribution Unlimited. + * + * Bugs - + * More statistics could always be gathered. + * This program has to run SUID to ROOT to access the ICMP socket. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: ping.c,v 1.107 2013/10/19 01:08:25 christos Exp $"); +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef IPSEC +#include +#endif /*IPSEC*/ + +#include "prog_ops.h" + +#define FLOOD_INTVL 0.01 /* default flood output interval */ +#define MAXPACKET (IP_MAXPACKET-60-8) /* max packet size */ + +#define F_VERBOSE 0x0001 +#define F_QUIET 0x0002 /* minimize all output */ +#define F_SEMI_QUIET 0x0004 /* ignore our ICMP errors */ +#define F_FLOOD 0x0008 /* flood-ping */ +#define F_RECORD_ROUTE 0x0010 /* record route */ +#define F_SOURCE_ROUTE 0x0020 /* loose source route */ +#define F_PING_FILLED 0x0040 /* is buffer filled with user data? */ +#define F_PING_RANDOM 0x0080 /* use random data */ +#define F_NUMERIC 0x0100 /* do not do gethostbyaddr() calls */ +#define F_TIMING 0x0200 /* room for a timestamp */ +#define F_DF 0x0400 /* set IP DF bit */ +#define F_SOURCE_ADDR 0x0800 /* set source IP address/interface */ +#define F_ONCE 0x1000 /* exit(0) after receiving 1 reply */ +#define F_MCAST 0x2000 /* multicast target */ +#define F_MCAST_NOLOOP 0x4000 /* no multicast loopback */ +#define F_AUDIBLE 0x8000 /* audible output */ +#define F_TIMING64 0x10000 /* 64 bit time, nanoseconds */ +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +#define F_POLICY 0x20000 +#else +#define F_AUTHHDR 0x20000 +#define F_ENCRYPT 0x40000 +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + + +/* MAX_DUP_CHK is the number of bits in received table, the + * maximum number of received sequence numbers we can track to check + * for duplicates. + */ +#define MAX_DUP_CHK (8 * 2048) +static u_char rcvd_tbl[MAX_DUP_CHK/8]; +static int nrepeats = 0; +#define A(seq) rcvd_tbl[(seq/8)%sizeof(rcvd_tbl)] /* byte in array */ +#define B(seq) (1 << (seq & 0x07)) /* bit in byte */ +#define SET(seq) (A(seq) |= B(seq)) +#define CLR(seq) (A(seq) &= (~B(seq))) +#define TST(seq) (A(seq) & B(seq)) + +struct tv32 { + int32_t tv32_sec; + int32_t tv32_usec; +}; + + +static u_char *packet; +static int packlen; +static int pingflags = 0, options; +static int pongflags = 0; +static char *fill_pat; + +static int s; /* Socket file descriptor */ +static int sloop; /* Socket file descriptor/loopback */ + +#define PHDR_LEN sizeof(struct tv32) /* size of timestamp header */ +#define PHDR64_LEN sizeof(struct timespec) /* size of timestamp header */ +static struct sockaddr_in whereto, send_addr; /* Who to ping */ +static struct sockaddr_in src_addr; /* from where */ +static struct sockaddr_in loc_addr; /* 127.1 */ +static int datalen; /* How much data */ +static int phdrlen; + +#ifndef __NetBSD__ +static char *progname; +#define getprogname() (progname) +#define setprogname(name) ((void)(progname = (name))) +#endif + +static char hostname[MAXHOSTNAMELEN]; + +static struct { + struct ip o_ip; + char o_opt[MAX_IPOPTLEN]; + union { + u_char u_buf[MAXPACKET+offsetof(struct icmp, icmp_data)]; + struct icmp u_icmp; + } o_u; +} out_pack; +#define opack_icmp out_pack.o_u.u_icmp +static struct ip *opack_ip; + +static char optspace[MAX_IPOPTLEN]; /* record route space */ +static int optlen; + +static int npackets; /* total packets to send */ +static int preload; /* number of packets to "preload" */ +static int ntransmitted; /* output sequence # = #sent */ +static int ident; /* our ID, in network byte order */ + +static int nreceived; /* # of packets we got back */ + +static double interval; /* interval between packets */ +static struct timespec interval_tv; +static double tmin = 999999999.0; +static double tmax = 0.0; +static double tsum = 0.0; /* sum of all times */ +static double tsumsq = 0.0; +static double maxwait = 0.0; + +#ifndef __minix +static int bufspace = IP_MAXPACKET; +#endif + +static struct timespec now, clear_cache, last_tx, next_tx, first_tx; +static struct timespec last_rx, first_rx; +static int lastrcvd = 1; /* last ping sent has been received */ + +static struct timespec jiggle_time; +static int jiggle_cnt, total_jiggled, jiggle_direction = -1; + +__dead static void doit(void); +static void prefinish(int); +static void prtsig(int); +__dead static void finish(int); +static void summary(int); +static void pinger(void); +static void fill(void); +static void rnd_fill(void); +static double diffsec(struct timespec *, struct timespec *); +#if 0 +static void timespecadd(struct timespec *, struct timespec *); +#endif +static void sec_to_timespec(const double, struct timespec *); +static double timespec_to_sec(const struct timespec *); +static void pr_pack(u_char *, int, struct sockaddr_in *); +static u_int16_t in_cksum(u_int16_t *, u_int); +static void pr_saddr(u_char *); +static char *pr_addr(struct in_addr *); +static void pr_iph(struct icmp *, int); +static void pr_retip(struct icmp *, int); +static int pr_icmph(struct icmp *, struct sockaddr_in *, int); +static void jiggle(int), jiggle_flush(int); +static void gethost(const char *, const char *, + struct sockaddr_in *, char *, int); +__dead static void usage(void); + +int +main(int argc, char *argv[]) +{ + int c, i, on = 1, hostind = 0; + long l; + int len = -1, compat = 0; + u_char ttl = 0; + u_long tos = 0; + char *p; +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + char *policy_in = NULL; + char *policy_out = NULL; +#endif +#endif +#ifdef SIGINFO + struct sigaction sa; +#endif + + if (prog_init && prog_init() == -1) + err(1, "init failed"); + + if ((s = prog_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) + err(1, "Cannot create socket"); + if ((sloop = prog_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) + err(1, "Cannot create socket"); + +#ifndef __minix + /* + * sloop is never read on. This prevents packets from + * queueing in its recv buffer. + */ + if (prog_shutdown(sloop, SHUT_RD) == -1) + warn("Cannot shutdown for read"); +#endif + + if (prog_setuid(prog_getuid()) == -1) + err(1, "setuid"); + + setprogname(argv[0]); + +#ifndef IPSEC +#define IPSECOPT +#else +#ifdef IPSEC_POLICY_IPSEC +#define IPSECOPT "E:" +#else +#define IPSECOPT "AE" +#endif /*IPSEC_POLICY_IPSEC*/ +#endif + while ((c = getopt(argc, argv, + "ac:CdDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:" IPSECOPT)) != -1) { +#undef IPSECOPT + switch (c) { + case 'a': + pingflags |= F_AUDIBLE; + break; + case 'C': + compat = 1; + break; + case 'c': + npackets = strtol(optarg, &p, 0); + if (*p != '\0' || npackets <= 0) + errx(1, "Bad/invalid number of packets"); + break; + case 'D': + pingflags |= F_DF; + break; + case 'd': + options |= SO_DEBUG; + break; + case 'f': + pingflags |= F_FLOOD; + break; + case 'h': + hostind = optind-1; + break; + case 'i': /* wait between sending packets */ + interval = strtod(optarg, &p); + if (*p != '\0' || interval <= 0) + errx(1, "Bad/invalid interval %s", optarg); + break; + case 'l': + preload = strtol(optarg, &p, 0); + if (*p != '\0' || preload < 0) + errx(1, "Bad/invalid preload value %s", + optarg); + break; + case 'n': + pingflags |= F_NUMERIC; + break; + case 'o': + pingflags |= F_ONCE; + break; + case 'p': /* fill buffer with user pattern */ + if (pingflags & F_PING_RANDOM) + errx(1, "Only one of -P and -p allowed"); + pingflags |= F_PING_FILLED; + fill_pat = optarg; + break; + case 'P': + if (pingflags & F_PING_FILLED) + errx(1, "Only one of -P and -p allowed"); + pingflags |= F_PING_RANDOM; + break; + case 'q': + pingflags |= F_QUIET; + break; + case 'Q': + pingflags |= F_SEMI_QUIET; + break; + case 'r': + options |= SO_DONTROUTE; + break; + case 's': /* size of packet to send */ + l = strtol(optarg, &p, 0); + if (*p != '\0' || l < 0) + errx(1, "Bad/invalid packet size %s", optarg); + if (l > MAXPACKET) + errx(1, "packet size is too large"); + len = (int)l; + break; + case 'v': + pingflags |= F_VERBOSE; + break; + case 'R': + pingflags |= F_RECORD_ROUTE; + break; + case 'L': + pingflags |= F_MCAST_NOLOOP; + break; + case 't': + tos = strtoul(optarg, &p, 0); + if (*p != '\0' || tos > 0xFF) + errx(1, "bad tos value: %s", optarg); + break; + case 'T': + l = strtol(optarg, &p, 0); + if (*p != '\0' || l > 255 || l <= 0) + errx(1, "ttl out of range"); + ttl = (u_char)l; /* cannot check >255 otherwise */ + break; + case 'I': + pingflags |= F_SOURCE_ADDR; + gethost("-I", optarg, &src_addr, 0, 0); + break; + case 'g': + pingflags |= F_SOURCE_ROUTE; + gethost("-g", optarg, &send_addr, 0, 0); + break; + case 'w': + maxwait = strtod(optarg, &p); + if (*p != '\0' || maxwait <= 0) + errx(1, "Bad/invalid maxwait time %s", optarg); + break; +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + case 'E': + pingflags |= F_POLICY; + if (!strncmp("in", optarg, 2)) { + policy_in = strdup(optarg); + if (!policy_in) + err(1, "strdup"); + } else if (!strncmp("out", optarg, 3)) { + policy_out = strdup(optarg); + if (!policy_out) + err(1, "strdup"); + } else + errx(1, "invalid security policy"); + break; +#else + case 'A': + pingflags |= F_AUTHHDR; + break; + case 'E': + pingflags |= F_ENCRYPT; + break; +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + default: + usage(); + break; + } + } + + if (interval == 0) + interval = (pingflags & F_FLOOD) ? FLOOD_INTVL : 1.0; +#ifndef sgi + if (pingflags & F_FLOOD && prog_getuid()) + errx(1, "Must be superuser to use -f"); + if (interval < 1.0 && prog_getuid()) + errx(1, "Must be superuser to use < 1 sec ping interval"); + if (preload > 0 && prog_getuid()) + errx(1, "Must be superuser to use -l"); +#endif + sec_to_timespec(interval, &interval_tv); + + if ((pingflags & (F_AUDIBLE|F_FLOOD)) == (F_AUDIBLE|F_FLOOD)) + warnx("Sorry, no audible output for flood pings"); + + if (npackets != 0) { + npackets += preload; + } else { + npackets = INT_MAX; + } + + if (hostind == 0) { + if (optind != argc-1) + usage(); + else + hostind = optind; + } + else if (hostind >= argc - 1) + usage(); + + gethost("", argv[hostind], &whereto, hostname, sizeof(hostname)); + if (IN_MULTICAST(ntohl(whereto.sin_addr.s_addr))) + pingflags |= F_MCAST; + if (!(pingflags & F_SOURCE_ROUTE)) + (void) memcpy(&send_addr, &whereto, sizeof(send_addr)); + + loc_addr.sin_family = AF_INET; + loc_addr.sin_len = sizeof(struct sockaddr_in); + loc_addr.sin_addr.s_addr = htonl((127 << 24) + 1); + + if (len != -1) + datalen = len; + else + datalen = 64; + if (!compat && datalen >= (int)PHDR64_LEN) { /* can we time them? */ + pingflags |= F_TIMING64; + phdrlen = PHDR64_LEN; + } else if (datalen >= (int)PHDR_LEN) { /* can we time them? */ + pingflags |= F_TIMING; + phdrlen = PHDR_LEN; + } else + phdrlen = 0; + + packlen = datalen + 60 + 76; /* MAXIP + MAXICMP */ + datalen -= phdrlen; + if ((packet = malloc(packlen)) == NULL) + err(1, "Out of memory"); + + if (pingflags & F_PING_FILLED) { + fill(); + } else if (pingflags & F_PING_RANDOM) { + rnd_fill(); + } else { + for (i = phdrlen; i < datalen; i++) + opack_icmp.icmp_data[i] = i; + } + + ident = arc4random() & 0xFFFF; + + if (options & SO_DEBUG) { + if (prog_setsockopt(s, SOL_SOCKET, SO_DEBUG, + (char *)&on, sizeof(on)) == -1) + warn("Can't turn on socket debugging"); + } + if (options & SO_DONTROUTE) { + if (prog_setsockopt(s, SOL_SOCKET, SO_DONTROUTE, + (char *)&on, sizeof(on)) == -1) + warn("SO_DONTROUTE"); + } + + if (options & SO_DEBUG) { + if (prog_setsockopt(sloop, SOL_SOCKET, SO_DEBUG, + (char *)&on, sizeof(on)) == -1) + warn("Can't turn on socket debugging"); + } + if (options & SO_DONTROUTE) { + if (prog_setsockopt(sloop, SOL_SOCKET, SO_DONTROUTE, + (char *)&on, sizeof(on)) == -1) + warn("SO_DONTROUTE"); + } + + if (pingflags & F_SOURCE_ROUTE) { + optspace[IPOPT_OPTVAL] = IPOPT_LSRR; + optspace[IPOPT_OLEN] = optlen = 7; + optspace[IPOPT_OFFSET] = IPOPT_MINOFF; + (void)memcpy(&optspace[IPOPT_MINOFF-1], &whereto.sin_addr, + sizeof(whereto.sin_addr)); + optspace[optlen++] = IPOPT_NOP; + } + if (pingflags & F_RECORD_ROUTE) { + optspace[optlen+IPOPT_OPTVAL] = IPOPT_RR; + optspace[optlen+IPOPT_OLEN] = (MAX_IPOPTLEN -1-optlen); + optspace[optlen+IPOPT_OFFSET] = IPOPT_MINOFF; + optlen = MAX_IPOPTLEN; + } + /* this leaves opack_ip 0(mod 4) aligned */ + opack_ip = (struct ip *)((char *)&out_pack.o_ip + + sizeof(out_pack.o_opt) + - optlen); + (void) memcpy(opack_ip + 1, optspace, optlen); + +#ifndef __minix + if (prog_setsockopt(s,IPPROTO_IP,IP_HDRINCL, + (char *) &on, sizeof(on)) < 0) + err(1, "Can't set special IP header"); +#endif + + opack_ip->ip_v = IPVERSION; + opack_ip->ip_hl = (sizeof(struct ip)+optlen) >> 2; + opack_ip->ip_tos = tos; + opack_ip->ip_off = (pingflags & F_DF) ? IP_DF : 0; + opack_ip->ip_ttl = ttl ? ttl : MAXTTL; + opack_ip->ip_p = IPPROTO_ICMP; + opack_ip->ip_src = src_addr.sin_addr; + opack_ip->ip_dst = send_addr.sin_addr; + + if (pingflags & F_MCAST) { + if (pingflags & F_MCAST_NOLOOP) { + u_char loop = 0; + if (prog_setsockopt(s, IPPROTO_IP, + IP_MULTICAST_LOOP, + (char *) &loop, 1) < 0) + err(1, "Can't disable multicast loopback"); + } + + if (ttl != 0 + && prog_setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, + (char *) &ttl, 1) < 0) + err(1, "Can't set multicast time-to-live"); + + if ((pingflags & F_SOURCE_ADDR) + && prog_setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, + (char *) &src_addr.sin_addr, + sizeof(src_addr.sin_addr)) < 0) + err(1, "Can't set multicast source interface"); + + } else if (pingflags & F_SOURCE_ADDR) { + if (prog_setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, + (char *) &src_addr.sin_addr, + sizeof(src_addr.sin_addr)) < 0) + err(1, "Can't set source interface/address"); + } +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + { + char *buf; + if (pingflags & F_POLICY) { + if (policy_in != NULL) { + buf = ipsec_set_policy(policy_in, strlen(policy_in)); + if (buf == NULL) + errx(1, "%s", ipsec_strerror()); + if (prog_setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) { + err(1, "ipsec policy cannot be configured"); + } + free(buf); + } + if (policy_out != NULL) { + buf = ipsec_set_policy(policy_out, strlen(policy_out)); + if (buf == NULL) + errx(1, "%s", ipsec_strerror()); + if (prog_setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) { + err(1, "ipsec policy cannot be configured"); + } + free(buf); + } + } + buf = ipsec_set_policy("out bypass", strlen("out bypass")); + if (buf == NULL) + errx(1, "%s", ipsec_strerror()); + if (prog_setsockopt(sloop, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)) < 0) { +#if 0 + warnx("ipsec is not configured"); +#else + /* ignore it, should be okay */ +#endif + } + free(buf); + } +#else + { + int optval; + if (pingflags & F_AUTHHDR) { + optval = IPSEC_LEVEL_REQUIRE; +#ifdef IP_AUTH_TRANS_LEVEL + (void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, + (char *)&optval, sizeof(optval)); +#else + (void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, + (char *)&optval, sizeof(optval)); +#endif + } + if (pingflags & F_ENCRYPT) { + optval = IPSEC_LEVEL_REQUIRE; + (void)prog_setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, + (char *)&optval, sizeof(optval)); + } + optval = IPSEC_LEVEL_BYPASS; +#ifdef IP_AUTH_TRANS_LEVEL + (void)prog_setsockopt(sloop, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, + (char *)&optval, sizeof(optval)); +#else + (void)prog_setsockopt(sloop, IPPROTO_IP, IP_AUTH_LEVEL, + (char *)&optval, sizeof(optval)); +#endif + (void)prog_setsockopt(sloop, IPPROTO_IP, IP_ESP_TRANS_LEVEL, + (char *)&optval, sizeof(optval)); + } +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + + (void)printf("PING %s (%s): %d data bytes\n", hostname, + inet_ntoa(whereto.sin_addr), datalen + phdrlen); + +#ifndef __minix + /* When pinging the broadcast address, you can get a lot + * of answers. Doing something so evil is useful if you + * are trying to stress the ethernet, or just want to + * fill the arp cache to get some stuff for /etc/ethers. + */ + while (0 > prog_setsockopt(s, SOL_SOCKET, SO_RCVBUF, + (char*)&bufspace, sizeof(bufspace))) { + if ((bufspace -= 4096) <= 0) + err(1, "Cannot set the receive buffer size"); + } + + /* make it possible to send giant probes, but do not worry now + * if it fails, since we probably won't send giant probes. + */ + (void)prog_setsockopt(s, SOL_SOCKET, SO_SNDBUF, + (char*)&bufspace, sizeof(bufspace)); +#endif + + (void)signal(SIGINT, prefinish); + +#ifdef SIGINFO + sa.sa_handler = prtsig; + sa.sa_flags = SA_NOKERNINFO; + sigemptyset(&sa.sa_mask); + (void)sigaction(SIGINFO, &sa, NULL); +#else + (void)signal(SIGQUIT, prtsig); +#endif + (void)signal(SIGCONT, prtsig); + + /* fire off them quickies */ + for (i = 0; i < preload; i++) { + clock_gettime(CLOCK_MONOTONIC, &now); + pinger(); + } + + doit(); + return 0; +} + + +static void +doit(void) +{ + int cc; + struct sockaddr_in from; + socklen_t fromlen; + double sec, last, d_last; + struct pollfd fdmaskp[1]; + + (void)clock_gettime(CLOCK_MONOTONIC, &clear_cache); + if (maxwait != 0) { + last = timespec_to_sec(&clear_cache) + maxwait; + d_last = 0; + } else { + last = 0; + d_last = 365*24*60*60; + } + + do { + clock_gettime(CLOCK_MONOTONIC, &now); + + if (last != 0) + d_last = last - timespec_to_sec(&now); + + if (ntransmitted < npackets && d_last > 0) { + /* send if within 100 usec or late for next packet */ + sec = diffsec(&next_tx, &now); + if (sec <= 0.0001 || + (lastrcvd && (pingflags & F_FLOOD))) { + pinger(); + sec = diffsec(&next_tx, &now); + } + if (sec < 0.0) + sec = 0.0; + if (d_last < sec) + sec = d_last; + + } else { + /* For the last response, wait twice as long as the + * worst case seen, or 10 times as long as the + * maximum interpacket interval, whichever is longer. + */ + sec = MAX(2 * tmax, 10 * interval) - + diffsec(&now, &last_tx); + if (d_last < sec) + sec = d_last; + if (sec <= 0) + break; + } + + fdmaskp[0].fd = s; + fdmaskp[0].events = POLLIN; + cc = prog_poll(fdmaskp, 1, (int)(sec * 1000)); + if (cc <= 0) { + if (cc < 0) { + if (errno == EINTR) + continue; + jiggle_flush(1); + err(1, "poll"); + } + continue; + } + + fromlen = sizeof(from); + cc = prog_recvfrom(s, (char *) packet, packlen, + 0, (struct sockaddr *)&from, + &fromlen); + if (cc < 0) { + perror("recvfrom failed"); + if (errno != EINTR) { + jiggle_flush(1); + warn("recvfrom"); + (void)fflush(stderr); + } + continue; + } + clock_gettime(CLOCK_MONOTONIC, &now); + pr_pack(packet, cc, &from); + + } while (nreceived < npackets + && (nreceived == 0 || !(pingflags & F_ONCE))); + + finish(0); +} + + +static void +jiggle_flush(int nl) /* new line if there are dots */ +{ + int serrno = errno; + + if (jiggle_cnt > 0) { + total_jiggled += jiggle_cnt; + jiggle_direction = 1; + do { + (void)putchar('.'); + } while (--jiggle_cnt > 0); + + } else if (jiggle_cnt < 0) { + total_jiggled -= jiggle_cnt; + jiggle_direction = -1; + do { + (void)putchar('\b'); + } while (++jiggle_cnt < 0); + } + + if (nl) { + if (total_jiggled != 0) + (void)putchar('\n'); + total_jiggled = 0; + jiggle_direction = -1; + } + + (void)fflush(stdout); + (void)fflush(stderr); + jiggle_time = now; + errno = serrno; +} + + +/* jiggle the cursor for flood-ping + */ +static void +jiggle(int delta) +{ + double dt; + + if (pingflags & F_QUIET) + return; + + /* do not back up into messages */ + if (total_jiggled+jiggle_cnt+delta < 0) + return; + + jiggle_cnt += delta; + + /* flush the FLOOD dots when things are quiet + * or occassionally to make the cursor jiggle. + */ + dt = diffsec(&last_tx, &jiggle_time); + if (dt > 0.2 || (dt >= 0.15 && delta*jiggle_direction < 0)) + jiggle_flush(0); +} + + +/* + * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet + * will be added on by the kernel. The ID field is our UNIX process ID, + * and the sequence number is an ascending integer. The first phdrlen bytes + * of the data portion are used to hold a UNIX "timeval" struct in VAX + * byte-order, to compute the round-trip time, or a UNIX "timespec" in native + * format. + */ +static void +pinger(void) +{ + struct tv32 tv32; +#ifndef __minix + int i, cc, sw; +#else + int i, cc; +#endif + + opack_icmp.icmp_code = 0; + opack_icmp.icmp_seq = htons((u_int16_t)(ntransmitted)); + +#ifndef __minix + /* clear the cached route in the kernel after an ICMP + * response such as a Redirect is seen to stop causing + * more such packets. Also clear the cached route + * periodically in case of routing changes that make + * black holes come and go. + */ + if (clear_cache.tv_sec != now.tv_sec) { + opack_icmp.icmp_type = ICMP_ECHOREPLY; + opack_icmp.icmp_id = ~ident; + opack_icmp.icmp_cksum = 0; + opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp, + phdrlen); + sw = 0; + if (prog_setsockopt(sloop,IPPROTO_IP,IP_HDRINCL, + (char *)&sw,sizeof(sw)) < 0) + err(1, "Can't turn off special IP header"); + if (prog_sendto(sloop, (char *) &opack_icmp, + ICMP_MINLEN, MSG_DONTROUTE, + (struct sockaddr *)&loc_addr, + sizeof(struct sockaddr_in)) < 0) { + /* + * XXX: we only report this as a warning in verbose + * mode because people get confused when they see + * this error when they are running in single user + * mode and they have not configured lo0 + */ + if (pingflags & F_VERBOSE) + warn("failed to clear cached route"); + } + sw = 1; + if (prog_setsockopt(sloop,IPPROTO_IP,IP_HDRINCL, + (char *)&sw, sizeof(sw)) < 0) + err(1, "Can't set special IP header"); + + (void)clock_gettime(CLOCK_MONOTONIC, &clear_cache); + } +#endif + + opack_icmp.icmp_type = ICMP_ECHO; + opack_icmp.icmp_id = ident; + + if (pingflags & F_TIMING) { + tv32.tv32_sec = (uint32_t)htonl(now.tv_sec); + tv32.tv32_usec = htonl(now.tv_nsec / 1000); + (void) memcpy(&opack_icmp.icmp_data[0], &tv32, sizeof(tv32)); + } else if (pingflags & F_TIMING64) + (void) memcpy(&opack_icmp.icmp_data[0], &now, sizeof(now)); + + cc = MAX(datalen, ICMP_MINLEN) + phdrlen; + opack_icmp.icmp_cksum = 0; + opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp, cc); + + cc += opack_ip->ip_hl<<2; + opack_ip->ip_len = cc; + i = prog_sendto(s, (char *) opack_ip, cc, 0, + (struct sockaddr *)&send_addr, sizeof(struct sockaddr_in)); + + if (i != cc) { + jiggle_flush(1); + if (i < 0) + warn("sendto"); + else + warnx("wrote %s %d chars, ret=%d", hostname, cc, i); + (void)fflush(stderr); + } + lastrcvd = 0; + + CLR(ntransmitted); + ntransmitted++; + + last_tx = now; + if (next_tx.tv_sec == 0) { + first_tx = now; + next_tx = now; + } + + /* Transmit regularly, at always the same microsecond in the + * second when going at one packet per second. + * If we are at most 100 ms behind, send extras to get caught up. + * Otherwise, skip packets we were too slow to send. + */ + if (diffsec(&next_tx, &now) <= interval) { + do { + timespecadd(&next_tx, &interval_tv, &next_tx); + } while (diffsec(&next_tx, &now) < -0.1); + } + + if (pingflags & F_FLOOD) + jiggle(1); + + /* While the packet is going out, ready buffer for the next + * packet. Use a fast but not very good random number generator. + */ + if (pingflags & F_PING_RANDOM) + rnd_fill(); +} + + +static void +pr_pack_sub(int cc, + char *addr, + int seqno, + int dupflag, + int ttl, + double triptime) +{ + jiggle_flush(1); + + if (pingflags & F_FLOOD) + return; + + (void)printf("%d bytes from %s: icmp_seq=%u", cc, addr, seqno); + if (dupflag) + (void)printf(" DUP!"); + (void)printf(" ttl=%d", ttl); + if (pingflags & (F_TIMING|F_TIMING64)) { + const unsigned int prec = (pingflags & F_TIMING64) != 0 ? 6 : 3; + + (void)printf(" time=%.*f ms", prec, triptime*1000.0); + } + + /* + * Send beep to stderr, since that's more likely than stdout + * to go to a terminal.. + */ + if (pingflags & F_AUDIBLE && !dupflag) + (void)fprintf(stderr,"\a"); +} + + +/* + * Print out the packet, if it came from us. This logic is necessary + * because ALL readers of the ICMP socket get a copy of ALL ICMP packets + * which arrive ('tis only fair). This permits multiple copies of this + * program to be run without having intermingled output (or statistics!). + */ +static void +pr_pack(u_char *buf, + int tot_len, + struct sockaddr_in *from) +{ + struct ip *ip; + struct icmp *icp; + int i, j, net_len; + u_char *cp; + static int old_rrlen; + static char old_rr[MAX_IPOPTLEN]; + int hlen, dupflag = 0, dumped; + double triptime = 0.0; +#define PR_PACK_SUB() {if (!dumped) { \ + dumped = 1; \ + pr_pack_sub(net_len, inet_ntoa(from->sin_addr), \ + ntohs((u_int16_t)icp->icmp_seq), \ + dupflag, ip->ip_ttl, triptime);}} + + /* Check the IP header */ + ip = (struct ip *) buf; + hlen = ip->ip_hl << 2; + if (tot_len < hlen + ICMP_MINLEN) { + if (pingflags & F_VERBOSE) { + jiggle_flush(1); + (void)printf("packet too short (%d bytes) from %s\n", + tot_len, inet_ntoa(from->sin_addr)); + } + return; + } + + /* Now the ICMP part */ + dumped = 0; + net_len = tot_len - hlen; + icp = (struct icmp *)(buf + hlen); + if (icp->icmp_type == ICMP_ECHOREPLY + && icp->icmp_id == ident) { + + if (icp->icmp_seq == htons((u_int16_t)(ntransmitted-1))) + lastrcvd = 1; + last_rx = now; + if (first_rx.tv_sec == 0) + first_rx = last_rx; + nreceived++; + if (pingflags & (F_TIMING|F_TIMING64)) { + struct timespec tv; + + if (pingflags & F_TIMING) { + struct tv32 tv32; + + (void)memcpy(&tv32, icp->icmp_data, sizeof(tv32)); + tv.tv_sec = (uint32_t)ntohl(tv32.tv32_sec); + tv.tv_nsec = ntohl(tv32.tv32_usec) * 1000; + } else if (pingflags & F_TIMING64) + (void)memcpy(&tv, icp->icmp_data, sizeof(tv)); + else + memset(&tv, 0, sizeof(tv)); /* XXX: gcc */ + + triptime = diffsec(&last_rx, &tv); + tsum += triptime; + tsumsq += triptime * triptime; + if (triptime < tmin) + tmin = triptime; + if (triptime > tmax) + tmax = triptime; + } + + if (TST(ntohs((u_int16_t)icp->icmp_seq))) { + nrepeats++, nreceived--; + dupflag=1; + } else { + SET(ntohs((u_int16_t)icp->icmp_seq)); + } + + if (tot_len != opack_ip->ip_len) { + PR_PACK_SUB(); + switch (opack_ip->ip_len - tot_len) { + case MAX_IPOPTLEN: + if ((pongflags & F_RECORD_ROUTE) != 0) + break; + if ((pingflags & F_RECORD_ROUTE) == 0) + goto out; + pongflags |= F_RECORD_ROUTE; + (void)printf("\nremote host does not " + "support record route"); + break; + case 8: + if ((pongflags & F_SOURCE_ROUTE) != 0) + break; + if ((pingflags & F_SOURCE_ROUTE) == 0) + goto out; + pongflags |= F_SOURCE_ROUTE; + (void)printf("\nremote host does not " + "support source route"); + break; + default: + out: + (void)printf("\nwrong total length %d " + "instead of %d", tot_len, opack_ip->ip_len); + break; + } + } + + if (!dupflag) { + static u_int16_t last_seqno = 0xffff; + u_int16_t seqno = ntohs((u_int16_t)icp->icmp_seq); + u_int16_t gap = seqno - (last_seqno + 1); + if (gap > 0 && gap < 0x8000 && + (pingflags & F_VERBOSE)) { + (void)printf("[*** sequence gap of %u " + "packets from %u ... %u ***]\n", gap, + (u_int16_t) (last_seqno + 1), + (u_int16_t) (seqno - 1)); + if (pingflags & F_QUIET) + summary(0); + } + + if (gap < 0x8000) + last_seqno = seqno; + } + + if (pingflags & F_QUIET) + return; + + if (!(pingflags & F_FLOOD)) + PR_PACK_SUB(); + + /* check the data */ + if ((size_t)(tot_len - hlen) > + offsetof(struct icmp, icmp_data) + datalen + && !(pingflags & F_PING_RANDOM) + && memcmp(icp->icmp_data + phdrlen, + opack_icmp.icmp_data + phdrlen, + datalen - phdrlen)) { + for (i = phdrlen; i < datalen; i++) { + if (icp->icmp_data[i] != + opack_icmp.icmp_data[i]) + break; + } + PR_PACK_SUB(); + (void)printf("\nwrong data byte #%d should have been" + " %#x but was %#x", i, + (u_char)opack_icmp.icmp_data[i], + (u_char)icp->icmp_data[i]); + for (i = phdrlen; i < datalen; i++) { + if ((i % 16) == 0) + (void)printf("\n\t"); + (void)printf("%2x ",(u_char)icp->icmp_data[i]); + } + } + + } else { + if (!pr_icmph(icp, from, net_len)) + return; + dumped = 2; + } + + /* Display any IP options */ + cp = buf + sizeof(struct ip); + while (hlen > (int)sizeof(struct ip)) { + switch (*cp) { + case IPOPT_EOL: + hlen = 0; + break; + case IPOPT_LSRR: + hlen -= 2; + j = *++cp; + ++cp; + j -= IPOPT_MINOFF; + if (j <= 0) + continue; + if (dumped <= 1) { + j = ((j+3)/4)*4; + hlen -= j; + cp += j; + break; + } + PR_PACK_SUB(); + (void)printf("\nLSRR: "); + for (;;) { + pr_saddr(cp); + cp += 4; + hlen -= 4; + j -= 4; + if (j <= 0) + break; + (void)putchar('\n'); + } + break; + case IPOPT_RR: + j = *++cp; /* get length */ + i = *++cp; /* and pointer */ + hlen -= 2; + if (i > j) + i = j; + i -= IPOPT_MINOFF; + if (i <= 0) + continue; + if (dumped <= 1) { + if (i == old_rrlen + && !memcmp(cp, old_rr, i)) { + if (dumped) + (void)printf("\t(same route)"); + j = ((i+3)/4)*4; + hlen -= j; + cp += j; + break; + } + old_rrlen = i; + (void) memcpy(old_rr, cp, i); + } + if (!dumped) { + jiggle_flush(1); + (void)printf("RR: "); + dumped = 1; + } else { + (void)printf("\nRR: "); + } + for (;;) { + pr_saddr(cp); + cp += 4; + hlen -= 4; + i -= 4; + if (i <= 0) + break; + (void)putchar('\n'); + } + break; + case IPOPT_NOP: + if (dumped <= 1) + break; + PR_PACK_SUB(); + (void)printf("\nNOP"); + break; +#ifdef sgi + case IPOPT_SECURITY: /* RFC 1108 RIPSO BSO */ + case IPOPT_ESO: /* RFC 1108 RIPSO ESO */ + case IPOPT_CIPSO: /* Commercial IPSO */ + if ((sysconf(_SC_IP_SECOPTS)) > 0) { + i = (unsigned)cp[1]; + hlen -= i - 1; + PR_PACK_SUB(); + (void)printf("\nSEC:"); + while (i--) { + (void)printf(" %02x", *cp++); + } + cp--; + break; + } +#endif + default: + PR_PACK_SUB(); + (void)printf("\nunknown option 0x%x", *cp); + break; + } + hlen--; + cp++; + } + + if (dumped) { + (void)putchar('\n'); + (void)fflush(stdout); + } else { + jiggle(-1); + } +} + + +/* Compute the IP checksum + * This assumes the packet is less than 32K long. + */ +static u_int16_t +in_cksum(u_int16_t *p, u_int len) +{ + u_int32_t sum = 0; + int nwords = len >> 1; + + while (nwords-- != 0) + sum += *p++; + + if (len & 1) { + union { + u_int16_t w; + u_int8_t c[2]; + } u; + u.c[0] = *(u_char *)p; + u.c[1] = 0; + sum += u.w; + } + + /* end-around-carry */ + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return (~sum); +} + + +/* + * compute the difference of two timespecs in seconds + */ +static double +diffsec(struct timespec *timenow, + struct timespec *then) +{ + if (timenow->tv_sec == 0) + return -1; + return (timenow->tv_sec - then->tv_sec) + * 1.0 + (timenow->tv_nsec - then->tv_nsec) / 1000000000.0; +} + + +#if 0 +static void +timespecadd(struct timespec *t1, + struct timespec *t2) +{ + + t1->tv_sec += t2->tv_sec; + if ((t1->tv_nsec += t2->tv_nsec) >= 1000000000) { + t1->tv_sec++; + t1->tv_nsec -= 1000000000; + } +} +#endif + + +static void +sec_to_timespec(const double sec, struct timespec *tp) +{ + tp->tv_sec = sec; + tp->tv_nsec = (sec - tp->tv_sec) * 1000000000.0; +} + + +static double +timespec_to_sec(const struct timespec *tp) +{ + return tp->tv_sec + tp->tv_nsec / 1000000000.0; +} + + +/* + * Print statistics. + * Heavily buffered STDIO is used here, so that all the statistics + * will be written with 1 sys-write call. This is nice when more + * than one copy of the program is running on a terminal; it prevents + * the statistics output from becomming intermingled. + */ +static void +summary(int header) +{ + jiggle_flush(1); + + if (header) + (void)printf("\n----%s PING Statistics----\n", hostname); + (void)printf("%d packets transmitted, ", ntransmitted); + (void)printf("%d packets received, ", nreceived); + if (nrepeats) + (void)printf("+%d duplicates, ", nrepeats); + if (ntransmitted) { + if (nreceived > ntransmitted) + (void)printf("-- somebody's duplicating packets!"); + else + (void)printf("%.1f%% packet loss", + (((ntransmitted-nreceived)*100.0) / + ntransmitted)); + } + (void)printf("\n"); + if (nreceived && (pingflags & (F_TIMING|F_TIMING64))) { + double n = nreceived + nrepeats; + double avg = (tsum / n); + double variance = 0.0; + const unsigned int prec = (pingflags & F_TIMING64) != 0 ? 6 : 3; + if (n>1) + variance = (tsumsq - n*avg*avg) /(n-1); + + printf("round-trip min/avg/max/stddev = " + "%.*f/%.*f/%.*f/%.*f ms\n", + prec, tmin * 1000.0, + prec, avg * 1000.0, + prec, tmax * 1000.0, + prec, sqrt(variance) * 1000.0); + if (pingflags & F_FLOOD) { + double r = diffsec(&last_rx, &first_rx); + double t = diffsec(&last_tx, &first_tx); + if (r == 0) + r = 0.0001; + if (t == 0) + t = 0.0001; + (void)printf(" %.1f packets/sec sent, " + " %.1f packets/sec received\n", + ntransmitted/t, nreceived/r); + } + } +} + + +/* + * Print statistics when SIGINFO is received. + */ +/* ARGSUSED */ +static void +prtsig(int dummy) +{ + + summary(0); +#ifndef SIGINFO + (void)signal(SIGQUIT, prtsig); +#endif +} + + +/* + * On the first SIGINT, allow any outstanding packets to dribble in + */ +static void +prefinish(int dummy) +{ + if (lastrcvd /* quit now if caught up */ + || nreceived == 0) /* or if remote is dead */ + finish(0); + + (void)signal(dummy, finish); /* do this only the 1st time */ + + if (npackets > ntransmitted) /* let the normal limit work */ + npackets = ntransmitted; +} + +/* + * Print statistics and give up. + */ +/* ARGSUSED */ +static void +finish(int dummy) +{ +#ifdef SIGINFO + (void)signal(SIGINFO, SIG_DFL); +#else + (void)signal(SIGQUIT, SIG_DFL); +#endif + + summary(1); + exit(nreceived > 0 ? 0 : 2); +} + + +static int /* 0=do not print it */ +ck_pr_icmph(struct icmp *icp, + struct sockaddr_in *from, + int cc, + int override) /* 1=override VERBOSE if interesting */ +{ + int hlen; + struct ip ipb, *ip = &ipb; + struct icmp icp2b, *icp2 = &icp2b; + int res; + + if (pingflags & F_VERBOSE) { + res = 1; + jiggle_flush(1); + } else { + res = 0; + } + + (void) memcpy(ip, icp->icmp_data, sizeof(*ip)); + hlen = ip->ip_hl << 2; + if (ip->ip_p == IPPROTO_ICMP + && hlen + 6 <= cc) { + (void) memcpy(icp2, &icp->icmp_data[hlen], sizeof(*icp2)); + if (icp2->icmp_id == ident) { + /* remember to clear route cached in kernel + * if this non-Echo-Reply ICMP message was for one + * of our packets. + */ + clear_cache.tv_sec = 0; + + if (!res && override + && (pingflags & (F_QUIET|F_SEMI_QUIET)) == 0) { + jiggle_flush(1); + (void)printf("%d bytes from %s: ", + cc, pr_addr(&from->sin_addr)); + res = 1; + } + } + } + + return res; +} + + +/* + * Print a descriptive string about an ICMP header other than an echo reply. + */ +static int /* 0=printed nothing */ +pr_icmph(struct icmp *icp, + struct sockaddr_in *from, + int cc) +{ + switch (icp->icmp_type ) { + case ICMP_UNREACH: + if (!ck_pr_icmph(icp, from, cc, 1)) + return 0; + switch (icp->icmp_code) { + case ICMP_UNREACH_NET: + (void)printf("Destination Net Unreachable"); + break; + case ICMP_UNREACH_HOST: + (void)printf("Destination Host Unreachable"); + break; + case ICMP_UNREACH_PROTOCOL: + (void)printf("Destination Protocol Unreachable"); + break; + case ICMP_UNREACH_PORT: + (void)printf("Destination Port Unreachable"); + break; + case ICMP_UNREACH_NEEDFRAG: + (void)printf("frag needed and DF set. Next MTU=%d", + ntohs(icp->icmp_nextmtu)); + break; + case ICMP_UNREACH_SRCFAIL: + (void)printf("Source Route Failed"); + break; + case ICMP_UNREACH_NET_UNKNOWN: + (void)printf("Unreachable unknown net"); + break; + case ICMP_UNREACH_HOST_UNKNOWN: + (void)printf("Unreachable unknown host"); + break; + case ICMP_UNREACH_ISOLATED: + (void)printf("Unreachable host isolated"); + break; + case ICMP_UNREACH_NET_PROHIB: + (void)printf("Net prohibited access"); + break; + case ICMP_UNREACH_HOST_PROHIB: + (void)printf("Host prohibited access"); + break; + case ICMP_UNREACH_TOSNET: + (void)printf("Bad TOS for net"); + break; + case ICMP_UNREACH_TOSHOST: + (void)printf("Bad TOS for host"); + break; + case 13: + (void)printf("Communication prohibited"); + break; + case 14: + (void)printf("Host precedence violation"); + break; + case 15: + (void)printf("Precedence cutoff"); + break; + default: + (void)printf("Bad Destination Unreachable Code: %d", + icp->icmp_code); + break; + } + /* Print returned IP header information */ + pr_retip(icp, cc); + break; + + case ICMP_SOURCEQUENCH: + if (!ck_pr_icmph(icp, from, cc, 1)) + return 0; + (void)printf("Source Quench"); + pr_retip(icp, cc); + break; + + case ICMP_REDIRECT: + if (!ck_pr_icmph(icp, from, cc, 1)) + return 0; + switch (icp->icmp_code) { + case ICMP_REDIRECT_NET: + (void)printf("Redirect Network"); + break; + case ICMP_REDIRECT_HOST: + (void)printf("Redirect Host"); + break; + case ICMP_REDIRECT_TOSNET: + (void)printf("Redirect Type of Service and Network"); + break; + case ICMP_REDIRECT_TOSHOST: + (void)printf("Redirect Type of Service and Host"); + break; + default: + (void)printf("Redirect--Bad Code: %d", icp->icmp_code); + break; + } + (void)printf(" New router addr: %s", + pr_addr(&icp->icmp_hun.ih_gwaddr)); + pr_retip(icp, cc); + break; + + case ICMP_ECHO: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Echo Request: ID=%d seq=%d", + ntohs(icp->icmp_id), ntohs(icp->icmp_seq)); + break; + + case ICMP_ECHOREPLY: + /* displaying other's pings is too noisey */ +#if 0 + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Echo Reply: ID=%d seq=%d", + ntohs(icp->icmp_id), ntohs(icp->icmp_seq)); + break; +#else + return 0; +#endif + + case ICMP_ROUTERADVERT: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Router Discovery Advert"); + break; + + case ICMP_ROUTERSOLICIT: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Router Discovery Solicit"); + break; + + case ICMP_TIMXCEED: + if (!ck_pr_icmph(icp, from, cc, 1)) + return 0; + switch (icp->icmp_code ) { + case ICMP_TIMXCEED_INTRANS: + (void)printf("Time To Live exceeded"); + break; + case ICMP_TIMXCEED_REASS: + (void)printf("Frag reassembly time exceeded"); + break; + default: + (void)printf("Time exceeded, Bad Code: %d", + icp->icmp_code); + break; + } + pr_retip(icp, cc); + break; + + case ICMP_PARAMPROB: + if (!ck_pr_icmph(icp, from, cc, 1)) + return 0; + (void)printf("Parameter problem: pointer = 0x%02x", + icp->icmp_hun.ih_pptr); + pr_retip(icp, cc); + break; + + case ICMP_TSTAMP: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Timestamp"); + break; + + case ICMP_TSTAMPREPLY: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Timestamp Reply"); + break; + + case ICMP_IREQ: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Information Request"); + break; + + case ICMP_IREQREPLY: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Information Reply"); + break; + + case ICMP_MASKREQ: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Address Mask Request"); + break; + + case ICMP_MASKREPLY: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Address Mask Reply"); + break; + + default: + if (!ck_pr_icmph(icp, from, cc, 0)) + return 0; + (void)printf("Bad ICMP type: %d", icp->icmp_type); + if (pingflags & F_VERBOSE) + pr_iph(icp, cc); + } + + return 1; +} + + +/* + * Print an IP header with options. + */ +static void +pr_iph(struct icmp *icp, + int cc) +{ + int hlen; + u_char *cp; + struct ip ipb, *ip = &ipb; + + (void) memcpy(ip, icp->icmp_data, sizeof(*ip)); + + hlen = ip->ip_hl << 2; + cp = (u_char *) &icp->icmp_data[20]; /* point to options */ + + (void)printf("\n Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n"); + (void)printf(" %1x %1x %02x %04x %04x", + ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); + (void)printf(" %1x %04x", + ((ip->ip_off)&0xe000)>>13, (ip->ip_off)&0x1fff); + (void)printf(" %02x %02x %04x", + ip->ip_ttl, ip->ip_p, ip->ip_sum); + (void)printf(" %15s ", + inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); + (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); + /* dump any option bytes */ + while (hlen-- > 20 && cp < (u_char*)icp+cc) { + (void)printf("%02x", *cp++); + } +} + +/* + * Print an ASCII host address starting from a string of bytes. + */ +static void +pr_saddr(u_char *cp) +{ + n_long l; + struct in_addr addr; + + l = (u_char)*++cp; + l = (l<<8) + (u_char)*++cp; + l = (l<<8) + (u_char)*++cp; + l = (l<<8) + (u_char)*++cp; + addr.s_addr = htonl(l); + (void)printf("\t%s", (l == 0) ? "0.0.0.0" : pr_addr(&addr)); +} + + +/* + * Return an ASCII host address + * as a dotted quad and optionally with a hostname + */ +static char * +pr_addr(struct in_addr *addr) /* in network order */ +{ + struct hostent *hp; + static char buf[MAXHOSTNAMELEN+4+16+1]; + + if ((pingflags & F_NUMERIC) + || !(hp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET))) { + (void)snprintf(buf, sizeof(buf), "%s", inet_ntoa(*addr)); + } else { + (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, + inet_ntoa(*addr)); + } + + return buf; +} + +/* + * Dump some info on a returned (via ICMP) IP packet. + */ +static void +pr_retip(struct icmp *icp, + int cc) +{ + int hlen; + u_char *cp; + struct ip ipb, *ip = &ipb; + + (void) memcpy(ip, icp->icmp_data, sizeof(*ip)); + + if (pingflags & F_VERBOSE) + pr_iph(icp, cc); + + hlen = ip->ip_hl << 2; + cp = (u_char *) &icp->icmp_data[hlen]; + + if (ip->ip_p == IPPROTO_TCP) { + if (pingflags & F_VERBOSE) + (void)printf("\n TCP: from port %u, to port %u", + (*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3))); + } else if (ip->ip_p == IPPROTO_UDP) { + if (pingflags & F_VERBOSE) + (void)printf("\n UDP: from port %u, to port %u", + (*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3))); + } else if (ip->ip_p == IPPROTO_ICMP) { + struct icmp icp2; + (void) memcpy(&icp2, cp, sizeof(icp2)); + if (icp2.icmp_type == ICMP_ECHO) { + if (pingflags & F_VERBOSE) + (void)printf("\n ID=%u icmp_seq=%u", + ntohs((u_int16_t)icp2.icmp_id), + ntohs((u_int16_t)icp2.icmp_seq)); + else + (void)printf(" for icmp_seq=%u", + ntohs((u_int16_t)icp2.icmp_seq)); + } + } +} + +static void +fill(void) +{ + int i, j, k; + char *cp; + int pat[16]; + + for (cp = fill_pat; *cp != '\0'; cp++) { + if (!isxdigit((unsigned char)*cp)) + break; + } + if (cp == fill_pat || *cp != '\0' || (cp-fill_pat) > 16*2) { + (void)fflush(stdout); + errx(1, "\"-p %s\": patterns must be specified with" + " 1-32 hex digits\n", + fill_pat); + } + + i = sscanf(fill_pat, + "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", + &pat[0], &pat[1], &pat[2], &pat[3], + &pat[4], &pat[5], &pat[6], &pat[7], + &pat[8], &pat[9], &pat[10], &pat[11], + &pat[12], &pat[13], &pat[14], &pat[15]); + + for (k = phdrlen, j = 0; k <= datalen; k++) { + opack_icmp.icmp_data[k] = pat[j]; + if (++j >= i) + j = 0; + } + + if (!(pingflags & F_QUIET)) { + (void)printf("PATTERN: 0x"); + for (j=0; j>24; + } +} + + +static void +gethost(const char *arg, + const char *name, + struct sockaddr_in *sa, + char *realname, + int realname_len) +{ + struct hostent *hp; + + (void)memset(sa, 0, sizeof(*sa)); + sa->sin_family = AF_INET; + sa->sin_len = sizeof(struct sockaddr_in); + + /* If it is an IP address, try to convert it to a name to + * have something nice to display. + */ + if (inet_aton(name, &sa->sin_addr) != 0) { + if (realname) { + if (pingflags & F_NUMERIC) + hp = 0; + else + hp = gethostbyaddr((char *)&sa->sin_addr, + sizeof(sa->sin_addr), + AF_INET); + (void)strlcpy(realname, hp ? hp->h_name : name, + realname_len); + } + return; + } + + hp = gethostbyname(name); + if (!hp) + errx(1, "Cannot resolve \"%s\" (%s)",name,hstrerror(h_errno)); + + if (hp->h_addrtype != AF_INET) + errx(1, "%s only supported with IP", arg); + + (void)memcpy(&sa->sin_addr, hp->h_addr, sizeof(sa->sin_addr)); + + if (realname) + (void)strlcpy(realname, hp->h_name, realname_len); +} + + +static void +usage(void) +{ +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +#define IPSECOPT "\n [-E policy] " +#else +#define IPSECOPT "\n [-AE] " +#endif /*IPSEC_POLICY_IPSEC*/ +#else +#define IPSECOPT "" +#endif /*IPSEC*/ + + (void)fprintf(stderr, "usage: \n" + "%s [-aCDdfLnoPQqRrv] [-c count] [-g gateway] [-h host]" + " [-I addr] [-i interval]\n" + " [-l preload] [-p pattern] [-s size] [-T ttl] [-t tos]" + " [-w maxwait] " IPSECOPT "host\n", + getprogname()); + exit(1); +} diff --git a/sbin/ping/ping_hostops.c b/sbin/ping/ping_hostops.c new file mode 100644 index 000000000..72b1f82fb --- /dev/null +++ b/sbin/ping/ping_hostops.c @@ -0,0 +1,53 @@ +/* $NetBSD: ping_hostops.c,v 1.2 2011/03/11 09:59:56 pooka Exp $ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: ping_hostops.c,v 1.2 2011/03/11 09:59:56 pooka Exp $"); +#endif /* !lint */ + +#include +#include +#include + +#include +#include + +#include "prog_ops.h" + +const struct prog_ops prog_ops = { + .op_socket = socket, + .op_setsockopt = setsockopt, + .op_shutdown = shutdown, + .op_poll = poll, + .op_recvfrom = recvfrom, + .op_sendto = sendto, + .op_close = close, + .op_getuid = getuid, + .op_setuid = setuid, +}; diff --git a/sbin/ping/ping_rumpops.c b/sbin/ping/ping_rumpops.c new file mode 100644 index 000000000..7e2f21144 --- /dev/null +++ b/sbin/ping/ping_rumpops.c @@ -0,0 +1,58 @@ +/* $NetBSD: ping_rumpops.c,v 1.2 2011/03/11 09:59:56 pooka Exp $ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: ping_rumpops.c,v 1.2 2011/03/11 09:59:56 pooka Exp $"); +#endif /* !lint */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "prog_ops.h" + +const struct prog_ops prog_ops = { + .op_init = rumpclient_init, + + .op_socket = rump_sys_socket, + .op_setsockopt= rump_sys_setsockopt, + .op_shutdown = rump_sys_shutdown, + .op_poll = rump_sys_poll, + .op_sendto = rump_sys_sendto, + .op_recvfrom = rump_sys_recvfrom, + .op_close = rump_sys_close, + .op_getuid = rump_sys_getuid, + .op_setuid = rump_sys_setuid, +}; diff --git a/sbin/ping/prog_ops.h b/sbin/ping/prog_ops.h new file mode 100644 index 000000000..ccc5a7066 --- /dev/null +++ b/sbin/ping/prog_ops.h @@ -0,0 +1,79 @@ +/* $NetBSD: prog_ops.h,v 1.3 2011/03/11 09:59:56 pooka Exp $ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PROG_OPS_H_ +#define _PROG_OPS_H_ + +#include + +#ifndef CRUNCHOPS +struct prog_ops { + int (*op_init)(void); + + int (*op_socket)(int, int, int); + int (*op_setsockopt)(int, int, int, const void *, socklen_t); + int (*op_shutdown)(int, int); + + int (*op_poll)(struct pollfd *, nfds_t, int); + + ssize_t (*op_recvfrom)(int, void *, size_t, int, + struct sockaddr *, socklen_t *); + ssize_t (*op_sendto)(int, const void *, size_t, int, + const struct sockaddr *, socklen_t); + + int (*op_close)(int); + + uid_t (*op_getuid)(void); + int (*op_setuid)(uid_t); +}; +extern const struct prog_ops prog_ops; + +#define prog_init prog_ops.op_init +#define prog_socket prog_ops.op_socket +#define prog_setsockopt prog_ops.op_setsockopt +#define prog_shutdown prog_ops.op_shutdown +#define prog_poll prog_ops.op_poll +#define prog_recvfrom prog_ops.op_recvfrom +#define prog_sendto prog_ops.op_sendto +#define prog_close prog_ops.op_close +#define prog_getuid prog_ops.op_getuid +#define prog_setuid prog_ops.op_setuid +#else +#define prog_init ((int (*)(void))NULL) +#define prog_socket socket +#define prog_setsockopt setsockopt +#define prog_shutdown shutdown +#define prog_poll poll +#define prog_recvfrom recvfrom +#define prog_sendto sendto +#define prog_close close +#define prog_getuid getuid +#define prog_setuid setuid +#endif + +#endif /* _PROG_OPS_H_ */ diff --git a/sys/net/Makefile b/sys/net/Makefile index 751f0734c..3870aabca 100644 --- a/sys/net/Makefile +++ b/sys/net/Makefile @@ -6,6 +6,8 @@ INCSDIR= /usr/include/net INCS= ethertypes.h \ if_ether.h \ + radix.h \ + route.h \ \ \ \ diff --git a/sys/netinet/Makefile b/sys/netinet/Makefile index 26e610888..d8bf7e6a6 100644 --- a/sys/netinet/Makefile +++ b/sys/netinet/Makefile @@ -7,8 +7,10 @@ INCS= \ in_systm.h \ \ ip.h \ + ip_icmp.h \ + ip_var.h \ tcp.h \ - \ + udp.h udp_var.h \ .if !defined(__MINIX) diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h new file mode 100644 index 000000000..2cdfdbbb9 --- /dev/null +++ b/sys/netinet/ip_icmp.h @@ -0,0 +1,253 @@ +/* $NetBSD: ip_icmp.h,v 1.33 2011/12/24 20:18:54 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_IP_ICMP_H_ +#define _NETINET_IP_ICMP_H_ + + +/* + * Interface Control Message Protocol Definitions. + * Per RFC 792, September 1981. + */ + +/* + * Internal of an ICMP Router Advertisement + */ +struct icmp_ra_addr { + u_int32_t ira_addr; + u_int32_t ira_preference; +} __packed; + +/* + * Structure of an icmp header. + */ +struct icmp { + u_int8_t icmp_type; /* type of message, see below */ + u_int8_t icmp_code; /* type sub code */ + u_int16_t icmp_cksum; /* ones complement cksum of struct */ + union { + u_int8_t ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + n_short icd_id; + n_short icd_seq; + } ih_idseq __packed; + int32_t ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu { + n_short ipm_void; + n_short ipm_nextmtu; + } ih_pmtu __packed; + struct ih_rtradv { + u_int8_t irt_num_addrs; + u_int8_t irt_wpa; + u_int16_t irt_lifetime; + } ih_rtradv __packed; + } icmp_hun /* XXX __packed ??? */; +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime + union { + struct id_ts { + n_time its_otime; + n_time its_rtime; + n_time its_ttime; + } id_ts __packed; + struct id_ip { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip /* XXX: __packed ??? */; + struct icmp_ra_addr id_radv; + u_int32_t id_mask; + int8_t id_data[1]; + } icmp_dun /* XXX __packed ??? */; +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_radv icmp_dun.id_mask +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data +}; + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enought to contain the returned ip header. + * Only then can we do the check to see if 64 bits of packet + * data have been returned, since we need to check the returned + * ip header length. + */ +#define ICMP_MINLEN 8 /* abs minimum */ +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMP_MASKLEN 12 /* address mask */ +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ + +/* + * Definition of type and code field values. + */ +#define ICMP_ECHOREPLY 0 /* echo reply */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_ADMIN_PROHIBIT 13 /* communication + administratively + prohibited */ +#define ICMP_UNREACH_HOST_PREC 14 /* host precedence + violation */ +#define ICMP_UNREACH_PREC_CUTOFF 15 /* precedence cutoff */ +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ +#define ICMP_REDIRECT 5 /* shorter route, codes: */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ +#define ICMP_ALTHOSTADDR 6 /* alternative host address */ +#define ICMP_ECHO 8 /* echo service */ +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#define ICMP_ROUTERADVERT_NORMAL 0 +#define ICMP_ROUTERADVERT_NOROUTE 16 +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_PARAMPROB_ERRATPTR 0 +#define ICMP_PARAMPROB_OPTABSENT 1 +#define ICMP_PARAMPROB_LENGTH 2 +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_IREQ 15 /* information request */ +#define ICMP_IREQREPLY 16 /* information reply */ +#define ICMP_MASKREQ 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ +#define ICMP_TRACEROUTE 30 /* traceroute */ +#define ICMP_DATACONVERR 31 /* data conversion error */ +#define ICMP_MOBILE_REDIRECT 32 /* mobile redirect */ +#define ICMP_IPV6_WHEREAREYOU 33 /* ipv6 where are you */ +#define ICMP_IPV6_IAMHERE 34 /* ipv6 i am here */ +#define ICMP_MOBILE_REGREQUEST 35 /* mobile registration req */ +#define ICMP_MOBILE_REGREPLY 36 /* mobile registration reply */ +#define ICMP_SKIP 39 /* SKIP */ +#define ICMP_PHOTURIS 40 /* security */ +#define ICMP_PHOTURIS_UNKNOWN_INDEX 0 /* unknown sec index */ +#define ICMP_PHOTURIS_AUTH_FAILED 1 /* auth failed */ +#define ICMP_PHOTURIS_DECOMPRESS_FAILED 2 /* decompress failed */ +#define ICMP_PHOTURIS_DECRYPT_FAILED 3 /* decrypt failed */ +#define ICMP_PHOTURIS_NEED_AUTHN 4 /* no authentication */ +#define ICMP_PHOTURIS_NEED_AUTHZ 5 /* no authorization */ + +#define ICMP_MAXTYPE 40 + +#ifdef ICMP_STRINGS +static const char *icmp_type[] = { + "echoreply", "unassigned_1", "unassigned_2", "unreach", + "sourcequench", "redirect", "althostaddr", "unassigned_7", + "echo", "routeradvert", "routersolicit", "timxceed", + "paramprob", "tstamp", "tstampreply", "ireq", + "ireqreply", "maskreq", "maskreply", "reserved_19", + "reserved_20", "reserved_21", "reserved_22", "reserved_23", + "reserved_24", "reserved_25", "reserved_26", "reserved_27", + "reserved_28", "reserved_29", "traceroute", "dataconverr", + "mobile_redirect", "ipv6_whereareyou", "ipv6_iamhere", + "mobile_regrequest", "mobile_regreply", "reserved_37", + "reserved_38", "skip", "photuris", NULL +}; +static const char *icmp_code_none[] = { "none", NULL }; +static const char *icmp_code_unreach[] = { + "net", "host", "oprt", "needfrag", "srcfail", "net_unknown", + "host_unknown", "isolated", "net_prohib", "host_prohib", + "tosnet", "toshost", "admin_prohibit", "host_prec", "prec_cutoff", NULL +}; +static const char *icmp_code_redirect[] = { + "net", "host", "tosnet", "toshost", NULL +}; +static const char *icmp_code_routeradvert[] = { + "normal", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "noroute", NULL +}; +static const char *icmp_code_timxceed[] = { + "intrans", "reass", NULL +}; +static const char *icmp_code_paramprob[] = { + "erratptr", "optabsent", "length", NULL +}; +static const char *icmp_code_photuris[] = { + "unknown_index", "auth_failed", "decompress_failed", + "decrypt_failed", "need_authn", "need_authz", NULL +}; +#endif + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#ifdef _KERNEL +void icmp_error(struct mbuf *, int, int, n_long, int); +void icmp_mtudisc(struct icmp *, struct in_addr); +void icmp_input(struct mbuf *, ...); +void icmp_init(void); +void icmp_reflect(struct mbuf *); +void icmp_send(struct mbuf *, struct mbuf *); +int icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t); + +void icmp_mtudisc_callback_register(void (*)(struct in_addr)); +int icmp_ratelimit(const struct in_addr *, const int, const int); +#endif + + +#endif /* !_NETINET_IP_ICMP_H_ */ diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 68e48faac..93e7e707a 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -24,7 +24,7 @@ SUBDIR= \ \ rdate \ \ - \ + traceroute \ \ \ unlink user \ diff --git a/usr.sbin/traceroute/CHANGES b/usr.sbin/traceroute/CHANGES new file mode 100644 index 000000000..0fadff055 --- /dev/null +++ b/usr.sbin/traceroute/CHANGES @@ -0,0 +1,149 @@ +$NetBSD: CHANGES,v 1.2 2011/09/11 01:06:26 christos Exp $ +@(#) Id: CHANGES,v 1.23 2000/12/14 06:53:11 leres Exp (LBL) + +v1.4 Wed Dec 13 22:50:35 PST 2000 + +- Add an option to use icmp echo instead of udp datagrams. + +- Add HPUX and Linux support. + +- Handle hex argument values as suggested by John Hawkinson + (jhawk@mit.edu) + +- Added flags to set the first ttl and to set the don't fragment bit. + +- Add a local autoconf macro to check for routines in libraries; the + autoconf version is broken (it only puts the library name in the + cache variable name). Thanks to John Hawkinson. + +- Add a local autoconf macro to check for types; the autoconf version + is broken (it uses grep instead of actually compiling a code fragment). + +- Attempt to detect "egcs" versions of gcc. + +- Fix problems caused by savestr(). + +- Detect when there are more interfaces than we can deal with. Thanks + to Guy Harris guy@netapp.com. + +- Accommodate changes made to FreeBSD 3.2-RELEASE network headers files. + +- The ip header offset needs to be byte swapped under Solaris on the + intel as well. Reported by John McDermott (jjm@jkintl.com) Also byte + ip length and offset for linux. + +- In wait_for_reply(), use passed socket instead of global one. Thanks + to Richard Kettlewell (richard.kettlewell@kewill.com) + +- Check for IFF_LOOPBACK as a define or an enum (concession to linux). + Reported by Robert Bihlmeyer (robbe@orcus.priv.at) + +- Increase size of SIOCGIFCONF buffer to accommodate systems with lots + of virtual interfaces. Ignore sun virtual interfaces. Suggested by + Ian Donaldson (iand@aone.com.au) + +- Always calculate icmp checksums when using -I. Reported by Soumen + (sbiswas@novell.com) + +- Documentation fix for description of -p. Thanks to Jeffrey C Honig + (jch@bsdi.com) + +- Enable ip checksums for Solaris 2.6 and higher (since they seem to + work correctly now). + +- Avoid problems when broken routers return 0.0.0.0 as their source + address. Thanks to John Hawkinson (jhawk@bbnplanet.com) + +- Canonicalize hostname if gethostname() doesn't return a domain. + +- Add -z flag (pause msecs) to allow optional pause between probes. + Suggested by Dave Morrison (drmorris@uplanet.com) + +- Fix max packet length test. + +- Use "/dev/null" instead of "." for file descriptor fodder. + Suggested by Tim Robbins (fyre@box3n.gumbynet.org) + +- Watch for a NULL argv[0]. Suggested by Tim Robbins. + +- Be careful with hostname legnths. + +- Print RFC1191 Path MTU Discovery value on "needfrag" unreachables. + +- Limit port size to 16 bits. Suggested by Tim Robbins. + +- Limit wait time to 24 hours. + +- Modified linux specific struct ipovly definition to avoid problems + with 64 bit systems. Problem reported by Uros Prestor + (uros@turbolinux.com) + +- Use kernel routing tables to determine correct source address. + Three styles are supported: bsd/socket, solaris/mib and linux. + +- Fix configure to recognize older versions of Solaris. + +v1.3.2 Thu Sep 26 18:06:16 PDT 1996 + +- Rewrite source routing code to eliminate a number of problems on + systems using raw ip options. Also pad options with a noop so gateway + addresses are aligned. + +- Don't call inet_ntoa() twice in the same printf(). Thanks to NetBSD + via Bill Fenner (fenner@parc.xerox.com) + +- Decode "administratively prohibited filter" icmp code and print + numeric value for unknown codes. Thanks to Bill Fenner. + +v1.3.1 Wed Sep 18 21:08:16 PDT 1996 + +- Some systems (e.g. AIX) need sys/select.h. Thanks to Brett Hogden + (hogden@rge.com) + +- Byte swap ip header length under Solaris. (This has no effect on the + sparc but is required on the i386.) + +- Made optional packet length control total size of packet. + +v1.3 Mon Sep 16 14:55:44 PDT 1996 + +- Overrun buffer security fixes. Thanks to Bill Fenner + (fenner@parc.xerox.com) + +- Wait for response packet relative to start of probe. Thanks to Bill + Fenner. + +- Fix bug that prevented changing the packet size. Thanks to Gregory + Decker (gdecker@nate.dcrt.nih.gov) + +- Add support for RAW_OPTIONS (e.g. 4.4 BSD systems such as BSD/OS and + FreeBSD) thanks to Jeffrey C Honig (jch@bsdi.com) + +- Remove ip header byte swap fix from v1.2; most kernels swap the ip + header length in the kernel (and it causes OSF3 to crash). + +- Fix to not exit when the number of probes is set to 1 (i.e. "-q 1") + +- Improve autoconf configuration. + +v1.2 Tue Oct 17 23:50:05 PDT 1995 + +- Convert to autoconf and ansify. + +- Byte swap ip header length for little endian machines. Fix thanks to + Y Badri (yb@greybox.demon.co.uk). + +v1.1 Thu Jun 15 02:32:55 PDT 1995 + +- Check for too many arguments. + +- Recode to make timing of packet's round trip more obvious and to + tighten up code. + +- Ifdef IP_OPTIONS code. + +- Display time in microseconds. + +v1.0 Tue Feb 28 23:50:05 PDT 1989 + +- Initial public release. diff --git a/usr.sbin/traceroute/Makefile b/usr.sbin/traceroute/Makefile new file mode 100644 index 000000000..4685ef6b0 --- /dev/null +++ b/usr.sbin/traceroute/Makefile @@ -0,0 +1,29 @@ +# $NetBSD: Makefile,v 1.19 2011/09/11 01:06:26 christos Exp $ + +USE_FORT?= yes # network client + +RUMPPRG=traceroute +MAN= traceroute.8 + +CPPFLAGS+=-DHAVE_MALLOC_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SOCKIO_H=1 +CPPFLAGS+=-DHAVE_STRERROR=1 -DHAVE_SETLINEBUF=1 -DHAVE_SOCKADDR_SA_LEN=1 +CPPFLAGS+=-DHAVE_RAW_OPTIONS=1 +CPPFLAGS+=-DHAVE_ICMP_NEXTMTU=1 + +#CPPFLAGS+=-DIPSEC +#LDADD+= -lipsec +#DPADD+= ${LIBIPSEC} + +BINOWN= root +BINMODE=4555 + +SRCS= traceroute.c ifaddrlist.c +SRCS+= version.c as.c + +.PATH: ${.CURDIR}/../../lib/libc/net +RUMPSRCS= getifaddrs.c +CPPFLAGS+= -DRUMP_ACTION + +AWKS= median.awk mean.awk + +.include diff --git a/usr.sbin/traceroute/as.c b/usr.sbin/traceroute/as.c new file mode 100644 index 000000000..380837271 --- /dev/null +++ b/usr.sbin/traceroute/as.c @@ -0,0 +1,224 @@ +/* $NetBSD: as.c,v 1.4 2011/05/10 01:52:49 christos Exp $ */ + +/* + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Brown. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "as.h" + +#define DEFAULT_AS_SERVER "whois.radb.net" +#undef AS_DEBUG_FILE + +struct aslookup { + FILE *as_f; +#ifdef AS_DEBUG_FILE + FILE *as_debug; +#endif /* AS_DEBUG_FILE */ +}; + +void * +as_setup(const char *server) +{ + struct aslookup *asn; + struct addrinfo hints, *res0, *res; + FILE *f; + int s, error; + + s = -1; + if (server == NULL) + server = getenv("RA_SERVER"); + if (server == NULL) + server = DEFAULT_AS_SERVER; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(server, "whois", &hints, &res0); + if (error == EAI_SERVICE) { + warnx("warning: whois/tcp service not found"); + error = getaddrinfo(server, "43", &hints, &res0); + } + + if (error != 0) { + warnx("%s: %s", server, gai_strerror(error)); + return (NULL); + } + + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s < 0) + continue; + if (connect(s, res->ai_addr, res->ai_addrlen) >= 0) + break; + close(s); + s = -1; + } + freeaddrinfo(res0); + if (s < 0) { + warn("connect"); + return (NULL); + } + + f = fdopen(s, "r+"); + (void)fprintf(f, "!!\n"); + (void)fflush(f); + + asn = malloc(sizeof(struct aslookup)); + if (asn == NULL) + (void)fclose(f); + else + asn->as_f = f; + +#ifdef AS_DEBUG_FILE + if (asn) { + asn->as_debug = fopen(AS_DEBUG_FILE, "w"); + if (asn->as_debug) { + (void)fprintf(asn->as_debug, ">> !!\n"); + (void)fflush(asn->as_debug); + } + } +#endif /* AS_DEBUG_FILE */ + + return (asn); +} + +unsigned int +as_lookup(void *_asn, char *addr, sa_family_t family) +{ + struct aslookup *asn = _asn; + char buf[1024]; + unsigned int as; + int rc, dlen, plen; + + as = 0; + rc = dlen = 0; + plen = (family == AF_INET6) ? 128 : 32; + (void)fprintf(asn->as_f, "!r%s/%d,l\n", addr, plen); + (void)fflush(asn->as_f); + +#ifdef AS_DEBUG_FILE + if (asn->as_debug) { + (void)fprintf(asn->as_debug, ">> !r%s/%d,l\n", addr, plen); + (void)fflush(asn->as_debug); + } +#endif /* AS_DEBUG_FILE */ + + while (fgets(buf, sizeof(buf), asn->as_f) != NULL) { + buf[sizeof(buf) - 1] = '\0'; + +#ifdef AS_DEBUG_FILE + if (asn->as_debug) { + (void)fprintf(asn->as_debug, "<< %s", buf); + (void)fflush(asn->as_debug); + } +#endif /* AS_DEBUG_FILE */ + + if (rc == 0) { + rc = buf[0]; + switch (rc) { + case 'A': + /* A - followed by # bytes of answer */ + sscanf(buf, "A%d\n", &dlen); +#ifdef AS_DEBUG_FILE + if (asn->as_debug) { + (void)fprintf(asn->as_debug, + "dlen: %d\n", dlen); + (void)fflush(asn->as_debug); + } +#endif /* AS_DEBUG_FILE */ + break; + case 'C': + case 'D': + case 'E': + case 'F': + /* C - no data returned */ + /* D - key not found */ + /* E - multiple copies of key */ + /* F - some other error */ + break; + } + if (rc == 'A') + /* skip to next input line */ + continue; + } + + if (dlen == 0) + /* out of data, next char read is end code */ + rc = buf[0]; + if (rc != 'A') + /* either an error off the bat, or a done code */ + break; + + /* data received, thank you */ + dlen -= strlen(buf); + + /* origin line is the interesting bit */ + if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) { + sscanf(buf + 7, " AS%u", &as); +#ifdef AS_DEBUG_FILE + if (asn->as_debug) { + (void)fprintf(asn->as_debug, "as: %d\n", as); + (void)fflush(asn->as_debug); + } +#endif /* AS_DEBUG_FILE */ + } + } + + return (as); +} + +void +as_shutdown(void *_asn) +{ + struct aslookup *asn = _asn; + + (void)fprintf(asn->as_f, "!q\n"); + (void)fclose(asn->as_f); + +#ifdef AS_DEBUG_FILE + if (asn->as_debug) { + (void)fprintf(asn->as_debug, ">> !q\n"); + (void)fclose(asn->as_debug); + } +#endif /* AS_DEBUG_FILE */ + + free(asn); +} diff --git a/usr.sbin/traceroute/as.h b/usr.sbin/traceroute/as.h new file mode 100644 index 000000000..324b89f58 --- /dev/null +++ b/usr.sbin/traceroute/as.h @@ -0,0 +1,34 @@ +/* $NetBSD: as.h,v 1.4 2011/05/10 01:52:49 christos Exp $ */ + +/* + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Brown. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +void *as_setup(const char *); +unsigned int as_lookup(void *, char *, sa_family_t); +void as_shutdown(void *); diff --git a/usr.sbin/traceroute/gnuc.h b/usr.sbin/traceroute/gnuc.h new file mode 100644 index 000000000..aadb5fa01 --- /dev/null +++ b/usr.sbin/traceroute/gnuc.h @@ -0,0 +1,36 @@ +/* $NetBSD: gnuc.h,v 1.2 2002/07/06 21:51:49 wiz Exp $ */ + +/* @(#) Header: gnuc.h,v 1.3 95/10/09 02:47:01 leres Exp (LBL) */ + +/* inline foo */ +#ifdef __GNUC__ +#define inline __inline +#else +#define inline +#endif + +/* + * Handle new and old "dead" routine prototypes + * + * For example: + * + * __dead void foo(void) __attribute__((volatile)); + * + */ +#ifdef __GNUC__ +#ifndef __dead +#define __dead volatile +#endif +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +#ifndef __attribute__ +#define __attribute__(args) +#endif +#endif +#else +#ifndef __dead +#define __dead +#endif +#ifndef __attribute__ +#define __attribute__(args) +#endif +#endif diff --git a/usr.sbin/traceroute/ifaddrlist.c b/usr.sbin/traceroute/ifaddrlist.c new file mode 100644 index 000000000..170f397b6 --- /dev/null +++ b/usr.sbin/traceroute/ifaddrlist.c @@ -0,0 +1,146 @@ +/* $NetBSD: ifaddrlist.c,v 1.10 2011/09/11 01:06:26 christos Exp $ */ + +/* + * Copyright (c) 1997, 1998, 1999, 2000 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static const char rcsid[] = + "@(#) Header: ifaddrlist.c,v 1.2 97/04/22 13:31:05 leres Exp (LBL)"; + "@(#) Id: ifaddrlist.c,v 1.9 2000/11/23 20:01:55 leres Exp (LBL)"; +#else +__RCSID("$NetBSD: ifaddrlist.c,v 1.10 2011/09/11 01:06:26 christos Exp $"); +#endif +#endif + +#include +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#include /* concession to AIX */ + +struct mbuf; +struct rtentry; + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gnuc.h" +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "ifaddrlist.h" + +/* Not all systems have IFF_LOOPBACK */ +#ifdef IFF_LOOPBACK +#define ISLOOPBACK(p) ((p)->ifa_flags & IFF_LOOPBACK) +#else +#define ISLOOPBACK(p) (strcmp((p)->ifa_name, "lo0") == 0) +#endif + +/* + * Return the interface list + */ +ssize_t +ifaddrlist(struct ifaddrlist **ipaddrp, char *errbuf, size_t buflen) +{ + struct sockaddr_in *sin; + struct ifaddrs *ifap = NULL, *ifa; + struct ifaddrlist *al = NULL, *nal; + size_t i = 0, maxal = 10; + + if (getifaddrs(&ifap) != 0) + goto out; + + if ((al = malloc(maxal * sizeof(*al))) == NULL) + goto out; + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + + /* Must be up */ + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + + /* + * Must not be a loopback address (127/8) + */ + sin = (struct sockaddr_in *)ifa->ifa_addr; + if (ISLOOPBACK(ifa)) + if (ntohl(sin->sin_addr.s_addr) == INADDR_LOOPBACK) + continue; + + if (i == maxal) { + maxal <<= 1; + if ((nal = realloc(al, maxal * sizeof(*al))) == NULL) + goto out; + al = nal; + } + + al[i].addr = sin->sin_addr.s_addr; + if ((al[i].device = strdup(ifa->ifa_name)) == NULL) + goto out; + i++; + } + if ((nal = realloc(al, i * sizeof(*al))) == NULL) + goto out; + freeifaddrs(ifap); + *ipaddrp = nal; + return (ssize_t)i; +out: + if (ifap) + freeifaddrs(ifap); + if (al) { + while (i > 0) + free(al[--i].device); + free(al); + } + (void)snprintf(errbuf, buflen, "%s: %s", __func__, strerror(errno)); + return -1; +} diff --git a/usr.sbin/traceroute/ifaddrlist.h b/usr.sbin/traceroute/ifaddrlist.h new file mode 100644 index 000000000..7e5427900 --- /dev/null +++ b/usr.sbin/traceroute/ifaddrlist.h @@ -0,0 +1,31 @@ +/* $NetBSD: ifaddrlist.h,v 1.3 2011/05/11 00:38:28 christos Exp $ */ + +/* + * Copyright (c) 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) Header: traceroute.h,v 1.1 97/01/04 19:33:33 leres Locked (LBL) + */ + +struct ifaddrlist { + uint32_t addr; + char *device; +}; + +ssize_t ifaddrlist(struct ifaddrlist **, char *, size_t); diff --git a/usr.sbin/traceroute/mean.awk b/usr.sbin/traceroute/mean.awk new file mode 100644 index 000000000..75cc421a6 --- /dev/null +++ b/usr.sbin/traceroute/mean.awk @@ -0,0 +1,14 @@ +#!/bin/awk -f +# $NetBSD: mean.awk,v 1.5 1997/10/04 16:31:29 christos Exp $ +/^ *[0-9]/ { + # print out the average time to each hop along a route. + tottime = 0; n = 0; + for (f = 5; f <= NF; ++f) { + if ($f == "ms") { + tottime += $(f - 1) + ++n + } + } + if (n > 0) + print $1, tottime/n, median +} diff --git a/usr.sbin/traceroute/median.awk b/usr.sbin/traceroute/median.awk new file mode 100644 index 000000000..672e1150e --- /dev/null +++ b/usr.sbin/traceroute/median.awk @@ -0,0 +1,31 @@ +#!/bin/awk -f +# $NetBSD: median.awk,v 1.5 1997/10/04 16:31:32 christos Exp $ +/^ *[0-9]/ { + # print out the median time to each hop along a route. + tottime = 0; n = 0; + for (f = 5; f <= NF; ++f) { + if ($f == "ms") { + ++n + time[n] = $(f - 1) + } + } + if (n > 0) { + # insertion sort the times to find the median + for (i = 2; i <= n; ++i) { + v = time[i]; j = i - 1; + while (time[j] > v) { + time[j+1] = time[j]; + j = j - 1; + if (j < 0) + break; + } + time[j+1] = v; + } + if (n > 1 && (n % 2) == 0) + median = (time[n/2] + time[(n/2) + 1]) / 2 + else + median = time[(n+1)/2] + + print $1, median + } +} diff --git a/usr.sbin/traceroute/prog_ops.h b/usr.sbin/traceroute/prog_ops.h new file mode 100644 index 000000000..9811d6f26 --- /dev/null +++ b/usr.sbin/traceroute/prog_ops.h @@ -0,0 +1,72 @@ +/* $NetBSD: prog_ops.h,v 1.1 2010/12/15 00:09:41 pooka Exp $ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PROG_OPS_H_ +#define _PROG_OPS_H_ + +#include +#include +#include + +struct prog_ops { + int (*op_init)(void); + + int (*op_socket)(int, int, int); + int (*op_setsockopt)(int, int, int, const void *, socklen_t); + int (*op_shutdown)(int, int); + + int (*op_poll)(struct pollfd *, nfds_t, int); + + ssize_t (*op_recvfrom)(int, void *, size_t, int, + struct sockaddr *, socklen_t *); + ssize_t (*op_sendto)(int, const void *, size_t, int, + const struct sockaddr *, socklen_t); + + int (*op_close)(int); + + int (*op_connect)(int, const struct sockaddr *, socklen_t); + int (*op_getsockname)(int, struct sockaddr *, socklen_t *); + + int (*op_sysctl)(const int *, u_int, void *, size_t *, + const void *, size_t); +}; +extern const struct prog_ops prog_ops; + +#define prog_init prog_ops.op_init +#define prog_socket prog_ops.op_socket +#define prog_setsockopt prog_ops.op_setsockopt +#define prog_shutdown prog_ops.op_shutdown +#define prog_poll prog_ops.op_poll +#define prog_recvfrom prog_ops.op_recvfrom +#define prog_sendto prog_ops.op_sendto +#define prog_close prog_ops.op_close +#define prog_connect prog_ops.op_connect +#define prog_getsockname prog_ops.op_getsockname +#define prog_sysctl prog_ops.op_sysctl + +#endif /* _PROG_OPS_H_ */ diff --git a/usr.sbin/traceroute/traceroute b/usr.sbin/traceroute/traceroute new file mode 100755 index 0000000000000000000000000000000000000000..d001d71a98e1879e32e46a3b5e0f4aa9515bd5df GIT binary patch literal 382374 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 z઼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 ^wMO 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 literal 0 HcmV?d00001 diff --git a/usr.sbin/traceroute/traceroute.8 b/usr.sbin/traceroute/traceroute.8 new file mode 100644 index 000000000..0ed6f2b59 --- /dev/null +++ b/usr.sbin/traceroute/traceroute.8 @@ -0,0 +1,419 @@ +.\" $NetBSD: traceroute.8,v 1.29 2011/09/11 01:06:26 christos Exp $ +.\" +.\" Copyright (c) 1989, 1995, 1996, 1997 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms are permitted +.\" provided that the above copyright notice and this paragraph are +.\" duplicated in all such forms and that any documentation, +.\" advertising materials, and other materials related to such +.\" distribution and use acknowledge that the software was developed +.\" by the University of California, Berkeley. The name of the +.\" University may not be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" Id: traceroute.8,v 1.19 2000/09/21 08:44:19 leres Exp +.\" +.TH TRACEROUTE 8 "21 September 2000" +.UC 6 +.SH NAME +traceroute \- print the route packets take to network host +.SH SYNOPSIS +.na +.B traceroute +[ +.B \-aDFPIdlMnrvx +] [ +.B \-f +.I first_ttl +] +.br +.ti +8 +[ +.B \-g +.I gateway +] [ +.B \-i +.I iface +] [ +.B \-m +max_ttl +] +.br +.ti +8 +[ +.B \-p +.I port +] [ +.B \-q +.I nqueries +] [ +.B \-s +.I src_addr +] +.br +.ti +8 +[ +.B \-t +.I tos +] [ +.B \-w +.I waittime +] [ +.B \-z +.I pausemsecs + ] +] [ +.B \-A +.I as_server +] +.br +.ti +8 +.I host +[ +.I packetlen +] +.ad +.SH DESCRIPTION +The Internet is a large and complex aggregation of +network hardware, connected together by gateways. +Tracking the route one's packets follow (or finding the miscreant +gateway that's discarding your packets) can be difficult. +.I Traceroute +uses the IP protocol `time to live' field and attempts to elicit an +ICMP TIME_EXCEEDED response from each gateway along the path to some +host. +.PP +The only mandatory parameter is the destination host name or IP number. +The default probe datagram length is 40 bytes, but this may be increased +by specifying a packet length (in bytes) after the destination host +name. +.PP +Other options are: +.TP +.B \-a +Turn on AS# lookups for each hop encountered. +.TP +.B \-A +Turn on AS# lookups and use the given server instead of the default. +.TP +.B \-d +Turn on socket-level debugging. +.TP +.B \-D +Dump the packet data to standard error before transmitting it. +.TP +.B \-f +Set the initial time-to-live used in the first outgoing probe packet. +.TP +.B \-F +Set the "don't fragment" bit. +.TP +.B \-g +Specify a loose source route gateway (8 maximum). +.TP +.B \-i +Specify a network interface to obtain the source IP address for +outgoing probe packets. This is normally only useful on a multi-homed +host. (See the +.B \-s +flag for another way to do this.) +.TP +.B \-I +Use ICMP ECHO instead of UDP datagrams. +.TP +.B \-l +Display the ttl value of the returned packet. This is useful for +checking for asymmetric routing. +.TP +.B \-m +Set the max time-to-live (max number of hops) used in outgoing probe +packets. The default value is taken from the +.I net.inet.ip.ttl +sysctl(3) variable. +.TP +.B \-M +If found, show the MPLS Label and the Experimental (EXP) bit for the hop. +.TP +.B \-n +Print hop addresses numerically rather than symbolically and numerically +(saves a nameserver address-to-name lookup for each gateway found on the +path). +.TP +.B \-p +Set the base UDP port number used in probes (default is 33434). +Traceroute hopes that nothing is listening on UDP ports +.I base +to +.I base + nhops \- 1 +at the destination host (so an ICMP PORT_UNREACHABLE message will +be returned to terminate the route tracing). If something is +listening on a port in the default range, this option can be used +to pick an unused port range. +.TP +.B \-P +Set the "don't fragment" bit, and use the next hop mtu each time we get +the "need fragmentation" error, thus probing the path MTU. +.TP +.B \-q +Set the number of probe packets sent for each hop. By default, traceroute +sends three probe packets. +.TP +.B \-r +Bypass the normal routing tables and send directly to a host on an attached +network. +If the host is not on a directly-attached network, +an error is returned. +This option can be used to ping a local host through an interface +that has no route through it (e.g., after the interface was dropped by +.IR routed (8)). +.TP +.B \-s +Use the following IP address (which usually is given as an IP number, not +a hostname) as the source address in outgoing probe packets. On +multi-homed hosts (those with more than one IP +address), this option can be used to +force the source address to be something other than the IP address +of the interface the probe packet is sent on. If the IP address +is not one of this machine's interface addresses, an error is +returned and nothing is sent. (See the +.B \-i +flag for another way to do this.) +.TP +.B \-t +Set the +.I type-of-service +in probe packets to the following value (default zero). The value must be +a decimal integer in the range 0 to 255. This option can be used to +see if different types-of-service result in different paths. (If you +are not running 4.4BSD, this may be academic since the normal network +services like telnet and ftp don't let you control the TOS). +Not all values of TOS are legal or +meaningful \- see the IP spec for definitions. Useful values are +probably +.RB ` -t +.IR 16 ' +(low delay) and +.RB ` -t +.IR 8 ' +(high throughput). +.TP +.B \-v +Verbose output. Received ICMP packets other than TIME_EXCEEDED and +UNREACHABLEs are listed. +.TP +.B \-w +Set the time (in seconds) to wait for a response to a probe (default 5 +sec.). +.TP +.B \-x +Toggle ip checksums. Normally, this prevents traceroute from calculating +ip checksums. In some cases, the operating system can overwrite parts of +the outgoing packet but not recalculate the checksum (so in some cases +the default is to not calculate checksums and using +.B \-x +causes them to be calculated). Note that checksums are usually required +for the last hop when using ICMP ECHO probes +.RB ( \-I ). +So they are always calculated when using ICMP. +.TP +.B \-z +Set the time (in milliseconds) to pause between probes (default 0). +Some systems such as Solaris and routers such as Ciscos rate limit +icmp messages. A good value to use with this this is 500 (e.g. 1/2 second). +.PP +This program attempts to trace the route an IP packet would follow to some +internet host by launching UDP probe +packets with a small ttl (time to live) then listening for an +ICMP "time exceeded" reply from a gateway. We start our probes +with a ttl of one and increase by one until we get an ICMP "port +unreachable" (which means we got to "host") or hit a max (which +defaults to 30 hops \*[Am] can be changed with the +.B \-m +flag). Three +probes (change with +.B \-q +flag) are sent at each ttl setting and a +line is printed showing the ttl, address of the gateway and +round trip time of each probe. If the probe answers come from +different gateways, the address of each responding system will +be printed. If there is no response within a 5 sec. timeout +interval (changed with the +.B \-w +flag), a "*" is printed for that +probe. +.PP +We don't want the destination +host to process the UDP probe packets so the destination port is set to an +unlikely value (if some clod on the destination is using that +value, it can be changed with the +.B \-p +flag). +.PP +A sample use and output might be: + +.RS +.nf +[yak 71]% traceroute nis.nsf.net. +traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 38 byte packet + 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms + 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms + 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms + 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms + 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms + 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms + 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms +10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms +11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms +.fi +.RE + +Note that lines 2 \*[Am] 3 are the same. This is due to a buggy +kernel on the 2nd hop system \- lilac-dmc.Berkeley.EDU \- that forwards +packets with a zero ttl (a bug in the distributed version +of 4.3BSD). Note that you have to guess what path +the packets are taking cross-country since the NSFNET (129.140) +doesn't supply address-to-name translations for its NSSes. +.PP +A more interesting example is: + +.RS +.nf +[yak 72]% traceroute allspice.lcs.mit.edu. +traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max + 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms + 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms + 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms + 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms + 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms + 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms + 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms + 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms +10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms +11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms +12 * * * +13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms +14 * * * +15 * * * +16 * * * +17 * * * +18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms +.fi +.RE + +Note that the gateways 12, 14, 15, 16 \*[Am] 17 hops away +either don't send ICMP "time exceeded" messages or send them +with a ttl too small to reach us. 14 \- 17 are running the +MIT C Gateway code that doesn't send "time exceeded"s. God +only knows what's going on with 12. +.PP +The silent gateway 12 in the above may be the result of a bug in +the 4.[23]BSD network code (and its derivatives): 4.x (x \(<= 3) +sends an unreachable message using whatever ttl remains in the +original datagram. Since, for gateways, the remaining ttl is +zero, the ICMP "time exceeded" is guaranteed to not make it back +to us. The behavior of this bug is slightly more interesting +when it appears on the destination system: + +.RS +.nf + 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms + 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms + 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms + 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms + 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms + 7 * * * + 8 * * * + 9 * * * +10 * * * +11 * * * +12 * * * +13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! +.fi +.RE + +Notice that there are 12 "gateways" (13 is the final +destination) and exactly the last half of them are "missing". +What's really happening is that rip (a Sun-3 running Sun OS3.5) +is using the ttl from our arriving datagram as the ttl in its +ICMP reply. So, the reply will time out on the return path +(with no notice sent to anyone since ICMP's aren't sent for +ICMP's) until we probe with a ttl that's at least twice the path +length. I.e., rip is really only 7 hops away. A reply that +returns with a ttl of 1 is a clue this problem exists. +Traceroute prints a "!" after the time if the ttl is \(<= 1. +Since vendors ship a lot of obsolete (DEC's ULTRIX, Sun 3.x) or +non-standard (HP-UX) software, expect to see this problem +frequently and/or take care picking the target host of your +probes. + +Other possible annotations after the time are +.BR !H , +.BR !N , +or +.B !P +(host, network or protocol unreachable), +.B !S +(source route failed), +.B !F\- +(fragmentation needed \- the RFC1191 Path MTU Discovery value is displayed), +.B !X +(communication administratively prohibited), +.B !V +(host precedence violation), +.B !C +(precedence cutoff in effect), or +.B !\*[Lt]N\*[Gt] +(ICMP unreachable code \*[Lt]num\*[Gt]). +These are defined by RFC1812 (which supersedes RFC1716). +If almost all the probes result in some kind of unreachable, traceroute +will give up and exit. + +.RS +.nf +traceroute \-g 10.3.0.5 128.182.0.0 +.fi +.RE + +will show the path from the Cambridge Mailbridge to PSC, while + +.RS +.nf +traceroute \-g 192.5.146.4 \-g 10.3.0.5 35.0.0.0 +.fi +.RE + +will show the path from the Cambridge Mailbridge to Merit, using PSC to +reach the Mailbridge. +.PP +This program is intended for use in network testing, measurement +and management. +It should be used primarily for manual fault isolation. +Because of the load it could impose on the network, it is unwise to use +.I traceroute +during normal operations or from automated scripts. +.SH SEE ALSO +netstat(1), ping(8) +.SH AUTHOR +Implemented by Van Jacobson from a suggestion by Steve Deering. Debugged +by a cast of thousands with particularly cogent suggestions or fixes from +C. Philip Wood, Tim Seaver and Ken Adelman. +.LP +The current version is available via anonymous ftp: +.LP +.RS +.I ftp://ftp.ee.lbl.gov/traceroute.tar.gz +.RE +.SH BUGS +Please send bug reports to traceroute@ee.lbl.gov. +.PP +The AS number capability reports information that may sometimes be +inaccurate due to discrepancies between the contents of the routing +database server and the current state of the Internet. diff --git a/usr.sbin/traceroute/traceroute.c b/usr.sbin/traceroute/traceroute.c new file mode 100644 index 000000000..a4b10f963 --- /dev/null +++ b/usr.sbin/traceroute/traceroute.c @@ -0,0 +1,1905 @@ +/* $NetBSD: traceroute.c,v 1.81 2012/08/16 00:40:28 zafer Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#ifndef lint +#if 0 +static const char rcsid[] = + "@(#)Id: traceroute.c,v 1.68 2000/12/14 08:04:33 leres Exp (LBL)"; +#else +__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997,\ + 1998, 1999, 2000\ + The Regents of the University of California. All rights reserved."); +__RCSID("$NetBSD: traceroute.c,v 1.81 2012/08/16 00:40:28 zafer Exp $"); +#endif +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * traceroute host - trace the route ip packets follow going to "host". + * + * Attempt to trace the route an ip packet would follow to some + * internet host. We find out intermediate hops by launching probe + * packets with a small ttl (time to live) then listening for an + * icmp "time exceeded" reply from a gateway. We start our probes + * with a ttl of one and increase by one until we get an icmp "port + * unreachable" (which means we got to "host") or hit a max (which + * defaults to 30 hops & can be changed with the -m flag). Three + * probes (change with -q flag) are sent at each ttl setting and a + * line is printed showing the ttl, address of the gateway and + * round trip time of each probe. If the probe answers come from + * different gateways, the address of each responding system will + * be printed. If there is no response within a 5 sec. timeout + * interval (changed with the -w flag), a "*" is printed for that + * probe. + * + * Probe packets are UDP format. We don't want the destination + * host to process them so the destination port is set to an + * unlikely value (if some clod on the destination is using that + * value, it can be changed with the -p flag). + * + * A sample use might be: + * + * [yak 71]% traceroute nis.nsf.net. + * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet + * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms + * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms + * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms + * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms + * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms + * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms + * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms + * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms + * + * Note that lines 2 & 3 are the same. This is due to a buggy + * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards + * packets with a zero ttl. + * + * A more interesting example is: + * + * [yak 72]% traceroute allspice.lcs.mit.edu. + * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max + * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms + * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms + * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms + * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms + * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms + * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms + * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms + * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms + * 12 * * * + * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms + * 14 * * * + * 15 * * * + * 16 * * * + * 17 * * * + * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms + * + * (I start to see why I'm having so much trouble with mail to + * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away + * either don't send ICMP "time exceeded" messages or send them + * with a ttl too small to reach us. 14 - 17 are running the + * MIT C Gateway code that doesn't send "time exceeded"s. God + * only knows what's going on with 12. + * + * The silent gateway 12 in the above may be the result of a bug in + * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) + * sends an unreachable message using whatever ttl remains in the + * original datagram. Since, for gateways, the remaining ttl is + * zero, the icmp "time exceeded" is guaranteed to not make it back + * to us. The behavior of this bug is slightly more interesting + * when it appears on the destination system: + * + * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms + * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms + * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms + * 7 * * * + * 8 * * * + * 9 * * * + * 10 * * * + * 11 * * * + * 12 * * * + * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! + * + * Notice that there are 12 "gateways" (13 is the final + * destination) and exactly the last half of them are "missing". + * What's really happening is that rip (a Sun-3 running Sun OS3.5) + * is using the ttl from our arriving datagram as the ttl in its + * icmp reply. So, the reply will time out on the return path + * (with no notice sent to anyone since icmp's aren't sent for + * icmp's) until we probe with a ttl that's at least twice the path + * length. I.e., rip is really only 7 hops away. A reply that + * returns with a ttl of 1 is a clue this problem exists. + * Traceroute prints a "!" after the time if the ttl is <= 1. + * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or + * non-standard (HPUX) software, expect to see this problem + * frequently and/or take care picking the target host of your + * probes. + * + * Other possible annotations after the time are !H, !N, !P (got a host, + * network or protocol unreachable, respectively), !S or !F (source + * route failed or fragmentation needed -- neither of these should + * ever occur and the associated gateway is busted if you see one). If + * almost all the probes result in some kind of unreachable, traceroute + * will give up and exit. + * + * Notes + * ----- + * This program must be run by root or be setuid. (I suggest that + * you *don't* make it setuid -- casual use could result in a lot + * of unnecessary traffic on our poor, congested nets.) + * + * This program requires a kernel mod that does not appear in any + * system available from Berkeley: A raw ip socket using proto + * IPPROTO_RAW must interpret the data sent as an ip datagram (as + * opposed to data to be wrapped in a ip datagram). See the README + * file that came with the source to this program for a description + * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may + * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE + * MODIFIED TO RUN THIS PROGRAM. + * + * The udp port usage may appear bizarre (well, ok, it is bizarre). + * The problem is that an icmp message only contains 8 bytes of + * data from the original datagram. 8 bytes is the size of a udp + * header so, if we want to associate replies with the original + * datagram, the necessary information must be encoded into the + * udp header (the ip id could be used but there's no way to + * interlock with the kernel's assignment of ip id's and, anyway, + * it would have taken a lot more kernel hacking to allow this + * code to set the ip id). So, to allow two or more users to + * use traceroute simultaneously, we use this task's pid as the + * source port (the high bit is set to move the port number out + * of the "likely" range). To keep track of which probe is being + * replied to (so times and/or hop counts don't get confused by a + * reply that was delayed in transit), we increment the destination + * port number before each probe. + * + * Don't use this as a coding example. I was trying to find a + * routing problem and this code sort-of popped out after 48 hours + * without sleep. I was amazed it ever compiled, much less ran. + * + * I stole the idea for this program from Steve Deering. Since + * the first release, I've learned that had I attended the right + * IETF working group meetings, I also could have stolen it from Guy + * Almes or Matt Mathis. I don't know (or care) who came up with + * the idea first. I envy the originators' perspicacity and I'm + * glad they didn't keep the idea a secret. + * + * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or + * enhancements to the original distribution. + * + * I've hacked up a round-trip-route version of this that works by + * sending a loose-source-routed udp datagram through the destination + * back to yourself. Unfortunately, SO many gateways botch source + * routing, the thing is almost worthless. Maybe one day... + * + * -- Van Jacobson (van@ee.lbl.gov) + * Tue Dec 20 03:50:13 PST 1988 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#ifdef HAVE_MALLOC_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#ifdef IPSEC +#include +#include +#endif + +#include "gnuc.h" +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +/* rfc1716 */ +#ifndef ICMP_UNREACH_FILTER_PROHIB +#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ +#endif +#ifndef ICMP_UNREACH_HOST_PRECEDENCE +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */ +#endif +#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ +#endif + +#include "ifaddrlist.h" +#include "as.h" +#include "prog_ops.h" + +/* Maximum number of gateways (include room for one noop) */ +#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t))) + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define Fprintf (void)fprintf +#define Printf (void)printf + +/* Host name and address list */ +struct hostinfo { + char *name; + int n; + u_int32_t *addrs; +}; + +/* Data section of the probe packet */ +struct outdata { + u_char seq; /* sequence number of this packet */ + u_char ttl; /* ttl packet left with */ + struct tv32 { + int32_t tv32_sec; + int32_t tv32_usec; + } tv; /* time packet left */ +}; + +/* + * Support for ICMP extensions + * + * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt + */ +#define ICMP_EXT_OFFSET 8 /* ICMP type, code, checksum, unused */ + \ + 128 /* original datagram */ +#define ICMP_EXT_VERSION 2 +/* + * ICMP extensions, common header + */ +struct icmp_ext_cmn_hdr { +#if BYTE_ORDER == BIG_ENDIAN + unsigned char version:4; + unsigned char reserved1:4; +#else + unsigned char reserved1:4; + unsigned char version:4; +#endif + unsigned char reserved2; + unsigned short checksum; +}; + +/* + * ICMP extensions, object header + */ +struct icmp_ext_obj_hdr { + u_short length; + u_char class_num; +#define MPLS_STACK_ENTRY_CLASS 1 + u_char c_type; +#define MPLS_STACK_ENTRY_C_TYPE 1 +}; + +struct mpls_header { +#if BYTE_ORDER == BIG_ENDIAN + uint32_t label:20; + unsigned char exp:3; + unsigned char s:1; + unsigned char ttl:8; +#else + unsigned char ttl:8; + unsigned char s:1; + unsigned char exp:3; + uint32_t label:20; +#endif +}; + +#ifndef HAVE_ICMP_NEXTMTU +/* Path MTU Discovery (RFC1191) */ +struct my_pmtu { + u_short ipm_void; + u_short ipm_nextmtu; +}; +#endif + +static u_char packet[512]; /* last inbound (icmp) packet */ + +static struct ip *outip; /* last output (udp) packet */ +static struct udphdr *outudp; /* last output (udp) packet */ +static void *outmark; /* packed location of struct outdata */ +static struct outdata outsetup; /* setup and copy for alignment */ + +static struct icmp *outicmp; /* last output (icmp) packet */ + +/* loose source route gateway list (including room for final destination) */ +static u_int32_t gwlist[NGATEWAYS + 1]; + +static int s; /* receive (icmp) socket file descriptor */ +static int sndsock; /* send (udp/icmp) socket file descriptor */ + +static struct sockaddr whereto; /* Who to try to reach */ +static struct sockaddr wherefrom; /* Who we are */ +static int packlen; /* total length of packet */ +static int minpacket; /* min ip packet size */ +static int maxpacket = 32 * 1024; /* max ip packet size */ +static int printed_ttl = 0; +static int pmtu; /* Path MTU Discovery (RFC1191) */ +static u_int pausemsecs; + +static const char *prog; +static char *source; +static char *hostname; +static char *device; +#ifdef notdef +static const char devnull[] = "/dev/null"; +#endif + +static int nprobes = 3; +static int max_ttl = 30; +static int first_ttl = 1; +static u_int16_t ident; +static in_port_t port = 32768 + 666; /* start udp dest port # for probe packets */ + +static int options; /* socket options */ +static int verbose; +static int waittime = 5; /* time to wait for response (in seconds) */ +static int nflag; /* print addresses numerically */ +static int dump; +static int Mflag; /* show MPLS labels if any */ +static int as_path; /* print as numbers for each hop */ +static char *as_server = NULL; +static void *asn; +static int useicmp = 0; /* use icmp echo instead of udp packets */ +#ifdef CANT_HACK_CKSUM +static int doipcksum = 0; /* don't calculate checksums */ +#else +static int doipcksum = 1; /* calculate checksums */ +#endif +static int optlen; /* length of ip options */ + +static int mtus[] = { + 17914, + 8166, + 4464, + 4352, + 2048, + 2002, + 1536, + 1500, + 1492, + 1480, + 1280, + 1006, + 576, + 552, + 544, + 512, + 508, + 296, + 68, + 0 +}; +static int *mtuptr = &mtus[0]; +static int mtudisc = 0; +static int nextmtu; /* from ICMP error, set by packet_ok(), might be 0 */ + +/* Forwards */ +static double deltaT(struct timeval *, struct timeval *); +static void freehostinfo(struct hostinfo *); +static void getaddr(u_int32_t *, char *); +static struct hostinfo *gethostinfo(char *); +static u_int16_t in_cksum(u_int16_t *, int); +static u_int16_t in_cksum2(u_int16_t, u_int16_t *, int); +static char *inetname(struct in_addr); +static int packet_ok(u_char *, ssize_t, struct sockaddr_in *, int); +static const char *pr_type(u_char); +static void print(u_char *, int, struct sockaddr_in *); +static void resize_packet(void); +static void dump_packet(void); +static void send_probe(int, int, struct timeval *); +static void setsin(struct sockaddr_in *, u_int32_t); +static int str2val(const char *, const char *, int, int); +static void tvsub(struct timeval *, struct timeval *); +static void usage(void) __attribute__((__noreturn__)); +static ssize_t wait_for_reply(int, struct sockaddr_in *, const struct timeval *); +static void decode_extensions(unsigned char *buf, int ip_len); +static void frag_err(void); +static int find_local_ip(struct sockaddr_in *, struct sockaddr_in *); +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +static int setpolicy(int, const char *); +#endif +#endif + +int +main(int argc, char **argv) +{ + int op, code, n; + u_char *outp; + u_int32_t *ap; + struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom; + struct sockaddr_in *to = (struct sockaddr_in *)&whereto; + struct hostinfo *hi; + int on = 1; + int ttl, probe, i; + int seq = 0; + int tos = 0, settos = 0, ttl_flag = 0; + int lsrr = 0; + u_int16_t off = 0; + struct ifaddrlist *al, *al2; + char errbuf[132]; + int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; + size_t size = sizeof(max_ttl); + + setprogname(argv[0]); + prog = getprogname(); + + if (prog_init && prog_init() == -1) + err(1, "init failed"); + +#ifdef notdef + /* Kernel takes care of it */ + /* Insure the socket fds won't be 0, 1 or 2 */ + if (open(devnull, O_RDONLY) < 0 || + open(devnull, O_RDONLY) < 0 || + open(devnull, O_RDONLY) < 0) + err(1, "Cannot open `%s'", devnull); +#endif + if ((s = prog_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) + err(1, "icmp socket"); + + /* + * XXX 'useicmp' will always be zero here. I think the HP-UX users + * running our traceroute code will forgive us. + */ +#ifndef __hpux +#ifdef __minix + sndsock = prog_socket(AF_INET, SOCK_RAW, IPPROTO_UDP); +#else + sndsock = prog_socket(AF_INET, SOCK_RAW, IPPROTO_RAW); +#endif +#else + sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW + useicmp ? IPPROTO_ICMP : IPPROTO_UDP); +#endif + if (sndsock < 0) + err(1, "raw socket"); + + (void) prog_sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size, + NULL, 0); + + opterr = 0; + while ((op = getopt(argc, argv, "aA:dDFPIMnlrvxf:g:i:m:p:q:s:t:w:z:")) != -1) + switch (op) { + + case 'a': + as_path = 1; + break; + + case 'A': + as_path = 1; + as_server = optarg; + break; + + case 'd': + options |= SO_DEBUG; + break; + + case 'D': + dump = 1; + break; + + case 'f': + first_ttl = str2val(optarg, "first ttl", 1, 255); + break; + + case 'F': + off = IP_DF; + break; + + case 'g': + if (lsrr >= NGATEWAYS) + errx(1, "more than %d gateways", NGATEWAYS); + getaddr(gwlist + lsrr, optarg); + ++lsrr; + break; + + case 'i': + device = optarg; + break; + + case 'I': + ++useicmp; + break; + + case 'l': + ++ttl_flag; + break; + + case 'm': + max_ttl = str2val(optarg, "max ttl", 1, 255); + break; + + case 'M': + Mflag = 1; + break; + + case 'n': + ++nflag; + break; + + case 'p': + port = (u_short)str2val(optarg, "port", + 1, (1 << 16) - 1); + break; + + case 'q': + nprobes = str2val(optarg, "nprobes", 1, -1); + break; + + case 'r': + options |= SO_DONTROUTE; + break; + + case 's': + /* + * set the ip source address of the outbound + * probe (e.g., on a multi-homed host). + */ + source = optarg; + break; + + case 't': + tos = str2val(optarg, "tos", 0, 255); + ++settos; + break; + + case 'v': + ++verbose; + break; + + case 'x': + doipcksum = (doipcksum == 0); + break; + + case 'w': + waittime = str2val(optarg, "wait time", + 2, 24 * 60 * 60); + break; + + case 'z': + pausemsecs = str2val(optarg, "pause msecs", + 0, 60 * 60 * 1000); + + case 'P': + off = IP_DF; + mtudisc = 1; + break; + + default: + usage(); + } + + if (first_ttl > max_ttl) + errx(1, "first ttl (%d) may not be greater than max ttl (%d)", + first_ttl, max_ttl); + + if (!doipcksum) + warnx("ip checksums disabled"); + + if (lsrr > 0) + optlen = (lsrr + 1) * sizeof(gwlist[0]); + minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen; + if (useicmp) + minpacket += 8; /* XXX magic number */ + else + minpacket += sizeof(*outudp); + packlen = minpacket; /* minimum sized packet */ + + if (mtudisc) + packlen = *mtuptr++; + + /* Process destination and optional packet size */ + switch (argc - optind) { + + case 2: + packlen = str2val(argv[optind + 1], + "packet length", minpacket, maxpacket); + /* Fall through */ + + case 1: + hostname = argv[optind]; + hi = gethostinfo(hostname); + setsin(to, hi->addrs[0]); + if (hi->n > 1) + warnx("%s has multiple addresses; using %s", + hostname, inet_ntoa(to->sin_addr)); + hostname = hi->name; + hi->name = NULL; + freehostinfo(hi); + break; + + default: + usage(); + } + +#ifdef HAVE_SETLINEBUF + setlinebuf (stdout); +#else + setvbuf(stdout, NULL, _IOLBF, 0); +#endif + + outip = malloc((unsigned)packlen); + if (outip == NULL) + err(1, "malloc"); + memset(outip, 0, packlen); + + outip->ip_v = IPVERSION; + if (settos) + outip->ip_tos = tos; +#ifdef BYTESWAP_IP_HDR + outip->ip_len = htons(packlen); + outip->ip_off = htons(off); +#else + outip->ip_len = packlen; + outip->ip_off = off; +#endif + outp = (u_char *)(outip + 1); +#ifdef HAVE_RAW_OPTIONS + if (lsrr > 0) { + u_char *optlist; + + optlist = outp; + outp += optlen; + + /* final hop */ + gwlist[lsrr] = to->sin_addr.s_addr; + + outip->ip_dst.s_addr = gwlist[0]; + + /* force 4 byte alignment */ + optlist[0] = IPOPT_NOP; + /* loose source route option */ + optlist[1] = IPOPT_LSRR; + i = lsrr * sizeof(gwlist[0]); + optlist[2] = i + 3; + /* Pointer to LSRR addresses */ + optlist[3] = IPOPT_MINOFF; + memcpy(optlist + 4, gwlist + 1, i); + } else +#endif + outip->ip_dst = to->sin_addr; + + outip->ip_hl = (outp - (u_char *)outip) >> 2; + ident = htons(arc4random() & 0xffff) | 0x8000; + if (useicmp) { + outip->ip_p = IPPROTO_ICMP; + + outicmp = (struct icmp *)outp; + outicmp->icmp_type = ICMP_ECHO; + outicmp->icmp_id = htons(ident); + + outmark = outp + 8; /* XXX magic number */ + } else { + outip->ip_p = IPPROTO_UDP; + + outudp = (struct udphdr *)outp; + outudp->uh_sport = htons(ident); + outudp->uh_ulen = + htons((u_int16_t)(packlen - (sizeof(*outip) + optlen))); + outmark = outudp + 1; + } + + if (options & SO_DEBUG) + (void)prog_setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, + sizeof(on)); +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + /* + * do not raise error even if setsockopt fails, kernel may have ipsec + * turned off. + */ + if (setpolicy(s, "in bypass") < 0) + exit(1); + if (setpolicy(s, "out bypass") < 0) + exit(1); +#else + { + int level = IPSEC_LEVEL_AVAIL; + + (void)prog_setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level, + sizeof(level)); + (void)prog_setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level, + sizeof(level)); +#ifdef IP_AUTH_TRANS_LEVEL + (void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level, + sizeof(level)); +#else + (void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level, + sizeof(level)); +#endif +#ifdef IP_AUTH_NETWORK_LEVEL + (void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level, + sizeof(level)); +#endif + } +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + /* + * do not raise error even if setsockopt fails, kernel may have ipsec + * turned off. + */ + if (setpolicy(sndsock, "in bypass") < 0) + exit(1); + if (setpolicy(sndsock, "out bypass") < 0) + exit(1); +#else + { + int level = IPSEC_LEVEL_BYPASS; + + (void)prog_setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level, + sizeof(level)); + (void)prog_setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level, + sizeof(level)); +#ifdef IP_AUTH_TRANS_LEVEL + (void)prog_setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level, + sizeof(level)); +#else + (void)prog_setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level, + sizeof(level)); +#endif +#ifdef IP_AUTH_NETWORK_LEVEL + (void)prog_setsockopt(sndsock, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level, + sizeof(level)); +#endif + } +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + +#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS) + if (lsrr > 0) { + u_char optlist[MAX_IPOPTLEN]; + + /* final hop */ + gwlist[lsrr] = to->sin_addr.s_addr; + ++lsrr; + + /* force 4 byte alignment */ + optlist[0] = IPOPT_NOP; + /* loose source route option */ + optlist[1] = IPOPT_LSRR; + i = lsrr * sizeof(gwlist[0]); + optlist[2] = i + 3; + /* Pointer to LSRR addresses */ + optlist[3] = IPOPT_MINOFF; + memcpy(optlist + 4, gwlist, i); + + if ((prog_setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, optlist, + i + sizeof(gwlist[0]))) < 0) + err(1, "IP_OPTIONS"); + } +#endif + +#ifndef __minix +#ifdef SO_SNDBUF + if (prog_setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen, + sizeof(packlen)) < 0) + err(1, "SO_SNDBUF"); +#endif +#ifdef IP_HDRINCL + if (prog_setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, + sizeof(on)) < 0) + err(1, "IP_HDRINCL"); +#else +#ifdef IP_TOS + if (settos && prog_setsockopt(sndsock, IPPROTO_IP, IP_TOS, + &tos, sizeof(tos)) < 0) + err(1, "setsockopt tos %d", tos); +#endif +#endif + if (options & SO_DEBUG) + if (prog_setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, &on, + sizeof(on)) < 0) + err(1, "setsockopt debug %d", tos); + if (options & SO_DONTROUTE) + if (prog_setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, &on, + sizeof(on)) < 0) + err(1, "setsockopt dontroute %d", tos); +#endif + + /* Get the interface address list */ + n = ifaddrlist(&al, errbuf, sizeof errbuf); + al2 = al; + if (n < 0) + errx(1, "ifaddrlist (%s)", errbuf); + if (n == 0) + errx(1, "Can't find any network interfaces"); + + /* Look for a specific device */ + if (device != NULL) { + for (i = n; i > 0; --i, ++al2) + if (strcmp(device, al2->device) == 0) + break; + if (i <= 0) + errx(1, "Can't find interface %.32s", device); + } + + /* Determine our source address */ + if (source == NULL) { + /* + * If a device was specified, use the interface address. + * Otherwise, try to determine our source address. + * Warn if there are more than one. + */ + setsin(from, al2->addr); + if (n > 1 && device == NULL && !find_local_ip(from, to)) { + warnx("Multiple interfaces found; using %s @ %s", + inet_ntoa(from->sin_addr), al2->device); + } + } else { + hi = gethostinfo(source); + source = hi->name; + hi->name = NULL; + if (device == NULL) { + /* + * Use the first interface found. + * Warn if there are more than one. + */ + setsin(from, hi->addrs[0]); + if (hi->n > 1) + warnx("%s has multiple addresses; using %s", + source, inet_ntoa(from->sin_addr)); + } else { + /* + * Make sure the source specified matches the + * interface address. + */ + for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) + if (*ap == al2->addr) + break; + if (i <= 0) + errx(1, "%s is not on interface %s", + source, device); + setsin(from, *ap); + } + freehostinfo(hi); + } + + /* Revert to non-privileged user after opening sockets */ + setgid(getgid()); + setuid(getuid()); + + /* + * If not root, make sure source address matches a local interface. + * (The list of addresses produced by ifaddrlist() automatically + * excludes interfaces that are marked down and/or loopback.) + */ + if (getuid()) { + al2 = al; + for (i = n; i > 0; --i, ++al2) + if (from->sin_addr.s_addr == al2->addr) + break; + if (i <= 0) + errx(1, "%s is not a valid local address " + "and you are not superuser.", + inet_ntoa(from->sin_addr)); + } + + outip->ip_src = from->sin_addr; +#ifndef IP_HDRINCL + if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) + err(1, "bind"); +#endif + + if (as_path) { + asn = as_setup(as_server); + if (asn == NULL) { + warnx("as_setup failed, AS# lookups disabled"); + (void)fflush(stderr); + as_path = 0; + } + } + + setuid(getuid()); + Fprintf(stderr, "%s to %s (%s)", + prog, hostname, inet_ntoa(to->sin_addr)); + if (source) + Fprintf(stderr, " from %s", source); + Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen); + (void)fflush(stderr); + + for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { + u_int32_t lastaddr = 0; + int gotlastaddr = 0; + int got_there = 0; + int unreachable = 0; + int sentfirst = 0; + +again: + printed_ttl = 0; + for (probe = 0; probe < nprobes; ++probe) { + int cc; + struct timeval t1, t2; + struct ip *ip; + if (sentfirst && pausemsecs > 0) + usleep(pausemsecs * 1000); + (void)gettimeofday(&t1, NULL); + if (!useicmp && htons(port + seq + 1) == 0) + seq++; + send_probe(++seq, ttl, &t1); + ++sentfirst; + while ((cc = wait_for_reply(s, from, &t1)) != 0) { + (void)gettimeofday(&t2, NULL); + /* + * Since we'll be receiving all ICMP + * messages to this host above, we may + * never end up with cc=0, so we need + * an additional termination check. + */ + if (t2.tv_sec - t1.tv_sec > waittime) { + cc = 0; + break; + } + i = packet_ok(packet, cc, from, seq); + /* Skip short packet */ + if (i == 0) + continue; + if (!gotlastaddr || + from->sin_addr.s_addr != lastaddr) { + if (gotlastaddr) printf("\n "); + print(packet, cc, from); + lastaddr = from->sin_addr.s_addr; + ++gotlastaddr; + } + ip = (struct ip *)packet; + Printf(" %.3f ms", deltaT(&t1, &t2)); + if (ttl_flag) + Printf(" (ttl = %d)", ip->ip_ttl); + if (i == -2) { +#ifndef ARCHAIC + if (ip->ip_ttl <= 1) + Printf(" !"); +#endif + ++got_there; + break; + } + + /* time exceeded in transit */ + if (i == -1) + break; + code = i - 1; + switch (code) { + + case ICMP_UNREACH_PORT: +#ifndef ARCHAIC + if (ip->ip_ttl <= 1) + Printf(" !"); +#endif + ++got_there; + break; + + case ICMP_UNREACH_NET: + ++unreachable; + Printf(" !N"); + break; + + case ICMP_UNREACH_HOST: + ++unreachable; + Printf(" !H"); + break; + + case ICMP_UNREACH_PROTOCOL: + ++got_there; + Printf(" !P"); + break; + + case ICMP_UNREACH_NEEDFRAG: + if (mtudisc) { + frag_err(); + goto again; + } else { + ++unreachable; + Printf(" !F-%d", pmtu); + } + break; + + case ICMP_UNREACH_SRCFAIL: + ++unreachable; + Printf(" !S"); + break; + + case ICMP_UNREACH_FILTER_PROHIB: + ++unreachable; + Printf(" !X"); + break; + + case ICMP_UNREACH_HOST_PRECEDENCE: + ++unreachable; + Printf(" !V"); + break; + + case ICMP_UNREACH_PRECEDENCE_CUTOFF: + ++unreachable; + Printf(" !C"); + break; + + default: + ++unreachable; + Printf(" !<%d>", code); + break; + } + break; + } + if (cc == 0) + Printf(" *"); + else if (cc && probe == nprobes - 1 && Mflag) + decode_extensions(packet, cc); + (void)fflush(stdout); + } + putchar('\n'); + if (got_there || + (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) + break; + } + + if (as_path) + as_shutdown(asn); + + exit(0); +} + +static ssize_t +wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp) +{ + struct pollfd set[1]; + struct timeval now, wait; + ssize_t cc = 0; + socklen_t fromlen = sizeof(*fromp); + int retval; + + set[0].fd = sock; + set[0].events = POLLIN; + + wait.tv_sec = tp->tv_sec + waittime; + wait.tv_usec = tp->tv_usec; + (void)gettimeofday(&now, NULL); + tvsub(&wait, &now); + + if (wait.tv_sec < 0) { + wait.tv_sec = 0; + wait.tv_usec = 0; + } + + retval = prog_poll(set, 1, wait.tv_sec * 1000 + wait.tv_usec / 1000); + if (retval < 0) + /* If we continue, we probably just flood the remote host. */ + err(1, "poll"); + if (retval > 0) { + cc = prog_recvfrom(sock, (char *)packet, sizeof(packet), 0, + (struct sockaddr *)fromp, &fromlen); + } + + return cc; +} + +static void +decode_extensions(unsigned char *buf, int ip_len) +{ + struct icmp_ext_cmn_hdr *cmn_hdr; + struct icmp_ext_obj_hdr *obj_hdr; + union { + struct mpls_header mpls; + uint32_t mpls_h; + } mpls; + size_t datalen, obj_len; + struct ip *ip; + + ip = (struct ip *)buf; + + if (ip_len < (int)((ip->ip_hl << 2) + ICMP_EXT_OFFSET + + sizeof(struct icmp_ext_cmn_hdr))) { + /* + * No support for ICMP extensions on this host + */ + return; + } + + /* + * Move forward to the start of the ICMP extensions, if present + */ + buf += (ip->ip_hl << 2) + ICMP_EXT_OFFSET; + cmn_hdr = (struct icmp_ext_cmn_hdr *)buf; + + if (cmn_hdr->version != ICMP_EXT_VERSION) { + /* + * Unknown version + */ + return; + } + + datalen = ip_len - ((u_char *)cmn_hdr - (u_char *)ip); + + /* + * Check the checksum, cmn_hdr->checksum == 0 means no checksum'ing + * done by sender. + * + * If the checksum is ok, we'll get 0, as the checksum is calculated + * with the checksum field being 0'd. + */ + if (ntohs(cmn_hdr->checksum) && + in_cksum((u_short *)cmn_hdr, datalen)) { + + return; + } + + buf += sizeof(*cmn_hdr); + datalen -= sizeof(*cmn_hdr); + + while (datalen >= sizeof(struct icmp_ext_obj_hdr)) { + obj_hdr = (struct icmp_ext_obj_hdr *)buf; + obj_len = ntohs(obj_hdr->length); + + /* + * Sanity check the length field + */ + if (obj_len > datalen) + return; + + datalen -= obj_len; + + /* + * Move past the object header + */ + buf += sizeof(struct icmp_ext_obj_hdr); + obj_len -= sizeof(struct icmp_ext_obj_hdr); + + switch (obj_hdr->class_num) { + case MPLS_STACK_ENTRY_CLASS: + switch (obj_hdr->c_type) { + case MPLS_STACK_ENTRY_C_TYPE: + while (obj_len >= sizeof(uint32_t)) { + mpls.mpls_h = ntohl(*(uint32_t *)buf); + + buf += sizeof(uint32_t); + obj_len -= sizeof(uint32_t); + + printf(" [MPLS: Label %d Exp %d]", + mpls.mpls.label, mpls.mpls.exp); + } + if (obj_len > 0) { + /* + * Something went wrong, and we're at + * a unknown offset into the packet, + * ditch the rest of it. + */ + return; + } + break; + default: + /* + * Unknown object, skip past it + */ + buf += ntohs(obj_hdr->length) - + sizeof(struct icmp_ext_obj_hdr); + break; + } + break; + + default: + /* + * Unknown object, skip past it + */ + buf += ntohs(obj_hdr->length) - + sizeof(struct icmp_ext_obj_hdr); + break; + } + } +} + +static void +dump_packet(void) +{ + u_char *p; + int i; + + Fprintf(stderr, "packet data:"); + +#ifdef __hpux + for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i < + i < packlen - (sizeof(*outip) + optlen); i++) +#else + for (p = (u_char *)outip, i = 0; i < packlen; i++) +#endif + { + if ((i % 24) == 0) + Fprintf(stderr, "\n "); + Fprintf(stderr, " %02x", *p++); + } + Fprintf(stderr, "\n"); +} + +void +send_probe(int seq, int ttl, struct timeval *tp) +{ + int cc; + struct udpiphdr * ui, *oui; + int oldmtu = packlen; + struct ip tip; + +again: +#ifdef BYTESWAP_IP_LEN + outip->ip_len = htons(packlen); +#else + outip->ip_len = packlen; +#endif + outip->ip_ttl = ttl; +#ifndef __hpux + outip->ip_id = htons(ident + seq); +#endif + + /* + * In most cases, the kernel will recalculate the ip checksum. + * But we must do it anyway so that the udp checksum comes out + * right. + */ + if (doipcksum) { + outip->ip_sum = + in_cksum((u_int16_t *)outip, sizeof(*outip) + optlen); + if (outip->ip_sum == 0) + outip->ip_sum = 0xffff; + } + + /* Payload */ + outsetup.seq = seq; + outsetup.ttl = ttl; + outsetup.tv.tv32_sec = htonl(tp->tv_sec); + outsetup.tv.tv32_usec = htonl(tp->tv_usec); + memcpy(outmark,&outsetup,sizeof(outsetup)); + + if (useicmp) + outicmp->icmp_seq = htons(seq); + else + outudp->uh_dport = htons(port + seq); + + if (useicmp) { + /* Always calculate checksum for icmp packets */ + outicmp->icmp_cksum = 0; + outicmp->icmp_cksum = in_cksum((u_short *)outicmp, + packlen - (sizeof(*outip) + optlen)); + if (outicmp->icmp_cksum == 0) + outicmp->icmp_cksum = 0xffff; + } else if (doipcksum) { + /* Checksum (we must save and restore ip header) */ + tip = *outip; + ui = (struct udpiphdr *)outip; + oui = (struct udpiphdr *)&tip; + /* Easier to zero and put back things that are ok */ + memset(ui, 0, sizeof(ui->ui_i)); + ui->ui_src = oui->ui_src; + ui->ui_dst = oui->ui_dst; + ui->ui_pr = oui->ui_pr; + ui->ui_len = outudp->uh_ulen; + outudp->uh_sum = 0; + outudp->uh_sum = in_cksum((u_short *)ui, packlen); + if (outudp->uh_sum == 0) + outudp->uh_sum = 0xffff; + *outip = tip; + } + + /* XXX undocumented debugging hack */ + if (verbose > 1) { + const u_int16_t *sp; + int nshorts, i; + + sp = (u_int16_t *)outip; + nshorts = (u_int)packlen / sizeof(u_int16_t); + i = 0; + Printf("[ %d bytes", packlen); + while (--nshorts >= 0) { + if ((i++ % 8) == 0) + Printf("\n\t"); + Printf(" %04x", ntohs(*sp++)); + } + if (packlen & 1) { + if ((i % 8) == 0) + Printf("\n\t"); + Printf(" %02x", *(const u_char *)sp); + } + Printf("]\n"); + } + +#ifndef __minix +#if !defined(IP_HDRINCL) && defined(IP_TTL) + if (prog_setsockopt(sndsock, IPPROTO_IP, IP_TTL, + (char *)&ttl, sizeof(ttl)) < 0) + err(1, "setsockopt ttl %d", ttl); +#endif +#else + { + nwio_ipopt_t ipopts; + memset(&ipopts, 0, sizeof(ipopts)); + ipopts.nwio_flags = NWIO_HDR_O_SPEC; + ipopts.nwio_ttl = ttl; + if(ioctl(sndsock, NWIOSIPOPT, &ipopts) < 0) { + err(1, "ttl ioctl"); + } + } +#endif + if (dump) + dump_packet(); + +#ifdef __hpux + cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp, + packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto)); + if (cc > 0) + cc += sizeof(*outip) + optlen; +#else + cc = prog_sendto(sndsock, (char *)outip, + packlen, 0, &whereto, sizeof(whereto)); +#endif + if (cc < 0 || cc != packlen) { + if (cc < 0) { + /* + * An errno of EMSGSIZE means we're writing too big a + * datagram for the interface. We have to just + * decrease the packet size until we find one that + * works. + * + * XXX maybe we should try to read the outgoing if's + * mtu? + */ + if (errno == EMSGSIZE) { + packlen = *mtuptr++; + resize_packet(); + goto again; + } else + warn("sendto.."); + } + + Printf("%s: wrote %s %d chars, ret=%d\n", + prog, hostname, packlen, cc); + (void)fflush(stdout); + } + if (oldmtu != packlen) { + Printf("message too big, " + "trying new MTU = %d\n", packlen); + printed_ttl = 0; + } + if (!printed_ttl) { + Printf("%2d ", ttl); + printed_ttl = 1; + } + +} + +static double +deltaT(struct timeval *t1p, struct timeval *t2p) +{ + double dt; + + dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + + (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; + return dt; +} + +/* + * Convert an ICMP "type" field to a printable string. + */ +static const char * +pr_type(u_char t) +{ + static const char *ttab[] = { + "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", + "Source Quench", "Redirect", "ICMP 6", "ICMP 7", + "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", + "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", + "Info Reply" + }; + + if (t > 16) + return "OUT-OF-RANGE"; + + return ttab[t]; +} + +static int +packet_ok(u_char *buf, ssize_t cc, struct sockaddr_in *from, int seq) +{ + struct icmp *icp; + u_char type, code; + int hlen; +#ifndef ARCHAIC + struct ip *ip; + + ip = (struct ip *) buf; + hlen = ip->ip_hl << 2; + if (cc < hlen + ICMP_MINLEN) { + if (verbose) + Printf("packet too short (%zd bytes) from %s\n", cc, + inet_ntoa(from->sin_addr)); + return 0; + } + cc -= hlen; + icp = (struct icmp *)(buf + hlen); +#else + icp = (struct icmp *)buf; +#endif + type = icp->icmp_type; + code = icp->icmp_code; + /* Path MTU Discovery (RFC1191) */ + if (code != ICMP_UNREACH_NEEDFRAG) + pmtu = 0; + else { +#ifdef HAVE_ICMP_NEXTMTU + pmtu = ntohs(icp->icmp_nextmtu); +#else + pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu); +#endif + } + if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || + type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { + struct ip *hip; + struct udphdr *up; + struct icmp *hicmp; + + hip = &icp->icmp_ip; + hlen = hip->ip_hl << 2; + + nextmtu = ntohs(icp->icmp_nextmtu); /* for frag_err() */ + + if (useicmp) { + /* XXX */ + if (type == ICMP_ECHOREPLY && + icp->icmp_id == htons(ident) && + icp->icmp_seq == htons(seq)) + return -2; + + hicmp = (struct icmp *)((u_char *)hip + hlen); + /* XXX 8 is a magic number */ + if (hlen + 8 <= cc && + hip->ip_p == IPPROTO_ICMP && + hicmp->icmp_id == htons(ident) && + hicmp->icmp_seq == htons(seq)) + return type == ICMP_TIMXCEED ? -1 : code + 1; + } else { + up = (struct udphdr *)((u_char *)hip + hlen); + /* XXX 8 is a magic number */ + if (hlen + 12 <= cc && + hip->ip_p == IPPROTO_UDP && + up->uh_sport == htons(ident) && + up->uh_dport == htons(port + seq)) + return type == ICMP_TIMXCEED ? -1 : code + 1; + } + } +#ifndef ARCHAIC + if (verbose) { + int i; + u_int32_t *lp = (u_int32_t *)&icp->icmp_ip; + + Printf("\n%zd bytes from %s to ", cc, inet_ntoa(from->sin_addr)); + Printf("%s: icmp type %d (%s) code %d\n", + inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); + for (i = 4; i < cc ; i += sizeof(*lp)) + Printf("%2d: x%8.8x\n", i, *lp++); + } +#endif + return(0); +} + +static void +resize_packet(void) +{ + if (useicmp) { + outicmp->icmp_cksum = 0; + outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp, + packlen - (sizeof(*outip) + optlen)); + if (outicmp->icmp_cksum == 0) + outicmp->icmp_cksum = 0xffff; + } else { + outudp->uh_ulen = + htons((u_int16_t)(packlen - (sizeof(*outip) + optlen))); + } +} + +static void +print(u_char *buf, int cc, struct sockaddr_in *from) +{ + struct ip *ip; + int hlen; + char addr[INET_ADDRSTRLEN]; + + ip = (struct ip *) buf; + hlen = ip->ip_hl << 2; + cc -= hlen; + + strlcpy(addr, inet_ntoa(from->sin_addr), sizeof(addr)); + + if (as_path) + Printf(" [AS%u]", as_lookup(asn, addr, AF_INET)); + + if (nflag) + Printf(" %s", addr); + else + Printf(" %s (%s)", inetname(from->sin_addr), addr); + + if (verbose) + Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); +} + +static u_int16_t +in_cksum(u_int16_t *addr, int len) +{ + + return ~in_cksum2(0, addr, len); +} + +/* + * Checksum routine for Internet Protocol family headers (C Version) + */ +static u_int16_t +in_cksum2(u_int16_t seed, u_int16_t *addr, int len) +{ + int nleft = len; + u_int16_t *w = addr; + union { + u_int16_t w; + u_int8_t b[2]; + } answer; + int32_t sum = seed; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), + * we add sequential 16 bit words to it, and at the end, fold + * back all the carry bits from the top 16 bits into the lower + * 16 bits. + */ + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) { + answer.b[0] = *(u_char *)w; + answer.b[1] = 0; + sum += answer.w; + } + + /* + * add back carry outs from top 16 bits to low 16 bits + */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer.w = sum; /* truncate to 16 bits */ + return answer.w; +} + +/* + * Subtract 2 timeval structs: out = out - in. + * Out is assumed to be >= in. + */ +static void +tvsub(struct timeval *out, struct timeval *in) +{ + + if ((out->tv_usec -= in->tv_usec) < 0) { + --out->tv_sec; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + +/* + * Construct an Internet address representation. + * If the nflag has been supplied, give + * numeric value, otherwise try for symbolic name. + */ +static char * +inetname(struct in_addr in) +{ + char *cp; + struct hostent *hp; + static int first = 1; + static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1]; + + if (first && !nflag) { + + first = 0; + if (gethostname(domain, sizeof(domain) - 1) < 0) + domain[0] = '\0'; + else { + cp = strchr(domain, '.'); + if (cp == NULL) { + hp = gethostbyname(domain); + if (hp != NULL) + cp = strchr(hp->h_name, '.'); + } + if (cp == NULL) + domain[0] = '\0'; + else { + ++cp; + (void)strlcpy(domain, cp, sizeof(domain)); + } + } + } + if (!nflag && in.s_addr != INADDR_ANY) { + hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); + if (hp != NULL) { + if ((cp = strchr(hp->h_name, '.')) != NULL && + strcmp(cp + 1, domain) == 0) + *cp = '\0'; + (void)strlcpy(line, hp->h_name, sizeof(line)); + return line; + } + } + return inet_ntoa(in); +} + +static struct hostinfo * +gethostinfo(char *hname) +{ + int n; + struct hostent *hp; + struct hostinfo *hi; + char **p; + u_int32_t *ap; + struct in_addr addr; + + hi = calloc(1, sizeof(*hi)); + if (hi == NULL) + err(1, "calloc"); + if (inet_aton(hname, &addr) != 0) { + hi->name = strdup(hname); + if (!hi->name) + err(1, "strdup"); + hi->n = 1; + hi->addrs = calloc(1, sizeof(hi->addrs[0])); + if (hi->addrs == NULL) + err(1, "calloc"); + hi->addrs[0] = addr.s_addr; + return hi; + } + + hp = gethostbyname(hname); + if (hp == NULL) + errx(1, "unknown host %s", hname); + if (hp->h_addrtype != AF_INET || hp->h_length != 4) + errx(1, "bad host %s", hname); + hi->name = strdup(hp->h_name); + if (!hi->name) + err(1, "strdup"); + for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p) + continue; + hi->n = n; + hi->addrs = calloc(n, sizeof(hi->addrs[0])); + if (hi->addrs == NULL) + err(1, "calloc"); + for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p) + memcpy(ap, *p, sizeof(*ap)); + return hi; +} + +static void +freehostinfo(struct hostinfo *hi) +{ + if (hi->name != NULL) { + free(hi->name); + hi->name = NULL; + } + free(hi->addrs); + free(hi); +} + +static void +getaddr(u_int32_t *ap, char *hname) +{ + struct hostinfo *hi; + + hi = gethostinfo(hname); + *ap = hi->addrs[0]; + freehostinfo(hi); +} + +static void +setsin(struct sockaddr_in *sin, u_int32_t addr) +{ + + memset(sin, 0, sizeof(*sin)); +#ifdef HAVE_SOCKADDR_SA_LEN + sin->sin_len = sizeof(*sin); +#endif + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = addr; +} + +/* String to value with optional min and max. Handles decimal and hex. */ +static int +str2val(const char *str, const char *what, int mi, int ma) +{ + const char *cp; + long val; + char *ep; + + errno = 0; + ep = NULL; + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { + cp = str + 2; + val = strtol(cp, &ep, 16); + } else + val = strtol(str, &ep, 10); + if (errno || str[0] == '\0' || *ep != '\0') + errx(1, "\"%s\" bad value for %s", str, what); + if (val < mi && mi >= 0) { + if (mi == 0) + errx(1, "%s must be >= %d", what, mi); + else + errx(1, "%s must be > %d", what, mi - 1); + } + if (val > ma && ma >= 0) + errx(1, "%s must be <= %d", what, ma); + return (int)val; +} + +__dead void +usage(void) +{ + extern char version[]; + + Fprintf(stderr, "Version %s\n", version); + Fprintf(stderr, "Usage: %s [-adDFPIlMnrvx] [-g gateway] [-i iface] \ +[-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\ +[-w waittime] [-z pausemsecs] [-A as_server] host [packetlen]\n", + getprogname()); + exit(1); +} + +/* + * Received ICMP unreachable (fragmentation required and DF set). + * If the ICMP error was from a "new" router, it'll contain the next-hop + * MTU that we should use next. Otherwise we'll just keep going in the + * mtus[] table, trying until we hit a valid MTU. + */ + + +void +frag_err() +{ + int i; + + if (nextmtu > 0 && nextmtu < packlen) { + Printf("\nfragmentation required and DF set, " + "next hop MTU = %d\n", + nextmtu); + packlen = nextmtu; + for (i = 0; mtus[i] > 0; i++) { + if (mtus[i] < nextmtu) { + mtuptr = &mtus[i]; /* next one to try */ + break; + } + } + } else { + Printf("\nfragmentation required and DF set. "); + if (nextmtu) + Printf("\nBogus next hop MTU = %d > last MTU = %d. ", + nextmtu, packlen); + packlen = *mtuptr++; + Printf("Trying new MTU = %d\n", packlen); + } + resize_packet(); +} + +int +find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to) +{ + int sock; + struct sockaddr_in help; + socklen_t help_len; + + sock = prog_socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) return 0; + + help.sin_family = AF_INET; + /* + * At this point the port number doesn't matter + * since it only has to be greater than zero. + */ + help.sin_port = 42; + help.sin_addr.s_addr = to->sin_addr.s_addr; + if (prog_connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) { + (void)prog_close(sock); + return 0; + } + + help_len = sizeof(help); + if (prog_getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 || + help_len != sizeof(help) || + help.sin_addr.s_addr == INADDR_ANY) { + (void)prog_close(sock); + return 0; + } + + (void)prog_close(sock); + setsin(from, help.sin_addr.s_addr); + return 1; +} + +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +static int +setpolicy(int so, const char *policy) +{ + char *buf; + + buf = ipsec_set_policy(policy, strlen(policy)); + if (buf == NULL) { + warnx("%s", ipsec_strerror()); + return -1; + } + (void)prog_setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY, + buf, ipsec_get_policylen(buf)); + + free(buf); + + return 0; +} +#endif +#endif + diff --git a/usr.sbin/traceroute/traceroute_hostops.c b/usr.sbin/traceroute/traceroute_hostops.c new file mode 100644 index 000000000..98016b8e2 --- /dev/null +++ b/usr.sbin/traceroute/traceroute_hostops.c @@ -0,0 +1,55 @@ +/* $NetBSD: traceroute_hostops.c,v 1.1 2010/12/15 00:09:41 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: traceroute_hostops.c,v 1.1 2010/12/15 00:09:41 pooka Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include + +#include +#include + +#include "prog_ops.h" + +const struct prog_ops prog_ops = { + .op_socket = socket, + .op_setsockopt = setsockopt, + .op_shutdown = shutdown, + .op_poll = poll, + .op_recvfrom = recvfrom, + .op_sendto = sendto, + .op_close = close, + .op_connect = connect, + .op_getsockname = getsockname, + .op_sysctl = sysctl, +}; diff --git a/usr.sbin/traceroute/traceroute_rumpops.c b/usr.sbin/traceroute/traceroute_rumpops.c new file mode 100644 index 000000000..f90cd17f6 --- /dev/null +++ b/usr.sbin/traceroute/traceroute_rumpops.c @@ -0,0 +1,59 @@ +/* $NetBSD: traceroute_rumpops.c,v 1.1 2010/12/15 00:09:42 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: traceroute_rumpops.c,v 1.1 2010/12/15 00:09:42 pooka Exp $"); +#endif /* !lint */ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "prog_ops.h" + +const struct prog_ops prog_ops = { + .op_init = rumpclient_init, + + .op_socket = rump_sys_socket, + .op_setsockopt= rump_sys_setsockopt, + .op_shutdown = rump_sys_shutdown, + .op_poll = rump_sys_poll, + .op_recvfrom = rump_sys_recvfrom, + .op_sendto = rump_sys_sendto, + .op_close = rump_sys_close, + .op_connect = rump_sys_connect, + .op_getsockname=rump_sys_getsockname, + .op_sysctl = rump_sys___sysctl, +}; diff --git a/usr.sbin/traceroute/trrt2netbsd b/usr.sbin/traceroute/trrt2netbsd new file mode 100755 index 000000000..bfe88f9c1 --- /dev/null +++ b/usr.sbin/traceroute/trrt2netbsd @@ -0,0 +1,272 @@ +#!/usr/local/bin/perl +# +# $NetBSD: trrt2netbsd,v 1.4 1999/06/16 20:47:57 is Exp $ +# +# Perl script to convert a standard distribution directory for traceroute into +# a NetBSD source tree. +# +# This is done as a script so that as each distribution is released, +# only changes from the previous one need to be dealt with as +# modifications to this script and related files. This should +# reduce the cost of updating from a new release of traceroute by an +# order of magnitude (or more?) +# +# This script requires two environment variables set: +# SRCDIR - traceroute source directory +# TARGETDIR - name of the high level directory to make +# +# Written by Christos Zoulas Oct 2nd, 1997 for traceroute-1.4a5 +# + +$version = "1.4a5"; + +# definitions ... + +@subdirs = ("usr.sbin/traceroute"); + +@trrtf = ("ifaddrlist.c", "savestr.c", "traceroute.c"); + +@trrthf = ("gnuc.h", "ifaddrlist.h", "savestr.h"); + +@trrtmf = ("traceroute.8"); +@trrtdf = ("CHANGES", "README"); +@trrtaf = ("mean.awk", "median.awk"); + + +# sed edit list: file, sed-program +%sedlist = (); + +# +# Utility Subroutines +# + +sub makedir { + system("mkdir -p @_"); +} + +# &fixrcs (fromfile, tofile); +sub fixrcs +{ + my ($f, $t) = @_; + my @keywords = ("Author", "Date", "Header", "Id", "Locker", "Log", + "Name", "RCSfile", "Revision", "Source", "State"); + my $state = 0; + my $hdr = 0; + + open(IFILE, "<$f") || die "Cannot open $f"; + open(OFILE, ">$t") || die "Cannot create $t"; + + if ($t =~ /.*\.[0-9]/) { + print OFILE '.\\" $', 'NetBSD', '$', "\n.\\\"", "\n"; + } + elsif ($t =~ /.*\.[ch]/) { + print OFILE "/*\t", '$', 'NetBSD', '$', "\t*/\n\n"; + } + elsif ($t =~ /.*\.[yl]/) { + $hdr = 1; + } + else { + print OFILE '$', 'NetBSD', '$', "\n"; + } + while () { + if ($hdr == 1) { + if (/%{/) { + print OFILE "%{\n/*\t", '$', 'NetBSD', '$', "\t*/\n\n"; + $hdr = 0; + next; + } + } + if ($state == 2) { + if (/#endif/) { + print OFILE "#else\n__RCSID(", '"$', 'NetBSD', '$"', + ");\n#endif\n"; + $state = 0; + } + } + if ($state == 1) { + print OFILE "#if 0\n"; + $state = 2; + } + if (/#ifndef lint/) { + print OFILE "#include \n"; + $state = 1; + } + foreach $key (@keywords) { + s/\$$key\$/$key/g; + s/\$$key:(.*)\$/$key:$1/g; + } + print OFILE $_; + } + close(IFILE) || die "closing input file"; + close(OFILE) || die "closing output file"; +} + +# ©files (fromdir, todir, list of files); +sub copyfiles { + local ($fdir, $tdir, @list) = @_; + local ($f); + + foreach $f (@list) { + print " $fdir/$f --> $tdir/$f\n"; + &fixrcs("$fdir/$f", "$tdir/$f"); + } +} + +# ©file (fromfile, tofile); +sub copyfile { + local ($f, $t) = @_; + + print " $f --> $t\n"; + system ("cp $f $t"); +} + +sub uniq { + local (@inlist) = @_; + local (@outlist); + + @outlist = ($inlist[0]); + for ( $i=1; $i < @inlist; $i++ ) { + if ($inlist[$i] ne $inlist[$i-1]) { + push (@outlist, $inlist[$i]); + } + } + + @outlist; +} + +sub dumpsrcs { + local (@names) = @_; + local ($count); + + $count = 0; + while ($f = pop(@names)) { + print ODATA "$f "; + if ($count == 5 && @names > 0) { + print ODATA "\\\n"; + $count = 0; + } else { + $count += 1; + } + } + if ($count != 0) { + print ODATA "\n"; + } +} + +# +# Main program. +# + +$srcdir = $ENV{'SRCDIR'}; +$targetdir = $ENV{'TARGETDIR'}; +$incdirs = "-I. -I$srcdir/config -I$srcdir"; + +if (!$srcdir | !targetdir) { + die "You must define the environment variables SRCDIR and TARGETDIR.\n" +} +print "Making the NetBSD directory tree.\n"; +foreach $f (@subdirs) { + print " -->$f\n"; + makedir ("$targetdir/$f"); +} + +print "Populating the usr.sbin/traceroute directory.\n"; +©files ("$srcdir", "$targetdir/usr.sbin/traceroute", @trrtf, @trrthf, @trrtdf, + @trrtmf, @trrtaf); + +# +# Build makefiles +# + +$first = "True"; +while ($line = ) { + chop ($line); + if (substr($line,0,2) eq "%%") { + @cmd = split (/ /,$line); + if ($cmd[1] eq "file") { + print "Building $targetdir/$cmd[2]\n"; + if ($first eq "") { + close (ODATA); + } else { + $first = ""; + } + open (ODATA, ">$targetdir/$cmd[2]") || + die "Could not create $targetdir/$cmd[2]"; + } elsif ($cmd[1] eq "awks") { + print " Defining AWKS\n"; + if ($first) { + die "Data file must start with a %% file!"; + } + print ODATA "AWKS=\t"; + &dumpsrcs (@trrtaf); + } elsif ($cmd[1] eq "srcs") { + print " Defining SRCS\n"; + if ($first) { + die "Data file must start with a %% file!"; + } + print ODATA "SRCS=\t"; + &dumpsrcs (@trrtf); + } elsif ($cmd[1] eq "man") { + print " Defining MAN\n"; + if ($first) { + die "Data file must start with a %% file!"; + } + print ODATA "MAN=\t"; + &dumpsrcs (@trrtmf); + } elsif ($cmd[1] eq "version") { + print " Defining VERSION\n"; + print ODATA "char version[] = \"$version\";"; + } elsif ($cmd[1] eq "NetBSD") { + if ($first) { + die "Data section must start with a %% file!"; + } + print ODATA "$cmd[2] \$"."NetBSD".": \$ $cmd[3]\n"; + } + } else { + if ($first) { + die "Data file must start with a %% file!"; + } + print ODATA "$line\n"; + } +} +close (ODATA); + +# +# Sed transformations of files +# +foreach $n (keys(%sedlist)) { + print "Modifying $n\n"; + system ("cd $targetdir; sed $sedlist{$n} $n > tmp; mv -f tmp $n"); +} + +# +# end of the script +# + +# what follows is the data for makefiles and other special files +# that need to be created. + +__END__ +%% file usr.sbin/traceroute/Makefile +%% NetBSD # + +WARNS?= 1 +PROG= traceroute +%% man + +CPPFLAGS+=-DHAVE_MALLOC_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SOCKIO_H=1 +CPPFLAGS+=-DHAVE_STRERROR=1 -DHAVE_SETLINEBUF=1 -DHAVE_SOCKADDR_SA_LEN=1 +CPPFLAGS+=-DHAVE_RAW_OPTIONS=1 + +BINOWN= root +BINMODE=4555 + +%% srcs +SRCS+= version.c + +%% awks + +.include +%% file usr.sbin/traceroute/version.c +%% NetBSD /* */ +%% version diff --git a/usr.sbin/traceroute/version.c b/usr.sbin/traceroute/version.c new file mode 100644 index 000000000..8f987c150 --- /dev/null +++ b/usr.sbin/traceroute/version.c @@ -0,0 +1,2 @@ +/* $NetBSD: version.c,v 1.3 2011/09/11 01:06:26 christos Exp $ */ +char version[] = "1.4a12";