xref: /original-bsd/usr.bin/netstat/route.c (revision e188a54c)
1 /*
2  * Copyright (c) 1983, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
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.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)route.c	5.14 (Berkeley) 06/29/88";
20 #endif /* not lint */
21 
22 #include <stdio.h>
23 #include <strings.h>
24 
25 #include <sys/param.h>
26 #include <sys/socket.h>
27 #include <sys/mbuf.h>
28 
29 #include <net/if.h>
30 #include <net/route.h>
31 #include <netinet/in.h>
32 
33 #include <netns/ns.h>
34 
35 #include <netdb.h>
36 
37 extern	int kmem;
38 extern	int nflag;
39 extern	char *routename(), *netname(), *ns_print(), *plural();
40 extern	char *malloc();
41 
42 /*
43  * Definitions for showing gateway flags.
44  */
45 struct bits {
46 	short	b_mask;
47 	char	b_val;
48 } bits[] = {
49 	{ RTF_UP,	'U' },
50 	{ RTF_GATEWAY,	'G' },
51 	{ RTF_HOST,	'H' },
52 	{ RTF_DYNAMIC,	'D' },
53 	{ RTF_MODIFIED,	'M' },
54 	{ 0 }
55 };
56 
57 /*
58  * Print routing tables.
59  */
60 routepr(hostaddr, netaddr, hashsizeaddr)
61 	off_t hostaddr, netaddr, hashsizeaddr;
62 {
63 	struct mbuf mb;
64 	register struct rtentry *rt;
65 	register struct mbuf *m;
66 	register struct bits *p;
67 	char name[16], *flags;
68 	struct mbuf **routehash;
69 	struct ifnet ifnet;
70 	int hashsize;
71 	int i, doinghost = 1;
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 	}
81 	if (hashsizeaddr == 0) {
82 		printf("rthashsize: symbol not in namelist\n");
83 		return;
84 	}
85 	klseek(kmem, hashsizeaddr, 0);
86 	read(kmem, (char *)&hashsize, sizeof (hashsize));
87 	routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) );
88 	klseek(kmem, hostaddr, 0);
89 	read(kmem, (char *)routehash, hashsize*sizeof (struct mbuf *));
90 	printf("Routing tables\n");
91 	printf("%-16.16s %-18.18s %-6.6s  %6.6s%8.8s  %s\n",
92 		"Destination", "Gateway",
93 		"Flags", "Refs", "Use", "Interface");
94 again:
95 	for (i = 0; i < hashsize; i++) {
96 		if (routehash[i] == 0)
97 			continue;
98 		m = routehash[i];
99 		while (m) {
100 			struct sockaddr_in *sin;
101 
102 			klseek(kmem, (off_t)m, 0);
103 			read(kmem, (char *)&mb, sizeof (mb));
104 			rt = mtod(&mb, struct rtentry *);
105 			if ((unsigned)rt < (unsigned)&mb ||
106 			    (unsigned)rt >= (unsigned)(&mb + 1)) {
107 				printf("???\n");
108 				return;
109 			}
110 
111 			switch(rt->rt_dst.sa_family) {
112 			case AF_INET:
113 				sin = (struct sockaddr_in *)&rt->rt_dst;
114 				printf("%-16.16s ",
115 				    (sin->sin_addr.s_addr == 0) ? "default" :
116 				    (rt->rt_flags & RTF_HOST) ?
117 				    routename(sin->sin_addr) :
118 					netname(sin->sin_addr, 0L));
119 				sin = (struct sockaddr_in *)&rt->rt_gateway;
120 				printf("%-18.18s ", routename(sin->sin_addr));
121 				break;
122 			case AF_NS:
123 				printf("%-16s ",
124 				    ns_print((struct sockaddr_ns *)&rt->rt_dst));
125 				printf("%-18s ",
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 				}
139 			}
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';
144 			printf("%-6.6s %6d %8d ", name,
145 				rt->rt_refcnt, rt->rt_use);
146 			if (rt->rt_ifp == 0) {
147 				putchar('\n');
148 				m = mb.m_next;
149 				continue;
150 			}
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);
154 			read(kmem, name, 16);
155 			printf(" %.15s%d\n", name, ifnet.if_unit);
156 			m = mb.m_next;
157 		}
158 	}
159 	if (doinghost) {
160 		klseek(kmem, netaddr, 0);
161 		read(kmem, (char *)routehash, hashsize*sizeof (struct mbuf *));
162 		doinghost = 0;
163 		goto again;
164 	}
165 	free((char *)routehash);
166 }
167 
168 char *
169 routename(in)
170 	struct in_addr in;
171 {
172 	register char *cp;
173 	static char line[MAXHOSTNAMELEN + 1];
174 	struct hostent *hp;
175 	static char domain[MAXHOSTNAMELEN + 1];
176 	static int first = 1;
177 	char *index();
178 
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 	}
187 	cp = 0;
188 	if (!nflag) {
189 		hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
190 			AF_INET);
191 		if (hp) {
192 			if ((cp = index(hp->h_name, '.')) &&
193 			    !strcmp(cp + 1, domain))
194 				*cp = 0;
195 			cp = hp->h_name;
196 		}
197 	}
198 	if (cp)
199 		strncpy(line, cp, sizeof(line) - 1);
200 	else {
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  */
213 char *
214 netname(in, mask)
215 	struct in_addr in;
216 	u_long mask;
217 {
218 	char *cp = 0;
219 	static char line[MAXHOSTNAMELEN + 1];
220 	struct netent *np = 0;
221 	u_long net;
222 	register i;
223 	int subnetshift;
224 
225 	i = ntohl(in.s_addr);
226 	if (!nflag && i) {
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 			}
238 			/*
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.
243 			 */
244 			while (i &~ mask)
245 				mask = (long)mask >> subnetshift;
246 		}
247 		net = i & mask;
248 		while ((mask & 1) == 0)
249 			mask >>= 1, net >>= 1;
250 		np = getnetbyaddr(net, AF_INET);
251 		if (np)
252 			cp = np->n_name;
253 	}
254 	if (cp)
255 		strncpy(line, cp, sizeof(line) - 1);
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));
262 	else
263 		sprintf(line, "%u.%u.%u.%u", C(i >> 24),
264 			C(i >> 16), C(i >> 8), C(i));
265 	return (line);
266 }
267 
268 /*
269  * Print routing statistics
270  */
271 rt_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");
283 	printf("\t%u bad routing redirect%s\n",
284 		rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
285 	printf("\t%u dynamically created route%s\n",
286 		rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
287 	printf("\t%u new gateway%s due to redirects\n",
288 		rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
289 	printf("\t%u destination%s found unreachable\n",
290 		rtstat.rts_unreach, plural(rtstat.rts_unreach));
291 	printf("\t%u use%s of a wildcard route\n",
292 		rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
293 }
294 short ns_nullh[] = {0,0,0};
295 short ns_bh[] = {-1,-1,-1};
296 
297 char *
298 ns_print(sns)
299 struct sockaddr_ns *sns;
300 {
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 = "";
306 	register char *p; register u_char *q;
307 
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 	}
320 
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;
331 	}
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);
339 	return(mybuf);
340 }
341 
342 char *
343 ns_phost(sns)
344 struct sockaddr_ns *sns;
345 {
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 }
358 upHex(p0)
359 char *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 	}
367 }
368