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