1 /* $OpenBSD: show.c,v 1.20 2001/07/07 18:26:20 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.20 2001/07/07 18:26:20 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 <netinet/ip_ipsp.h> 57 #include <arpa/inet.h> 58 59 #include <sys/sysctl.h> 60 61 #include "keywords.h" 62 63 #include <netdb.h> 64 #include <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 #include <unistd.h> 68 69 /* XXX: things from route.c */ 70 extern char *routename __P((struct sockaddr *)); 71 extern char *netname __P((struct sockaddr *)); 72 extern char *ns_print __P((struct sockaddr_ns *)); 73 extern int nflag; 74 75 #define ROUNDUP(a) \ 76 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 77 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 78 79 /* 80 * Definitions for showing gateway flags. 81 */ 82 struct bits { 83 short b_mask; 84 char b_val; 85 }; 86 static const struct bits bits[] = { 87 { RTF_UP, 'U' }, 88 { RTF_GATEWAY, 'G' }, 89 { RTF_HOST, 'H' }, 90 { RTF_REJECT, 'R' }, 91 { RTF_BLACKHOLE, 'B' }, 92 { RTF_DYNAMIC, 'D' }, 93 { RTF_MODIFIED, 'M' }, 94 { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ 95 { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */ 96 { RTF_CLONING, 'C' }, 97 { RTF_XRESOLVE, 'X' }, 98 { RTF_LLINFO, 'L' }, 99 { RTF_STATIC, 'S' }, 100 { RTF_PROTO1, '1' }, 101 { RTF_PROTO2, '2' }, 102 { 0 } 103 }; 104 105 static void p_rtentry __P((struct rt_msghdr *)); 106 static void p_sockaddr __P((struct sockaddr *, int, int)); 107 static void p_flags __P((int, char *)); 108 static void pr_rthdr __P((void)); 109 static void pr_family __P((int)); 110 111 int keyword(char *); 112 void usage(char *); 113 114 /* 115 * Print routing tables. 116 */ 117 void 118 show(argc, argv) 119 int argc; 120 char **argv; 121 { 122 struct rt_msghdr *rtm; 123 char *buf = NULL, *next, *lim = NULL; 124 size_t needed; 125 int mib[6], af = 0; 126 struct sockaddr *sa; 127 128 if (argc > 1) { 129 argv++; 130 if (argc == 2 && **argv == '-') 131 switch (keyword(*argv + 1)) { 132 case K_INET: 133 af = AF_INET; 134 break; 135 #ifdef INET6 136 case K_INET6: 137 af = AF_INET6; 138 break; 139 #endif 140 case K_XNS: 141 af = AF_NS; 142 break; 143 case K_IPX: 144 af = AF_IPX; 145 break; 146 case K_LINK: 147 af = AF_LINK; 148 break; 149 case K_ISO: 150 case K_OSI: 151 af = AF_ISO; 152 break; 153 case K_X25: 154 af = AF_CCITT; 155 break; 156 default: 157 goto bad; 158 } else 159 bad: usage(*argv); 160 } 161 mib[0] = CTL_NET; 162 mib[1] = PF_ROUTE; 163 mib[2] = 0; 164 mib[3] = 0; 165 mib[4] = NET_RT_DUMP; 166 mib[5] = 0; 167 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 168 perror("route-sysctl-estimate"); 169 exit(1); 170 } 171 if (needed > 0) { 172 if ((buf = malloc(needed)) == 0) { 173 printf("out of space\n"); 174 exit(1); 175 } 176 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 177 perror("sysctl of routing table"); 178 exit(1); 179 } 180 lim = buf + needed; 181 } 182 183 printf("Routing tables\n"); 184 185 if (buf) { 186 for (next = buf; next < lim; next += rtm->rtm_msglen) { 187 rtm = (struct rt_msghdr *)next; 188 sa = (struct sockaddr *)(rtm + 1); 189 if (af && sa->sa_family != af) 190 continue; 191 p_rtentry(rtm); 192 } 193 free(buf); 194 } 195 } 196 197 /* column widths; each followed by one space */ 198 #define WID_DST 16 /* width of destination column */ 199 #define WID_GW 18 /* width of gateway column */ 200 201 /* 202 * Print header for routing table columns. 203 */ 204 static void 205 pr_rthdr() 206 { 207 printf("%-*.*s %-*.*s %-6.6s\n", 208 WID_DST, WID_DST, "Destination", 209 WID_GW, WID_GW, "Gateway", 210 "Flags"); 211 } 212 213 /* 214 * Print a routing table entry. 215 */ 216 static void 217 p_rtentry(rtm) 218 struct rt_msghdr *rtm; 219 { 220 struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 221 #ifdef notdef 222 static int masks_done, banner_printed; 223 #endif 224 static int old_af; 225 int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_MASK; 226 227 #ifdef notdef 228 /* for the moment, netmasks are skipped over */ 229 if (!banner_printed) { 230 printf("Netmasks:\n"); 231 banner_printed = 1; 232 } 233 if (masks_done == 0) { 234 if (rtm->rtm_addrs != RTA_DST ) { 235 masks_done = 1; 236 af = sa->sa_family; 237 } 238 } else 239 #endif 240 af = sa->sa_family; 241 if (old_af != af) { 242 old_af = af; 243 pr_family(af); 244 pr_rthdr(); 245 } 246 if (rtm->rtm_addrs == RTA_DST) 247 p_sockaddr(sa, 0, 36); 248 else { 249 p_sockaddr(sa, rtm->rtm_flags, 16); 250 sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa); 251 p_sockaddr(sa, 0, 18); 252 } 253 p_flags(rtm->rtm_flags & interesting, "%-6.6s "); 254 putchar('\n'); 255 } 256 257 /* 258 * Print address family header before a section of the routing table. 259 */ 260 static void 261 pr_family(af) 262 int af; 263 { 264 char *afname; 265 266 switch (af) { 267 case AF_INET: 268 afname = "Internet"; 269 break; 270 #ifdef INET6 271 case AF_INET6: 272 afname = "Internet6"; 273 break; 274 #endif /* INET6 */ 275 case AF_NS: 276 afname = "XNS"; 277 break; 278 case AF_IPX: 279 afname = "IPX"; 280 break; 281 case AF_ISO: 282 afname = "ISO"; 283 break; 284 case AF_CCITT: 285 afname = "X.25"; 286 break; 287 case AF_APPLETALK: 288 afname = "AppleTalk"; 289 break; 290 default: 291 afname = NULL; 292 break; 293 } 294 if (afname) 295 printf("\n%s:\n", afname); 296 else 297 printf("\nProtocol Family %d:\n", af); 298 } 299 300 301 static void 302 p_sockaddr(sa, flags, width) 303 struct sockaddr *sa; 304 int flags, width; 305 { 306 char workbuf[128], *cplim; 307 char *cp = workbuf; 308 309 switch(sa->sa_family) { 310 311 case AF_LINK: 312 { 313 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 314 315 if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && 316 sdl->sdl_slen == 0) 317 (void) sprintf(workbuf, "link#%d", sdl->sdl_index); 318 else switch (sdl->sdl_type) { 319 case IFT_ETHER: 320 { 321 int i; 322 u_char *lla = (u_char *)sdl->sdl_data + 323 sdl->sdl_nlen; 324 325 cplim = ""; 326 for (i = 0; i < sdl->sdl_alen; i++, lla++) { 327 cp += sprintf(cp, "%s%x", cplim, *lla); 328 cplim = ":"; 329 } 330 cp = workbuf; 331 break; 332 } 333 default: 334 cp = link_ntoa(sdl); 335 break; 336 } 337 break; 338 } 339 340 case AF_INET: 341 { 342 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 343 344 if (sin->sin_addr.s_addr == 0) 345 cp = "default"; 346 else 347 cp = (flags & RTF_HOST) ? routename(sa) : netname(sa); 348 break; 349 } 350 351 #ifdef INET6 352 case AF_INET6: 353 { 354 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; 355 356 cp = IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr) ? "default" : 357 ((flags & RTF_HOST) ? 358 routename(sa) : netname(sa)); 359 /* make sure numeric address is not truncated */ 360 if (strchr(cp, ':') != NULL && strlen(cp) > width) 361 width = strlen(cp); 362 break; 363 } 364 #endif /* INET6 */ 365 366 case AF_NS: 367 cp = ns_print((struct sockaddr_ns *)sa); 368 break; 369 370 default: 371 { 372 u_char *s = (u_char *)sa->sa_data, *slim; 373 374 slim = sa->sa_len + (u_char *) sa; 375 cplim = cp + sizeof(workbuf) - 6; 376 cp += sprintf(cp, "(%d)", sa->sa_family); 377 while (s < slim && cp < cplim) { 378 cp += sprintf(cp, " %02x", *s++); 379 if (s < slim) 380 cp += sprintf(cp, "%02x", *s++); 381 } 382 cp = workbuf; 383 } 384 } 385 if (width < 0 ) 386 printf("%s ", cp); 387 else { 388 if (nflag) 389 printf("%-*s ", width, cp); 390 else 391 printf("%-*.*s ", width, width, cp); 392 } 393 } 394 395 static void 396 p_flags(f, format) 397 int f; 398 char *format; 399 { 400 char name[33], *flags; 401 const struct bits *p = bits; 402 403 for (flags = name; p->b_mask && flags < &name[sizeof name-2]; p++) 404 if (p->b_mask & f) 405 *flags++ = p->b_val; 406 *flags = '\0'; 407 printf(format, name); 408 } 409