File:  [DragonFly] / src / sbin / route / show.c
Revision 1.3: download - view: text, annotated - select for diffs
Tue Mar 23 18:25:51 2004 UTC (10 years, 5 months ago) by dillon
Branches: MAIN
CVS tags: HEAD, DragonFly_Snap29Sep2004, DragonFly_Snap13Sep2004, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Add -w, which prints the full width of the data being represented even if
it overflows the column, and do not truncate the base domain from displayed
host names.  This is for programmatic interfaces and for sysops
who really want to see the whole host name.

    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.3 2004/03/23 18:25:51 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 int 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: 	int width;
  207: 
  208: #ifdef notdef
  209: 	/* for the moment, netmasks are skipped over */
  210: 	if (!banner_printed) {
  211: 		printf("Netmasks:\n");
  212: 		banner_printed = 1;
  213: 	}
  214: 	if (masks_done == 0) {
  215: 		if (rtm->rtm_addrs != RTA_DST ) {
  216: 			masks_done = 1;
  217: 			af = sa->sa_family;
  218: 		}
  219: 	} else
  220: #endif
  221: 		af = sa->sa_family;
  222: 	if (old_af != af) {
  223: 		old_af = af;
  224: 		pr_family(af);
  225: 		pr_rthdr();
  226: 	}
  227: 
  228: 	/*
  229: 	 * Print the information.  If wflag is set p_sockaddr() can return
  230: 	 * a wider width then specified and we try to fit the second
  231: 	 * address in any remaining space so the flags still lines up.
  232: 	 */
  233: 	if (rtm->rtm_addrs == RTA_DST) {
  234: 		p_sockaddr(sa, 0, WID_DST + WID_GW + 2);
  235: 	} else {
  236: 		width = p_sockaddr(sa, rtm->rtm_flags, WID_DST);
  237: 		sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
  238: 		p_sockaddr(sa, 0, WID_GW + WID_DST - width);
  239: 	}
  240: 	p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
  241: 	putchar('\n');
  242: }
  243: 
  244: /*
  245:  * Print address family header before a section of the routing table.
  246:  */
  247: static void
  248: pr_family(int af)
  249: {
  250: 	char *afname;
  251: 
  252: 	switch (af) {
  253: 	case AF_INET:
  254: 		afname = "Internet";
  255: 		break;
  256: #ifdef INET6
  257: 	case AF_INET6:
  258: 		afname = "Internet6";
  259: 		break;
  260: #endif /* INET6 */
  261: 	case AF_NS:
  262: 		afname = "XNS";
  263: 		break;
  264: 	case AF_IPX:
  265: 		afname = "IPX";
  266: 		break;
  267: 	case AF_ISO:
  268: 		afname = "ISO";
  269: 		break;
  270: 	case AF_CCITT:
  271: 		afname = "X.25";
  272: 		break;
  273: 	case AF_APPLETALK:
  274: 		afname = "AppleTalk";
  275: 		break;
  276: 	default:
  277: 		afname = NULL;
  278: 		break;
  279: 	}
  280: 	if (afname)
  281: 		printf("\n%s:\n", afname);
  282: 	else
  283: 		printf("\nProtocol Family %d:\n", af);
  284: }
  285: 
  286: static int
  287: p_sockaddr(struct sockaddr *sa, int flags, int width)
  288: {
  289: 	char workbuf[128], *cplim;
  290: 	char *cp = workbuf;
  291: 	int len = sizeof(workbuf);
  292: 	int count;
  293: 
  294: 	switch(sa->sa_family) {
  295: 
  296: 	case AF_LINK:
  297: 	    {
  298: 		struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
  299: 
  300: 		if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
  301: 		    sdl->sdl_slen == 0)
  302: 			snprintf(workbuf, sizeof(workbuf),
  303: 			    "link#%d", sdl->sdl_index);
  304: 		else {
  305: 			switch (sdl->sdl_type) {
  306: 			case IFT_ETHER:
  307: 			    {
  308: 				int i;
  309: 				u_char *lla = (u_char *)sdl->sdl_data +
  310: 				    sdl->sdl_nlen;
  311: 
  312: 				cplim = "";
  313: 				for (i = 0; i < sdl->sdl_alen; i++, lla++) {
  314: 					snprintf(cp, len, "%s%x", cplim, *lla);
  315: 					len -= strlen(cp);
  316: 					cp += strlen(cp);
  317: 					if (len <= 0)
  318: 						break;	/* overflow */
  319: 					cplim = ":";
  320: 				}
  321: 				cp = workbuf;
  322: 				break;
  323: 			    }
  324: 			default:
  325: 				cp = link_ntoa(sdl);
  326: 				break;
  327: 			}
  328: 		}
  329: 		break;
  330: 	    }
  331: 
  332: 	case AF_INET:
  333: 	    {
  334: 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  335: 
  336: 		if (sin->sin_addr.s_addr == 0)
  337: 			cp = "default";
  338: 		else
  339: 			cp = (flags & RTF_HOST) ? routename(sa) : netname(sa);
  340: 		break;
  341: 	    }
  342: 
  343: #ifdef INET6
  344: 	case AF_INET6:
  345: 	    {
  346: 		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa;
  347: 
  348: 		cp = IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr) ? "default" :
  349: 			((flags & RTF_HOST) ?  routename(sa) :	netname(sa));
  350: 		/* make sure numeric address is not truncated */
  351: 		if (strchr(cp, ':') != NULL && strlen(cp) > width)
  352: 			width = strlen(cp);
  353: 		break;
  354: 	    }
  355: #endif /* INET6 */
  356: 
  357: 	case AF_NS:
  358: 		cp = ns_print((struct sockaddr_ns *)sa);
  359: 		break;
  360: 
  361: 	default:
  362: 	    {
  363: 		u_char *s = (u_char *)sa->sa_data, *slim;
  364: 
  365: 		slim =  sa->sa_len + (u_char *) sa;
  366: 		cplim = cp + sizeof(workbuf) - 6;
  367: 		snprintf(cp, len, "(%d)", sa->sa_family);
  368: 		len -= strlen(cp);
  369: 		cp += strlen(cp);
  370: 		if (len <= 0) {
  371: 			cp = workbuf;
  372: 			break;		/* overflow */
  373: 		}
  374: 		while (s < slim && cp < cplim) {
  375: 			snprintf(cp, len, " %02x", *s++);
  376: 			len -= strlen(cp);
  377: 			cp += strlen(cp);
  378: 			if (len <= 0)
  379: 				break;		/* overflow */
  380: 			if (s < slim) {
  381: 				snprintf(cp, len, "%02x", *s++);
  382: 				len -= strlen(cp);
  383: 				cp += strlen(cp);
  384: 				if (len <= 0)
  385: 					break;		/* overflow */
  386: 			}
  387: 		}
  388: 		cp = workbuf;
  389: 	    }
  390: 	}
  391: 	if (width < 0 ) {
  392: 		count = printf("%s ", cp);
  393: 	} else {
  394: 		if (nflag || wflag)
  395: 			count = printf("%-*s ", width, cp);
  396: 		else
  397: 			count = printf("%-*.*s ", width, width, cp);
  398: 	}
  399: 	return(count);
  400: }
  401: 
  402: static void
  403: p_flags(int f, char *format)
  404: {
  405: 	char name[33], *flags;
  406: 	const struct bits *p = bits;
  407: 
  408: 	for (flags = name; p->b_mask && flags < &name[sizeof(name-2)]; p++) {
  409: 		if (p->b_mask & f)
  410: 			*flags++ = p->b_val;
  411: 	}
  412: 	*flags = '\0';
  413: 	printf(format, name);
  414: }