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