?? traceroute.c
字號:
/*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Van Jacobson. * * Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001 * 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 University of * California, Berkeley and its contributors. * 4. 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. *//* * traceroute host - trace the route ip packets follow going to "host". * 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.) * * 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@helios.ee.lbl.gov) * Tue Dec 20 03:50:13 PST 1988 */#undef BB_FEATURE_TRACEROUTE_VERBOSE//#define BB_FEATURE_TRACEROUTE_VERBOSE#undef BB_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <endian.h>#include <arpa/inet.h>#include <netinet/udp.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h> /* It turns out that libc5 doesn't have proper icmp support * built into it header files, so we have to supplement it */#if __GNU_LIBRARY__ < 5static const int ICMP_MINLEN = 8; /* abs minimum */struct icmp_ra_addr{ u_int32_t ira_addr; u_int32_t ira_preference;};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 checksum of struct */ union { u_char ih_pptr; /* ICMP_PARAMPROB */ struct in_addr ih_gwaddr; /* gateway address */ struct ih_idseq /* echo datagram */ { u_int16_t icd_id; u_int16_t icd_seq; } ih_idseq; u_int32_t ih_void; /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ struct ih_pmtu { u_int16_t ipm_void; u_int16_t ipm_nextmtu; } ih_pmtu; struct ih_rtradv { u_int8_t irt_num_addrs; u_int8_t irt_wpa; u_int16_t irt_lifetime; } ih_rtradv; } icmp_hun;#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 { u_int32_t its_otime; u_int32_t its_rtime; u_int32_t its_ttime; } id_ts; struct { struct ip idi_ip; /* options and then 64 bits of data */ } id_ip; struct icmp_ra_addr id_radv; u_int32_t id_mask; u_int8_t id_data[1]; } icmp_dun;#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_radv#define icmp_mask icmp_dun.id_mask#define icmp_data icmp_dun.id_data};#define ICMP_MINLEN 8 /* abs minimum */#define ICMP_UNREACH 3 /* dest unreachable, codes: */#define ICMP_TIMXCEED 11 /* time exceeded, code: */#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */#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 */#endif#define MAXPACKET 65535 /* max ip packet size */#ifndef MAXHOSTNAMELEN#define MAXHOSTNAMELEN 64#endif/* * format of a (udp) probe packet. */struct opacket { struct ip ip; struct udphdr udp; u_char seq; /* sequence number of this packet */ u_char ttl; /* ttl packet left with */ struct timeval tv; /* time packet left */};/* * Definitions for internet protocol version 4. * Per RFC 791, September 1981. */#define IPVERSION 4#include "busybox.h"static u_char packet[512]; /* last inbound (icmp) packet */static struct opacket *outpacket; /* last output (udp) packet */static int s; /* receive (icmp) socket file descriptor */static int sndsock; /* send (udp) socket file descriptor */static struct sockaddr whereto; /* Who to try to reach */static int datalen; /* How much data */static char *hostname;static int max_ttl = 30;static u_short ident;static u_short port = 32768+666; /* start udp dest port # for probe packets */#ifdef BB_FEATURE_TRACEROUTE_VERBOSEstatic int verbose;#endifstatic int waittime = 5; /* time to wait for response (in seconds) */static int nflag; /* print addresses numerically *//* * Construct an Internet address representation. * If the nflag has been supplied, give * numeric value, otherwise try for symbolic name. */static inline voidinetname(struct sockaddr_in *from){ char *cp; struct hostent *hp; static char domain[MAXHOSTNAMELEN + 1]; static int first = 1; const char *ina; if (first && !nflag) { first = 0; if (getdomainname(domain, MAXHOSTNAMELEN) != 0) domain[0] = 0; } cp = 0; if (!nflag && from->sin_addr.s_addr != INADDR_ANY) { hp = gethostbyaddr((char *)&(from->sin_addr), sizeof (from->sin_addr), AF_INET); if (hp) { if ((cp = strchr(hp->h_name, '.')) && !strcmp(cp + 1, domain)) *cp = 0; cp = (char *)hp->h_name; } } ina = inet_ntoa(from->sin_addr); if (nflag) printf(" %s", ina); else printf(" %s (%s)", (cp ? cp : ina), ina);}static inline voidprint(u_char *buf, int cc, struct sockaddr_in *from){ struct ip *ip; int hlen; ip = (struct ip *) buf; hlen = ip->ip_hl << 2; cc -= hlen; inetname(from);#ifdef BB_FEATURE_TRACEROUTE_VERBOSE if (verbose) printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));#endif}static inline doubledeltaT(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);}static inline intwait_for_reply(int sock, struct sockaddr_in *from, int reset_timer){ fd_set fds; static struct timeval wait; int cc = 0; int fromlen = sizeof (*from); FD_ZERO(&fds); FD_SET(sock, &fds); if (reset_timer) { /* * traceroute could hang if someone else has a ping * running and our ICMP reply gets dropped but we don't * realize it because we keep waking up to handle those * other ICMP packets that keep coming in. To fix this, * "reset_timer" will only be true if the last packet that * came in was for us or if this is the first time we're * waiting for a reply since sending out a probe. Note * that this takes advantage of the select() feature on * Linux where the remaining timeout is written to the * struct timeval area. */ wait.tv_sec = waittime; wait.tv_usec = 0; } if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0) cc=recvfrom(s, (char *)packet, sizeof(packet), 0, (struct sockaddr *)from, &fromlen); return(cc);}#ifdef BB_FEATURE_TRACEROUTE_VERBOSE/* * Convert an ICMP "type" field to a printable string. */static inline const char *pr_type(u_char t){
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -