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