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