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