xref: /netbsd-src/sbin/route/show.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
1 /*	$NetBSD: show.c,v 1.1 1996/11/15 18:01:41 gwr Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1988, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "from: @(#)route.c	8.3 (Berkeley) 3/9/94";
39 #else
40 static char *rcsid = "$NetBSD: show.c,v 1.1 1996/11/15 18:01:41 gwr Exp $";
41 #endif
42 #endif /* not lint */
43 
44 #include <sys/param.h>
45 #include <sys/protosw.h>
46 #include <sys/socket.h>
47 #include <sys/mbuf.h>
48 
49 #include <net/if.h>
50 #include <net/if_dl.h>
51 #include <net/if_types.h>
52 #include <net/route.h>
53 #include <netinet/in.h>
54 #include <netns/ns.h>
55 
56 #include <sys/sysctl.h>
57 
58 #include <netdb.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <unistd.h>
63 
64 /* XXX: things from route.c */
65 extern char * routename __P((struct sockaddr *));
66 extern char * netname __P((struct sockaddr *));
67 extern char * ns_print __P((struct sockaddr_ns *));
68 extern int nflag;
69 
70 
71 /*
72  * Definitions for showing gateway flags.
73  */
74 struct bits {
75 	short	b_mask;
76 	char	b_val;
77 };
78 static const struct bits bits[] = {
79 	{ RTF_UP,	'U' },
80 	{ RTF_GATEWAY,	'G' },
81 	{ RTF_HOST,	'H' },
82 	{ RTF_REJECT,	'R' },
83 	{ RTF_DYNAMIC,	'D' },
84 	{ RTF_MODIFIED,	'M' },
85 	{ RTF_DONE,	'd' }, /* Completed -- for routing messages only */
86 	{ RTF_MASK,	'm' }, /* Mask Present -- for routing messages only */
87 	{ RTF_CLONING,	'C' },
88 	{ RTF_XRESOLVE,	'X' },
89 	{ RTF_LLINFO,	'L' },
90 	{ RTF_STATIC,	'S' },
91 	{ RTF_PROTO1,	'1' },
92 	{ RTF_PROTO2,	'2' },
93 	{ 0 }
94 };
95 
96 
97 static void p_rtentry __P((struct rt_msghdr *));
98 static void p_sockaddr __P((struct sockaddr *, int, int));
99 static void p_flags __P((int, char *));
100 static void pr_rthdr __P((void));
101 static void pr_family __P((int));
102 
103 
104 /*
105  * Print routing tables.
106  */
107 void
108 show(argc, argv)
109 	int argc;
110 	char **argv;
111 {
112 	size_t needed;
113 	int mib[6];
114 	char *buf, *next, *lim;
115 	register struct rt_msghdr *rtm;
116 	int i;
117 
118 	mib[0] = CTL_NET;
119 	mib[1] = PF_ROUTE;
120 	mib[2] = 0;
121 	mib[3] = 0;
122 	mib[4] = NET_RT_DUMP;
123 	mib[5] = 0;
124 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)	{
125 		perror("route-sysctl-estimate");
126 		exit(1);
127 	}
128 	if ((buf = malloc(needed)) == 0) {
129 		printf("out of space\n");
130 		exit(1);
131 	}
132 	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
133 		perror("sysctl of routing table");
134 		exit(1);
135 	}
136 	lim  = buf + needed;
137 
138 	printf("Routing tables\n");
139 
140 	/* for (i = 0; i <= AF_MAX; i++) ??? */
141 	{
142 		for (next = buf; next < lim; next += rtm->rtm_msglen) {
143 			rtm = (struct rt_msghdr *)next;
144 			p_rtentry(rtm);
145 		}
146 	}
147 }
148 
149 
150 /* column widths; each followed by one space */
151 #define	WID_DST		16	/* width of destination column */
152 #define	WID_GW		18	/* width of gateway column */
153 
154 /*
155  * Print header for routing table columns.
156  */
157 static void
158 pr_rthdr()
159 {
160 
161 	printf("%-*.*s %-*.*s %-6.6s\n",
162 		WID_DST, WID_DST, "Destination",
163 		WID_GW, WID_GW, "Gateway",
164 		"Flags");
165 }
166 
167 
168 /*
169  * Print a routing table entry.
170  */
171 static void
172 p_rtentry(rtm)
173 	register struct rt_msghdr *rtm;
174 {
175 	register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
176 #ifdef notdef
177 	static int masks_done, banner_printed;
178 #endif
179 	static int old_af;
180 	int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
181 
182 #ifdef notdef
183 	/* for the moment, netmasks are skipped over */
184 	if (!banner_printed) {
185 		printf("Netmasks:\n");
186 		banner_printed = 1;
187 	}
188 	if (masks_done == 0) {
189 		if (rtm->rtm_addrs != RTA_DST ) {
190 			masks_done = 1;
191 			af = sa->sa_family;
192 		}
193 	} else
194 #endif
195 		af = sa->sa_family;
196 	if (old_af != af) {
197 		old_af = af;
198 		pr_family(af);
199 		pr_rthdr();
200 	}
201 	if (rtm->rtm_addrs == RTA_DST)
202 		p_sockaddr(sa, 0, 36);
203 	else {
204 		p_sockaddr(sa, rtm->rtm_flags, 16);
205 		if (sa->sa_len == 0)
206 			sa->sa_len = sizeof(long);
207 		sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
208 		p_sockaddr(sa, 0, 18);
209 	}
210 	p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
211 	putchar('\n');
212 }
213 
214 
215 /*
216  * Print address family header before a section of the routing table.
217  */
218 static void
219 pr_family(af)
220 	int af;
221 {
222 	char *afname;
223 
224 	switch (af) {
225 	case AF_INET:
226 		afname = "Internet";
227 		break;
228 #ifndef SMALL
229 	case AF_NS:
230 		afname = "XNS";
231 		break;
232 	case AF_ISO:
233 		afname = "ISO";
234 		break;
235 	case AF_CCITT:
236 		afname = "X.25";
237 		break;
238 #endif /* SMALL */
239 	default:
240 		afname = NULL;
241 		break;
242 	}
243 	if (afname)
244 		printf("\n%s:\n", afname);
245 	else
246 		printf("\nProtocol Family %d:\n", af);
247 }
248 
249 
250 static void
251 p_sockaddr(sa, flags, width)
252 	struct sockaddr *sa;
253 	int flags, width;
254 {
255 	char workbuf[128], *cplim;
256 	register char *cp = workbuf;
257 
258 	switch(sa->sa_family) {
259 
260 	case AF_LINK:
261 	    {
262 		register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
263 
264 		if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
265 		    sdl->sdl_slen == 0)
266 			(void) sprintf(workbuf, "link#%d", sdl->sdl_index);
267 		else switch (sdl->sdl_type) {
268 		case IFT_ETHER:
269 		    {
270 			register int i;
271 			register u_char *lla = (u_char *)sdl->sdl_data +
272 			    sdl->sdl_nlen;
273 
274 			cplim = "";
275 			for (i = 0; i < sdl->sdl_alen; i++, lla++) {
276 				cp += sprintf(cp, "%s%x", cplim, *lla);
277 				cplim = ":";
278 			}
279 			cp = workbuf;
280 			break;
281 		    }
282 		default:
283 			cp = link_ntoa(sdl);
284 			break;
285 		}
286 		break;
287 	    }
288 
289 	case AF_INET:
290 	    {
291 		register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
292 
293 		cp = (sin->sin_addr.s_addr == 0) ? "default" :
294 			((flags & RTF_HOST) ?
295 			routename(sa) :	netname(sa));
296 		break;
297 	    }
298 
299 #ifndef SMALL
300 	case AF_NS:
301 		cp = ns_print((struct sockaddr_ns *)sa);
302 		break;
303 #endif /* SMALL */
304 
305 	default:
306 	    {
307 		register u_char *s = (u_char *)sa->sa_data, *slim;
308 
309 		slim =  sa->sa_len + (u_char *) sa;
310 		cplim = cp + sizeof(workbuf) - 6;
311 		cp += sprintf(cp, "(%d)", sa->sa_family);
312 		while (s < slim && cp < cplim) {
313 			cp += sprintf(cp, " %02x", *s++);
314 			if (s < slim)
315 			    cp += sprintf(cp, "%02x", *s++);
316 		}
317 		cp = workbuf;
318 	    }
319 	}
320 	if (width < 0 )
321 		printf("%s ", cp);
322 	else {
323 		if (nflag)
324 			printf("%-*s ", width, cp);
325 		else
326 			printf("%-*.*s ", width, width, cp);
327 	}
328 }
329 
330 static void
331 p_flags(f, format)
332 	register int f;
333 	char *format;
334 {
335 	char name[33], *flags;
336 	register const struct bits *p = bits;
337 
338 	for (flags = name; p->b_mask; p++)
339 		if (p->b_mask & f)
340 			*flags++ = p->b_val;
341 	*flags = '\0';
342 	printf(format, name);
343 }
344 
345