1 /* $NetBSD: show.c,v 1.19 2001/10/24 16:05:07 atatat 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 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94"; 40 #else 41 __RCSID("$NetBSD: show.c,v 1.19 2001/10/24 16:05:07 atatat 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 57 #include <sys/sysctl.h> 58 59 #include <netdb.h> 60 #include <stdio.h> 61 #include <stdlib.h> 62 #include <string.h> 63 #include <unistd.h> 64 #include <err.h> 65 66 #include "extern.h" 67 68 #define ROUNDUP(a) \ 69 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 70 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 71 72 /* 73 * Definitions for showing gateway flags. 74 */ 75 struct bits { 76 short b_mask; 77 char b_val; 78 }; 79 static const struct bits bits[] = { 80 { RTF_UP, 'U' }, 81 { RTF_GATEWAY, 'G' }, 82 { RTF_HOST, 'H' }, 83 { RTF_REJECT, 'R' }, 84 { RTF_DYNAMIC, 'D' }, 85 { RTF_MODIFIED, 'M' }, 86 { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ 87 { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */ 88 { RTF_CLONING, 'C' }, 89 { RTF_XRESOLVE, 'X' }, 90 { RTF_LLINFO, 'L' }, 91 { RTF_STATIC, 'S' }, 92 { RTF_BLACKHOLE, 'B' }, 93 { RTF_CLONED, 'c' }, 94 { RTF_PROTO1, '1' }, 95 { RTF_PROTO2, '2' }, 96 { 0 } 97 }; 98 99 static void pr_rthdr __P((void)); 100 static void p_rtentry __P((struct rt_msghdr *)); 101 static void pr_family __P((int)); 102 static void p_sockaddr __P((struct sockaddr *, struct sockaddr *, int, int )); 103 static void p_flags __P((int)); 104 105 /* 106 * Print routing tables. 107 */ 108 void 109 show(argc, argv) 110 int argc; 111 char **argv; 112 { 113 size_t needed; 114 int mib[6]; 115 char *buf, *next, *lim; 116 struct rt_msghdr *rtm; 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 err(1, NULL); 130 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 131 err(1, "sysctl of routing table"); 132 lim = buf + needed; 133 134 printf("Routing tables\n"); 135 136 /* for (i = 0; i <= AF_MAX; i++) ??? */ 137 { 138 for (next = buf; next < lim; next += rtm->rtm_msglen) { 139 rtm = (struct rt_msghdr *)next; 140 p_rtentry(rtm); 141 } 142 } 143 } 144 145 146 /* column widths; each followed by one space */ 147 #define WID_DST 17 /* width of destination column */ 148 #define WID_GW 18 /* width of gateway column */ 149 150 /* 151 * Print header for routing table columns. 152 */ 153 static void 154 pr_rthdr() 155 { 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 /* 165 * Print a routing table entry. 166 */ 167 static void 168 p_rtentry(rtm) 169 struct rt_msghdr *rtm; 170 { 171 struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 172 #ifdef notdef 173 static int masks_done, banner_printed; 174 #endif 175 static int old_af; 176 int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_REJECT; 177 178 #ifdef notdef 179 /* for the moment, netmasks are skipped over */ 180 if (!banner_printed) { 181 printf("Netmasks:\n"); 182 banner_printed = 1; 183 } 184 if (masks_done == 0) { 185 if (rtm->rtm_addrs != RTA_DST ) { 186 masks_done = 1; 187 af = sa->sa_family; 188 } 189 } else 190 #endif 191 af = sa->sa_family; 192 if (old_af != af) { 193 old_af = af; 194 pr_family(af); 195 pr_rthdr(); 196 } 197 if (rtm->rtm_addrs == RTA_DST) 198 p_sockaddr(sa, NULL, 0, WID_DST + 1 + WID_GW + 1); 199 else { 200 struct sockaddr *nm; 201 202 if ((rtm->rtm_addrs & RTA_NETMASK) == 0) 203 nm = NULL; 204 else { 205 /* skip to gateway */ 206 nm = (struct sockaddr *) 207 (ROUNDUP(sa->sa_len) + (char *)sa); 208 /* skip over gateway to netmask */ 209 nm = (struct sockaddr *) 210 (ROUNDUP(nm->sa_len) + (char *)nm); 211 } 212 213 p_sockaddr(sa, nm, rtm->rtm_flags, WID_DST); 214 sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa); 215 p_sockaddr(sa, NULL, 0, WID_GW); 216 } 217 p_flags(rtm->rtm_flags & interesting); 218 putchar('\n'); 219 } 220 221 222 /* 223 * Print address family header before a section of the routing table. 224 */ 225 static void 226 pr_family(af) 227 int af; 228 { 229 char *afname; 230 231 switch (af) { 232 case AF_INET: 233 afname = "Internet"; 234 break; 235 #ifndef SMALL 236 #ifdef INET6 237 case AF_INET6: 238 afname = "Internet6"; 239 break; 240 #endif /* INET6 */ 241 case AF_NS: 242 afname = "XNS"; 243 break; 244 case AF_ISO: 245 afname = "ISO"; 246 break; 247 case AF_CCITT: 248 afname = "X.25"; 249 break; 250 #endif /* SMALL */ 251 case AF_APPLETALK: 252 afname = "AppleTalk"; 253 break; 254 default: 255 afname = NULL; 256 break; 257 } 258 if (afname) 259 printf("\n%s:\n", afname); 260 else 261 printf("\nProtocol Family %d:\n", af); 262 } 263 264 265 static void 266 p_sockaddr(sa, nm, flags, width) 267 struct sockaddr *sa, *nm; 268 int flags, width; 269 { 270 char workbuf[128], *cplim; 271 char *cp = workbuf; 272 273 switch(sa->sa_family) { 274 275 case AF_LINK: 276 if (getnameinfo(sa, sa->sa_len, workbuf, sizeof(workbuf), 277 NULL, 0, NI_NUMERICHOST) != 0) 278 strncpy(workbuf, "invalid", sizeof(workbuf)); 279 cp = workbuf; 280 break; 281 282 case AF_INET: 283 cp = routename(sa, nm, flags); 284 break; 285 286 #ifndef SMALL 287 #ifdef INET6 288 case AF_INET6: 289 cp = routename(sa, nm, flags); 290 /* make sure numeric address is not truncated */ 291 if (strchr(cp, ':') != NULL && strlen(cp) > width) 292 width = strlen(cp); 293 break; 294 #endif /* INET6 */ 295 296 case AF_NS: 297 cp = ns_print((struct sockaddr_ns *)sa); 298 break; 299 #endif /* SMALL */ 300 301 default: 302 { 303 u_char *s = (u_char *)sa->sa_data, *slim; 304 305 slim = sa->sa_len + (u_char *) sa; 306 cplim = cp + sizeof(workbuf) - 6; 307 cp += snprintf(cp, cplim - cp, "(%d)", sa->sa_family); 308 while (s < slim && cp < cplim) { 309 cp += snprintf(cp, cplim - cp, " %02x", *s++); 310 if (s < slim) 311 cp += snprintf(cp, cplim - cp, "%02x", *s++); 312 } 313 cp = workbuf; 314 } 315 } 316 if (width < 0 ) 317 printf("%s ", cp); 318 else { 319 if (nflag) 320 printf("%-*s ", width, cp); 321 else 322 printf("%-*.*s ", width, width, cp); 323 } 324 } 325 326 static void 327 p_flags(f) 328 int f; 329 { 330 char name[33], *flags; 331 const struct bits *p = bits; 332 333 for (flags = name; p->b_mask; p++) 334 if (p->b_mask & f) 335 *flags++ = p->b_val; 336 *flags = '\0'; 337 printf("%-6.6s ", name); 338 } 339 340