new statistics
[unix-history] / usr / src / usr.bin / netstat / route.c
CommitLineData
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 8static 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
26extern int kmem;
27extern int nflag;
f7c99b06
MK
28extern char *routename(), *netname(), *ns_print(), *plural();
29extern char *malloc();
3537c4ea
SL
30
31/*
32 * Definitions for showing gateway flags.
33 */
34struct 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
48routepr(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");
82again:
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
156char *
157routename(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 */
201char *
202netname(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 */
260rt_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 283short ns_nullh[] = {0,0,0};
f1fbb01b
KS
284short ns_bh[] = {-1,-1,-1};
285
286char *
287ns_print(sns)
288struct 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
331char *
332ns_phost(sns)
333struct 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}
347upHex(p0)
348char *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}