File:  [DragonFly] / src / sbin / route / show.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Mar 23 18:00:48 2004 UTC (10 years, 8 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Make the Destination and Gateway columns wider when printing FQDNs so
the hostnames do not get cut-off too badly.

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