1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if defined(DO_SCCS) && !defined(lint) 8: static char sccsid[] = "@(#)route.c 5.6 (Berkeley) 86/04/23"; 9: #endif 10: 11: #include <sys/param.h> 12: #include <sys/socket.h> 13: #include <sys/mbuf.h> 14: 15: #include <net/if.h> 16: #include <net/route.h> 17: #include <netinet/in.h> 18: 19: #include <netns/ns.h> 20: 21: #include <netdb.h> 22: #include "net.h" /* for CRASH only */ 23: 24: extern int kmem; 25: extern int nflag; 26: extern char *routename(), *netname(), *ns_print(); 27: 28: /* 29: * Definitions for showing gateway flags. 30: */ 31: struct bits { 32: short b_mask; 33: char b_val; 34: } bits[] = { 35: { RTF_UP, 'U' }, 36: { RTF_GATEWAY, 'G' }, 37: { RTF_HOST, 'H' }, 38: { RTF_DYNAMIC, 'D' }, 39: { 0 } 40: }; 41: 42: /* 43: * Print routing tables. 44: */ 45: routepr(hostaddr, netaddr, hashsizeaddr) 46: off_t hostaddr, netaddr, hashsizeaddr; 47: { 48: register struct rtentry *rt; 49: register struct mbuf *m; 50: register struct bits *p; 51: #ifdef CRASH 52: register struct arenas *asp; 53: #endif CRASH 54: char name[16], *flags; 55: struct rtentry rte; 56: struct rtentry **routehash; 57: struct mbuf mb; 58: struct mbuf **routehash; 59: struct ifnet ifnet; 60: int hashsize; 61: int i, doinghost = 1; 62: 63: if (hostaddr == 0) { 64: printf("rthost: symbol not in namelist\n"); 65: return; 66: } 67: if (netaddr == 0) { 68: printf("rtnet: symbol not in namelist\n"); 69: return; 70: } 71: if (hashsizeaddr == 0) { 72: printf("rthashsize: symbol not in namelist\n"); 73: return; 74: } 75: klseek(kmem, (off_t)hashsizeaddr, 0); 76: read(kmem, &hashsize, sizeof (hashsize)); 77: #ifdef pdp11 78: routehash = (struct rtentry **)malloc( hashsize*sizeof (struct rtentry *) ); 79: klseek(kmem, (off_t)hostaddr, 0); 80: read(kmem, routehash, hashsize*sizeof (struct rtentry *)); 81: #else 82: routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) ); 83: klseek(kmem, (off_t)hostaddr, 0); 84: read(kmem, routehash, hashsize*sizeof (struct mbuf *)); 85: #endif 86: printf("Routing tables\n"); 87: printf("%-20.20s %-20.20s %-8.8s %-6.6s %-10.10s %s\n", 88: "Destination", "Gateway", 89: "Flags", "Refcnt", "Use", "Interface"); 90: again: 91: for (i = 0; i < hashsize; i++) { 92: if (routehash[i] == 0) 93: continue; 94: #ifdef pdp11 95: rt = routehash[i]; 96: while (rt) { 97: struct sockaddr_in *sin; 98: struct sockaddr_ns *sns; 99: 100: #ifdef CRASH 101: if (!VALADD(rt, struct rtentry)) { 102: printf("bad rtentry address ("); 103: DUMP((unsigned)rt); 104: puts(")"); 105: break; 106: } 107: (putars((unsigned)rt, sizeof(struct rtentry), 108: AS_RTENT))->as_ref++; 109: rt = XLATE(rt, struct rtentry *); 110: #else 111: klseek(kmem, (off_t)rt, 0); 112: read(kmem, &rte, sizeof (rte)); 113: rt = &rte; 114: #endif CRASH 115: #else 116: m = routehash[i]; 117: while (m) { 118: struct sockaddr_in *sin; 119: struct sockaddr_ns *sns; 120: 121: klseek(kmem, (off_t)m, 0); 122: read(kmem, &mb, sizeof (mb)); 123: rt = mtod(&mb, struct rtentry *); 124: if ((unsigned)rt < (unsigned)&mb || 125: (unsigned)rt >= (unsigned)(&mb + 1)) { 126: printf("???\n"); 127: return; 128: } 129: #endif 130: 131: switch(rt->rt_dst.sa_family) { 132: case AF_INET: 133: sin = (struct sockaddr_in *)&rt->rt_dst; 134: printf("%-20.20s ", 135: (sin->sin_addr.s_addr == 0) ? "default" : 136: (rt->rt_flags & RTF_HOST) ? 137: routename(sin->sin_addr) : 138: netname(sin->sin_addr, 0L)); 139: sin = (struct sockaddr_in *)&rt->rt_gateway; 140: printf("%-20.20s ", routename(sin->sin_addr)); 141: break; 142: case AF_NS: 143: printf("%-20s ", 144: ns_print((struct sockaddr_ns *)&rt->rt_dst)); 145: printf("%-20s ", 146: ns_print((struct sockaddr_ns *)&rt->rt_gateway)); 147: break; 148: default: 149: { 150: u_short *s = (u_short *)rt->rt_dst.sa_data; 151: printf("(%d)%x %x %x %x %x %x %x ", 152: rt->rt_dst.sa_family, 153: s[0], s[1], s[2], s[3], s[4], s[5], s[6]); 154: s = (u_short *)rt->rt_gateway.sa_data; 155: printf("(%d)%x %x %x %x %x %x %x ", 156: rt->rt_gateway.sa_family, 157: s[0], s[1], s[2], s[3], s[4], s[5], s[6]); 158: } 159: } 160: for (flags = name, p = bits; p->b_mask; p++) 161: if (p->b_mask & rt->rt_flags) 162: *flags++ = p->b_val; 163: *flags = '\0'; 164: printf("%-8.8s %-6d %-10d ", name, 165: rt->rt_refcnt, rt->rt_use); 166: if (rt->rt_ifp == 0) { 167: putchar('\n'); 168: #ifdef pdp11 169: rt = rt->rt_next; 170: #else 171: m = mb.m_next; 172: #endif 173: continue; 174: } 175: klseek(kmem, (off_t)rt->rt_ifp, 0); 176: read(kmem, &ifnet, sizeof (ifnet)); 177: klseek(kmem, (off_t)ifnet.if_name, 0); 178: read(kmem, name, 16); 179: printf("%s%d\n", name, ifnet.if_unit); 180: #ifdef pdp11 181: rt = rt->rt_next; 182: #else 183: m = mb.m_next; 184: #endif 185: } 186: } 187: if (doinghost) { 188: klseek(kmem, (off_t)netaddr, 0); 189: #ifdef pdp11 190: read(kmem, routehash, hashsize*sizeof (struct rtentry *)); 191: #else 192: read(kmem, routehash, hashsize*sizeof (struct mbuf *)); 193: #endif 194: doinghost = 0; 195: goto again; 196: } 197: free(routehash); 198: } 199: 200: char * 201: routename(in) 202: struct in_addr in; 203: { 204: register char *cp; 205: static char line[50]; 206: struct hostent *hp; 207: static char domain[MAXHOSTNAMELEN + 1]; 208: static int first = 1; 209: char *index(); 210: 211: if (first) { 212: first = 0; 213: if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 214: (cp = index(domain, '.'))) 215: (void) strcpy(domain, cp + 1); 216: else 217: domain[0] = 0; 218: } 219: cp = 0; 220: if (!nflag) { 221: hp = gethostbyaddr(&in, sizeof (struct in_addr), 222: AF_INET); 223: if (hp) { 224: if ((cp = index(hp->h_name, '.')) && 225: !strcmp(cp + 1, domain)) 226: *cp = 0; 227: cp = hp->h_name; 228: } 229: } 230: if (cp) 231: strcpy(line, cp); 232: else { 233: #define C(x) (((int)(x)) & 0xff) 234: in.s_addr = ntohl(in.s_addr); 235: sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 236: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 237: } 238: return (line); 239: } 240: 241: /* 242: * Return the name of the network whose address is given. 243: * The address is assumed to be that of a net or subnet, not a host. 244: */ 245: char * 246: netname(in, mask) 247: struct in_addr in; 248: u_long mask; 249: { 250: char *cp = 0; 251: static char line[50]; 252: struct netent *np = 0; 253: u_long net; 254: int subnetshift; 255: 256: in.s_addr = ntohl(in.s_addr); 257: if (!nflag && in.s_addr) { 258: if (mask == 0L) { 259: if (IN_CLASSA(in.s_addr)) { 260: mask = IN_CLASSA_NET; 261: subnetshift = 8; 262: } else if (IN_CLASSB(in.s_addr)) { 263: mask = IN_CLASSB_NET; 264: subnetshift = 8; 265: } else { 266: mask = IN_CLASSC_NET; 267: subnetshift = 4; 268: } 269: /* 270: * If there are more bits than the standard mask 271: * would suggest, subnets must be in use. 272: * Guess at the subnet mask, assuming reasonable 273: * width subnet fields. 274: */ 275: while (in.s_addr &~ mask) 276: mask >>= subnetshift; 277: } 278: net = in.s_addr & mask; 279: while ((mask & 1L) == 0) 280: mask >>= 1, net >>= 1, net &= 0x7fffffffL; 281: np = getnetbyaddr(net, AF_INET); 282: if (np) 283: cp = np->n_name; 284: } 285: if (cp) 286: strcpy(line, cp); 287: else if ((in.s_addr & 0x00ffffffL) == 0L) 288: sprintf(line, "%u", C(in.s_addr >> 24)); 289: else if ((in.s_addr & 0x0000ffffL) == 0L) 290: sprintf(line, "%u.%u", C(in.s_addr >> 24) , C(in.s_addr >> 16)); 291: else if ((in.s_addr & 0x000000ffL) == 0L) 292: sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), 293: C(in.s_addr >> 16), C(in.s_addr >> 8)); 294: else 295: sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 296: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 297: return (line); 298: } 299: 300: /* 301: * Print routing statistics 302: */ 303: rt_stats(off) 304: off_t off; 305: { 306: struct rtstat rtstat; 307: char *plural(); 308: 309: if (off == 0) { 310: printf("rtstat: symbol not in namelist\n"); 311: return; 312: } 313: klseek(kmem, (off_t)off, 0); 314: read(kmem, (char *)&rtstat, sizeof (rtstat)); 315: printf("routing:\n"); 316: printf("\t%d bad routing redirect%s\n", 317: rtstat.rts_badredirect, plural((long)rtstat.rts_badredirect)); 318: printf("\t%d dynamically created route%s\n", 319: rtstat.rts_dynamic, plural((long)rtstat.rts_dynamic)); 320: printf("\t%d new gateway%s due to redirects\n", 321: rtstat.rts_newgateway, plural((long)rtstat.rts_newgateway)); 322: printf("\t%d destination%s found unreachable\n", 323: rtstat.rts_unreach, plural((long)rtstat.rts_unreach)); 324: printf("\t%d use%s of a wildcard route\n", 325: rtstat.rts_wildcard, plural((long)rtstat.rts_wildcard)); 326: } 327: short ns_nullh[] = {0,0,0}; 328: short ns_bh[] = {-1,-1,-1}; 329: 330: char * 331: ns_print(sns) 332: struct sockaddr_ns *sns; 333: { 334: struct ns_addr work; 335: union { union ns_net net_e; u_long long_e; } net; 336: u_short port; 337: static char mybuf[50], cport[10], chost[25]; 338: char *host = ""; 339: register char *p; register u_char *q; u_char *q_lim; 340: 341: work = sns->sns_addr; 342: port = ntohs(work.x_port); 343: work.x_port = 0; 344: net.net_e = work.x_net; 345: if (ns_nullhost(work) && net.long_e == 0) { 346: if (port ) { 347: sprintf(mybuf, "*.%xH", port); 348: upHex(mybuf); 349: } else 350: sprintf(mybuf, "*.*"); 351: return (mybuf); 352: } 353: 354: if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) { 355: host = "any"; 356: } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) { 357: host = "*"; 358: } else { 359: q = work.x_host.c_host; 360: sprintf(chost, "%02x%02x%02x%02x%02x%02xH", 361: q[0], q[1], q[2], q[3], q[4], q[5]); 362: for (p = chost; *p == '0' && p < chost + 12; p++); 363: host = p; 364: } 365: if (port) 366: sprintf(cport, ".%xH", htons(port)); 367: else 368: *cport = 0; 369: 370: sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport); 371: upHex(mybuf); 372: return(mybuf); 373: } 374: 375: char * 376: ns_phost(sns) 377: struct sockaddr_ns *sns; 378: { 379: struct sockaddr_ns work; 380: static union ns_net ns_zeronet; 381: char *p; 382: 383: work = *sns; 384: work.sns_addr.x_port = 0; 385: work.sns_addr.x_net = ns_zeronet; 386: 387: p = ns_print(&work); 388: if (strncmp("0H.", p, 3) == 0) p += 3; 389: return(p); 390: } 391: upHex(p0) 392: char *p0; 393: { 394: register char *p = p0; 395: for (; *p; p++) switch (*p) { 396: 397: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 398: *p += ('A' - 'a'); 399: } 400: }