Commit | Line | Data |
---|---|---|
5ff67f98 DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
3537c4ea | 7 | #ifndef lint |
bd91d3f9 | 8 | static char sccsid[] = "@(#)route.c 5.8 (Berkeley) 86/12/15"; |
f1fbb01b | 9 | #endif |
3537c4ea | 10 | |
f7c99b06 MK |
11 | #include <stdio.h> |
12 | #include <strings.h> | |
13 | ||
6c5bed6c | 14 | #include <sys/param.h> |
3537c4ea SL |
15 | #include <sys/socket.h> |
16 | #include <sys/mbuf.h> | |
44906619 | 17 | |
3537c4ea | 18 | #include <net/if.h> |
3537c4ea | 19 | #include <net/route.h> |
44906619 SL |
20 | #include <netinet/in.h> |
21 | ||
f1fbb01b KS |
22 | #include <netns/ns.h> |
23 | ||
3537c4ea SL |
24 | #include <netdb.h> |
25 | ||
26 | extern int kmem; | |
27 | extern int nflag; | |
f7c99b06 MK |
28 | extern char *routename(), *netname(), *ns_print(), *plural(); |
29 | extern char *malloc(); | |
3537c4ea SL |
30 | |
31 | /* | |
32 | * Definitions for showing gateway flags. | |
33 | */ | |
34 | struct bits { | |
35 | short b_mask; | |
36 | char b_val; | |
37 | } bits[] = { | |
38 | { RTF_UP, 'U' }, | |
39 | { RTF_GATEWAY, 'G' }, | |
40 | { RTF_HOST, 'H' }, | |
6c5bed6c | 41 | { RTF_DYNAMIC, 'D' }, |
3537c4ea SL |
42 | { 0 } |
43 | }; | |
44 | ||
45 | /* | |
46 | * Print routing tables. | |
47 | */ | |
f508555e MK |
48 | routepr(hostaddr, netaddr, hashsizeaddr) |
49 | off_t hostaddr, netaddr, hashsizeaddr; | |
3537c4ea SL |
50 | { |
51 | struct mbuf mb; | |
52 | register struct rtentry *rt; | |
53 | register struct mbuf *m; | |
54 | register struct bits *p; | |
3537c4ea | 55 | char name[16], *flags; |
f508555e | 56 | struct mbuf **routehash; |
3537c4ea | 57 | struct ifnet ifnet; |
f508555e MK |
58 | int hashsize; |
59 | int i, doinghost = 1; | |
3537c4ea SL |
60 | |
61 | if (hostaddr == 0) { | |
62 | printf("rthost: symbol not in namelist\n"); | |
63 | return; | |
64 | } | |
65 | if (netaddr == 0) { | |
66 | printf("rtnet: symbol not in namelist\n"); | |
67 | return; | |
68 | } | |
f508555e MK |
69 | if (hashsizeaddr == 0) { |
70 | printf("rthashsize: symbol not in namelist\n"); | |
71 | return; | |
72 | } | |
73 | klseek(kmem, hashsizeaddr, 0); | |
f7c99b06 | 74 | read(kmem, (char *)&hashsize, sizeof (hashsize)); |
f508555e | 75 | routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) ); |
3537c4ea | 76 | klseek(kmem, hostaddr, 0); |
f7c99b06 | 77 | read(kmem, (char *)routehash, hashsize*sizeof (struct mbuf *)); |
3537c4ea | 78 | printf("Routing tables\n"); |
2ff355d6 | 79 | printf("%-20.20s %-20.20s %-8.8s %-6.6s %-10.10s %s\n", |
3537c4ea SL |
80 | "Destination", "Gateway", |
81 | "Flags", "Refcnt", "Use", "Interface"); | |
82 | again: | |
f508555e | 83 | for (i = 0; i < hashsize; i++) { |
3537c4ea SL |
84 | if (routehash[i] == 0) |
85 | continue; | |
86 | m = routehash[i]; | |
87 | while (m) { | |
88 | struct sockaddr_in *sin; | |
89 | ||
f7c99b06 MK |
90 | klseek(kmem, (off_t)m, 0); |
91 | read(kmem, (char *)&mb, sizeof (mb)); | |
3537c4ea | 92 | rt = mtod(&mb, struct rtentry *); |
2ff355d6 MK |
93 | if ((unsigned)rt < (unsigned)&mb || |
94 | (unsigned)rt >= (unsigned)(&mb + 1)) { | |
95 | printf("???\n"); | |
96 | return; | |
97 | } | |
98 | ||
f1fbb01b | 99 | switch(rt->rt_dst.sa_family) { |
2ff355d6 MK |
100 | case AF_INET: |
101 | sin = (struct sockaddr_in *)&rt->rt_dst; | |
102 | printf("%-20.20s ", | |
103 | (sin->sin_addr.s_addr == 0) ? "default" : | |
104 | (rt->rt_flags & RTF_HOST) ? | |
105 | routename(sin->sin_addr) : | |
f7c99b06 | 106 | netname(sin->sin_addr, 0L)); |
2ff355d6 MK |
107 | sin = (struct sockaddr_in *)&rt->rt_gateway; |
108 | printf("%-20.20s ", routename(sin->sin_addr)); | |
109 | break; | |
110 | case AF_NS: | |
111 | printf("%-20s ", | |
112 | ns_print((struct sockaddr_ns *)&rt->rt_dst)); | |
113 | printf("%-20s ", | |
114 | ns_print((struct sockaddr_ns *)&rt->rt_gateway)); | |
115 | break; | |
116 | default: | |
117 | { | |
118 | u_short *s = (u_short *)rt->rt_dst.sa_data; | |
119 | printf("(%d)%x %x %x %x %x %x %x ", | |
120 | rt->rt_dst.sa_family, | |
121 | s[0], s[1], s[2], s[3], s[4], s[5], s[6]); | |
122 | s = (u_short *)rt->rt_gateway.sa_data; | |
123 | printf("(%d)%x %x %x %x %x %x %x ", | |
124 | rt->rt_gateway.sa_family, | |
125 | s[0], s[1], s[2], s[3], s[4], s[5], s[6]); | |
126 | } | |
f1fbb01b | 127 | } |
3537c4ea SL |
128 | for (flags = name, p = bits; p->b_mask; p++) |
129 | if (p->b_mask & rt->rt_flags) | |
130 | *flags++ = p->b_val; | |
131 | *flags = '\0'; | |
132 | printf("%-8.8s %-6d %-10d ", name, | |
133 | rt->rt_refcnt, rt->rt_use); | |
134 | if (rt->rt_ifp == 0) { | |
135 | putchar('\n'); | |
136 | m = mb.m_next; | |
137 | continue; | |
138 | } | |
f7c99b06 MK |
139 | klseek(kmem, (off_t)rt->rt_ifp, 0); |
140 | read(kmem, (char *)&ifnet, sizeof (ifnet)); | |
141 | klseek(kmem, (off_t)ifnet.if_name, 0); | |
3537c4ea SL |
142 | read(kmem, name, 16); |
143 | printf("%s%d\n", name, ifnet.if_unit); | |
144 | m = mb.m_next; | |
145 | } | |
146 | } | |
147 | if (doinghost) { | |
148 | klseek(kmem, netaddr, 0); | |
f7c99b06 | 149 | read(kmem, (char *)routehash, hashsize*sizeof (struct mbuf *)); |
3537c4ea SL |
150 | doinghost = 0; |
151 | goto again; | |
152 | } | |
f7c99b06 | 153 | free((char *)routehash); |
3537c4ea SL |
154 | } |
155 | ||
156 | char * | |
157 | routename(in) | |
158 | struct in_addr in; | |
159 | { | |
6b9930b0 | 160 | register char *cp; |
3537c4ea | 161 | static char line[50]; |
40f48772 | 162 | struct hostent *hp; |
6c5bed6c MK |
163 | static char domain[MAXHOSTNAMELEN + 1]; |
164 | static int first = 1; | |
165 | char *index(); | |
3537c4ea | 166 | |
6c5bed6c MK |
167 | if (first) { |
168 | first = 0; | |
169 | if (gethostname(domain, MAXHOSTNAMELEN) == 0 && | |
170 | (cp = index(domain, '.'))) | |
171 | (void) strcpy(domain, cp + 1); | |
172 | else | |
173 | domain[0] = 0; | |
174 | } | |
6b9930b0 | 175 | cp = 0; |
3537c4ea | 176 | if (!nflag) { |
f7c99b06 | 177 | hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), |
cab3a575 | 178 | AF_INET); |
6c5bed6c MK |
179 | if (hp) { |
180 | if ((cp = index(hp->h_name, '.')) && | |
181 | !strcmp(cp + 1, domain)) | |
182 | *cp = 0; | |
cab3a575 | 183 | cp = hp->h_name; |
6c5bed6c | 184 | } |
3537c4ea SL |
185 | } |
186 | if (cp) | |
187 | strcpy(line, cp); | |
188 | else { | |
cab3a575 MK |
189 | #define C(x) ((x) & 0xff) |
190 | in.s_addr = ntohl(in.s_addr); | |
191 | sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), | |
192 | C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); | |
193 | } | |
194 | return (line); | |
195 | } | |
196 | ||
197 | /* | |
198 | * Return the name of the network whose address is given. | |
199 | * The address is assumed to be that of a net or subnet, not a host. | |
200 | */ | |
201 | char * | |
202 | netname(in, mask) | |
203 | struct in_addr in; | |
204 | u_long mask; | |
205 | { | |
206 | char *cp = 0; | |
207 | static char line[50]; | |
208 | struct netent *np = 0; | |
209 | u_long net; | |
210 | register i; | |
6c5bed6c | 211 | int subnetshift; |
cab3a575 MK |
212 | |
213 | in.s_addr = ntohl(in.s_addr); | |
214 | if (!nflag && in.s_addr) { | |
6c5bed6c MK |
215 | if (mask == 0) { |
216 | if (IN_CLASSA(i)) { | |
217 | mask = IN_CLASSA_NET; | |
218 | subnetshift = 8; | |
219 | } else if (IN_CLASSB(i)) { | |
220 | mask = IN_CLASSB_NET; | |
221 | subnetshift = 8; | |
222 | } else { | |
223 | mask = IN_CLASSC_NET; | |
224 | subnetshift = 4; | |
225 | } | |
cab3a575 | 226 | /* |
6c5bed6c MK |
227 | * If there are more bits than the standard mask |
228 | * would suggest, subnets must be in use. | |
229 | * Guess at the subnet mask, assuming reasonable | |
230 | * width subnet fields. | |
cab3a575 | 231 | */ |
6c5bed6c MK |
232 | while (in.s_addr &~ mask) |
233 | mask = (long)mask >> subnetshift; | |
cab3a575 | 234 | } |
6c5bed6c MK |
235 | net = in.s_addr & mask; |
236 | while ((mask & 1) == 0) | |
237 | mask >>= 1, net >>= 1; | |
238 | np = getnetbyaddr(net, AF_INET); | |
cab3a575 MK |
239 | if (np) |
240 | cp = np->n_name; | |
f7c99b06 | 241 | } |
cab3a575 MK |
242 | if (cp) |
243 | strcpy(line, cp); | |
244 | else if ((in.s_addr & 0xffffff) == 0) | |
245 | sprintf(line, "%u", C(in.s_addr >> 24)); | |
246 | else if ((in.s_addr & 0xffff) == 0) | |
247 | sprintf(line, "%u.%u", C(in.s_addr >> 24) , C(in.s_addr >> 16)); | |
248 | else if ((in.s_addr & 0xff) == 0) | |
249 | sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), | |
250 | C(in.s_addr >> 16), C(in.s_addr >> 8)); | |
251 | else | |
252 | sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), | |
253 | C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); | |
3537c4ea SL |
254 | return (line); |
255 | } | |
6c5bed6c | 256 | |
bbd2d21e SL |
257 | /* |
258 | * Print routing statistics | |
259 | */ | |
260 | rt_stats(off) | |
261 | off_t off; | |
262 | { | |
263 | struct rtstat rtstat; | |
264 | ||
265 | if (off == 0) { | |
266 | printf("rtstat: symbol not in namelist\n"); | |
267 | return; | |
268 | } | |
269 | klseek(kmem, off, 0); | |
270 | read(kmem, (char *)&rtstat, sizeof (rtstat)); | |
271 | printf("routing:\n"); | |
bd91d3f9 | 272 | printf("\t%u bad routing redirect%s\n", |
bbd2d21e | 273 | rtstat.rts_badredirect, plural(rtstat.rts_badredirect)); |
bd91d3f9 | 274 | printf("\t%u dynamically created route%s\n", |
bbd2d21e | 275 | rtstat.rts_dynamic, plural(rtstat.rts_dynamic)); |
bd91d3f9 | 276 | printf("\t%u new gateway%s due to redirects\n", |
bbd2d21e | 277 | rtstat.rts_newgateway, plural(rtstat.rts_newgateway)); |
bd91d3f9 | 278 | printf("\t%u destination%s found unreachable\n", |
bbd2d21e | 279 | rtstat.rts_unreach, plural(rtstat.rts_unreach)); |
bd91d3f9 | 280 | printf("\t%u use%s of a wildcard route\n", |
bbd2d21e SL |
281 | rtstat.rts_wildcard, plural(rtstat.rts_wildcard)); |
282 | } | |
2ff355d6 | 283 | short ns_nullh[] = {0,0,0}; |
f1fbb01b KS |
284 | short ns_bh[] = {-1,-1,-1}; |
285 | ||
286 | char * | |
287 | ns_print(sns) | |
288 | struct sockaddr_ns *sns; | |
289 | { | |
2ff355d6 MK |
290 | struct ns_addr work; |
291 | union { union ns_net net_e; u_long long_e; } net; | |
292 | u_short port; | |
293 | static char mybuf[50], cport[10], chost[25]; | |
294 | char *host = ""; | |
f7c99b06 | 295 | register char *p; register u_char *q; |
f1fbb01b | 296 | |
2ff355d6 MK |
297 | work = sns->sns_addr; |
298 | port = ntohs(work.x_port); | |
299 | work.x_port = 0; | |
300 | net.net_e = work.x_net; | |
301 | if (ns_nullhost(work) && net.long_e == 0) { | |
302 | if (port ) { | |
303 | sprintf(mybuf, "*.%xH", port); | |
304 | upHex(mybuf); | |
305 | } else | |
306 | sprintf(mybuf, "*.*"); | |
307 | return (mybuf); | |
308 | } | |
f1fbb01b | 309 | |
2ff355d6 MK |
310 | if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) { |
311 | host = "any"; | |
312 | } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) { | |
313 | host = "*"; | |
314 | } else { | |
315 | q = work.x_host.c_host; | |
316 | sprintf(chost, "%02x%02x%02x%02x%02x%02xH", | |
317 | q[0], q[1], q[2], q[3], q[4], q[5]); | |
318 | for (p = chost; *p == '0' && p < chost + 12; p++); | |
319 | host = p; | |
f1fbb01b | 320 | } |
2ff355d6 MK |
321 | if (port) |
322 | sprintf(cport, ".%xH", htons(port)); | |
323 | else | |
324 | *cport = 0; | |
325 | ||
326 | sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport); | |
327 | upHex(mybuf); | |
f1fbb01b KS |
328 | return(mybuf); |
329 | } | |
2ff355d6 | 330 | |
f1fbb01b KS |
331 | char * |
332 | ns_phost(sns) | |
333 | struct sockaddr_ns *sns; | |
334 | { | |
2ff355d6 MK |
335 | struct sockaddr_ns work; |
336 | static union ns_net ns_zeronet; | |
337 | char *p; | |
338 | ||
339 | work = *sns; | |
340 | work.sns_addr.x_port = 0; | |
341 | work.sns_addr.x_net = ns_zeronet; | |
342 | ||
343 | p = ns_print(&work); | |
344 | if (strncmp("0H.", p, 3) == 0) p += 3; | |
345 | return(p); | |
346 | } | |
347 | upHex(p0) | |
348 | char *p0; | |
349 | { | |
350 | register char *p = p0; | |
351 | for (; *p; p++) switch (*p) { | |
352 | ||
353 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': | |
354 | *p += ('A' - 'a'); | |
355 | } | |
f1fbb01b | 356 | } |