]>
Commit | Line | Data |
---|---|---|
b7080c8e A |
1 | Tue Dec 27 06:24:24 PST 1988 |
2 | ||
3 | Traceroute is a system administrators utility to trace the route | |
4 | ip packets from the current system take in getting to some | |
5 | destination system. See the comments at the front of the | |
6 | program for a description of its use. | |
7 | ||
8 | This program | |
9 | ||
10 | a) can only be run by root (it uses raw ip sockets). | |
11 | ||
12 | b) REQUIRES A KERNEL MOD to the raw ip output code to run. | |
13 | ||
14 | If you want to hack on your kernel, my modified version of the | |
15 | routine rip_output (in file /sys/netinet/raw_ip.c) is attached. | |
16 | This code may or may not resemble the code in your kernel. | |
17 | It may offer you a place to start but I make no promises. | |
18 | If you do hack your kernel, remember to test everything that uses | |
19 | raw ip sockets (e.g., ping and egpup/gated) & make sure they still | |
20 | work. I wish you the best of luck and you're on your own. | |
21 | ||
22 | If your system has the ttl bug mentioned in the source, you | |
23 | might want to fix it while you're in the kernel. (This bug | |
24 | appears in all releases of BSD up to but not including 4.3tahoe. | |
25 | If your version of netinet/ip_icmp.c is any earlier than 7.3 | |
26 | (April, '87), it has the bug.) The fix is just to add the line | |
27 | ip->ip_ttl = MAXTTL; | |
28 | after the line | |
29 | ip->ip_src = t; | |
30 | (or anywhere before the call to icmp_send) in routine icmp_reflect. | |
31 | ||
32 | If you're running this on a pre-4.3bsd system (e.g., Sun 3.x, | |
33 | Ultrix) that strips ip headers from icmp messages, add -DARCHAIC | |
34 | to CFLAGS in the Makefile. Also note that rip_output contains | |
35 | a conditional for a 4.2/4.3 change in the location of a raw | |
36 | socket's protocol number. I've checked this under 4.3 & Sun OS | |
37 | 3.5 but you should double-check your system to make sure the | |
38 | appropriate branch of the #if is taken (check the line that | |
39 | assigned to ip->ip_p in your system's original rip_output). | |
40 | ||
41 | A couple of awk programs to massage the traceroute output are | |
42 | included. "mean.awk" and "median.awk" compute the mean and median | |
43 | time to each hop, respectively. I've found that something like | |
44 | ||
45 | traceroute -q 7 foo.somewhere >t | |
46 | awk -f median.awk t | graph | |
47 | ||
48 | can give you a quick picture of the bad spots on a long | |
49 | path (median is usually a better noise filter than mean). | |
50 | ||
51 | Enjoy. | |
52 | ||
53 | - Van Jacobson (van@helios.ee.lbl.gov) | |
54 | ||
55 | -------------------- rip_output from /sys/netinet/raw_ip.c | |
56 | rip_output(m, so) | |
57 | register struct mbuf *m; | |
58 | struct socket *so; | |
59 | { | |
60 | register struct ip *ip; | |
61 | int error; | |
62 | struct rawcb *rp = sotorawcb(so); | |
63 | struct sockaddr_in *sin; | |
64 | #if BSD>=43 | |
65 | short proto = rp->rcb_proto.sp_protocol; | |
66 | #else | |
67 | short proto = so->so_proto->pr_protocol; | |
68 | #endif | |
69 | /* | |
70 | * if the protocol is IPPROTO_RAW, the user handed us a | |
71 | * complete IP packet. Otherwise, allocate an mbuf for a | |
72 | * header and fill it in as needed. | |
73 | */ | |
74 | if (proto != IPPROTO_RAW) { | |
75 | /* | |
76 | * Calculate data length and get an mbuf | |
77 | * for IP header. | |
78 | */ | |
79 | int len = 0; | |
80 | struct mbuf *m0; | |
81 | ||
82 | for (m0 = m; m; m = m->m_next) | |
83 | len += m->m_len; | |
84 | ||
85 | m = m_get(M_DONTWAIT, MT_HEADER); | |
86 | if (m == 0) { | |
87 | m = m0; | |
88 | error = ENOBUFS; | |
89 | goto bad; | |
90 | } | |
91 | m->m_off = MMAXOFF - sizeof(struct ip); | |
92 | m->m_len = sizeof(struct ip); | |
93 | m->m_next = m0; | |
94 | ||
95 | ip = mtod(m, struct ip *); | |
96 | ip->ip_tos = 0; | |
97 | ip->ip_off = 0; | |
98 | ip->ip_p = proto; | |
99 | ip->ip_len = sizeof(struct ip) + len; | |
100 | ip->ip_ttl = MAXTTL; | |
101 | } else | |
102 | ip = mtod(m, struct ip *); | |
103 | ||
104 | if (rp->rcb_flags & RAW_LADDR) { | |
105 | sin = (struct sockaddr_in *)&rp->rcb_laddr; | |
106 | if (sin->sin_family != AF_INET) { | |
107 | error = EAFNOSUPPORT; | |
108 | goto bad; | |
109 | } | |
110 | ip->ip_src.s_addr = sin->sin_addr.s_addr; | |
111 | } else | |
112 | ip->ip_src.s_addr = 0; | |
113 | ||
114 | ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; | |
115 | ||
116 | #if BSD>=43 | |
117 | return (ip_output(m, rp->rcb_options, &rp->rcb_route, | |
118 | (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); | |
119 | #else | |
120 | return (ip_output(m, (struct mbuf *)0, &rp->rcb_route, | |
121 | (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); | |
122 | #endif | |
123 | bad: | |
124 | m_freem(m); | |
125 | return (error); | |
126 | } |