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