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: char copyright[] =
   9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)route.c	5.6 (Berkeley) 6/5/86";
  15: #endif not lint
  16: 
  17: #include <sys/param.h>
  18: #include <sys/socket.h>
  19: #include <sys/ioctl.h>
  20: #include <sys/mbuf.h>
  21: 
  22: #include <net/route.h>
  23: #include <netinet/in.h>
  24: #include <netns/ns.h>
  25: 
  26: #include <stdio.h>
  27: #include <errno.h>
  28: #include <ctype.h>
  29: #include <netdb.h>
  30: 
  31: struct  rtentry route;
  32: int s;
  33: int forcehost, forcenet, doflush, nflag;
  34: struct  sockaddr_in sin = { AF_INET };
  35: struct  in_addr inet_makeaddr();
  36: char    *malloc();
  37: 
  38: main(argc, argv)
  39:     int argc;
  40:     char *argv[];
  41: {
  42: 
  43:     if (argc < 2)
  44:         printf("usage: route [ -n ] [ -f ] [ cmd [ net | host ] args ]\n"),
  45:         exit(1);
  46:     s = socket(AF_INET, SOCK_RAW, 0);
  47:     if (s < 0) {
  48:         perror("route: socket");
  49:         exit(1);
  50:     }
  51:     argc--, argv++;
  52:     for (; argc >  0 && argv[0][0] == '-'; argc--, argv++) {
  53:         for (argv[0]++; *argv[0]; argv[0]++)
  54:             switch (*argv[0]) {
  55:             case 'f':
  56:                 doflush++;
  57:                 break;
  58:             case 'n':
  59:                 nflag++;
  60:                 break;
  61:             }
  62:     }
  63:     if (doflush)
  64:         flushroutes();
  65:     if (argc > 0) {
  66:         if (strcmp(*argv, "add") == 0)
  67:             newroute(argc, argv);
  68:         else if (strcmp(*argv, "delete") == 0)
  69:             newroute(argc, argv);
  70:         else if (strcmp(*argv, "change") == 0)
  71:             changeroute(argc-1, argv+1);
  72:         else
  73:             printf("%s: huh?\n", *argv);
  74:     }
  75: }
  76: 
  77: /*
  78:  * Purge all entries in the routing tables not
  79:  * associated with network interfaces.
  80:  */
  81: #include <nlist.h>
  82: 
  83: struct nlist nl[] = {
  84: #define N_RTHOST    0
  85:     { "_rthost" },
  86: #define N_RTNET     1
  87:     { "_rtnet" },
  88: #define N_RTHASHSIZE    2
  89:     { "_rthashsize" },
  90:     "",
  91: };
  92: 
  93: flushroutes()
  94: {
  95:     struct mbuf mb;
  96:     register struct rtentry *rt;
  97:     register struct mbuf *m;
  98:     struct mbuf **routehash;
  99:     int rthashsize, i, doinghost = 1, kmem;
 100:     char *routename(), *netname();
 101: 
 102:     nlist("/vmunix", nl);
 103:     if (nl[N_RTHOST].n_value == 0) {
 104:         printf("route: \"rthost\", symbol not in namelist\n");
 105:         exit(1);
 106:     }
 107:     if (nl[N_RTNET].n_value == 0) {
 108:         printf("route: \"rtnet\", symbol not in namelist\n");
 109:         exit(1);
 110:     }
 111:     if (nl[N_RTHASHSIZE].n_value == 0) {
 112:         printf("route: \"rthashsize\", symbol not in namelist\n");
 113:         exit(1);
 114:     }
 115:     kmem = open("/dev/kmem", 0);
 116:     if (kmem < 0) {
 117:         perror("route: /dev/kmem");
 118:         exit(1);
 119:     }
 120:     lseek(kmem, nl[N_RTHASHSIZE].n_value, 0);
 121:     read(kmem, &rthashsize, sizeof (rthashsize));
 122:     routehash = (struct mbuf **)malloc(rthashsize*sizeof (struct mbuf *));
 123: 
 124:     lseek(kmem, nl[N_RTHOST].n_value, 0);
 125:     read(kmem, routehash, rthashsize*sizeof (struct mbuf *));
 126:     printf("Flushing routing tables:\n");
 127: again:
 128:     for (i = 0; i < rthashsize; i++) {
 129:         if (routehash[i] == 0)
 130:             continue;
 131:         m = routehash[i];
 132:         while (m) {
 133:             lseek(kmem, m, 0);
 134:             read(kmem, &mb, sizeof (mb));
 135:             rt = mtod(&mb, struct rtentry *);
 136:             if (rt->rt_flags & RTF_GATEWAY) {
 137:                 printf("%-20.20s ", doinghost ?
 138:                     routename(&rt->rt_dst) :
 139:                     netname(&rt->rt_dst));
 140:                 printf("%-20.20s ", routename(&rt->rt_gateway));
 141:                 if (ioctl(s, SIOCDELRT, (caddr_t)rt) < 0)
 142:                     error("delete");
 143:                 else
 144:                     printf("done\n");
 145:             }
 146:             m = mb.m_next;
 147:         }
 148:     }
 149:     if (doinghost) {
 150:         lseek(kmem, nl[N_RTNET].n_value, 0);
 151:         read(kmem, routehash, rthashsize*sizeof (struct mbuf *));
 152:         doinghost = 0;
 153:         goto again;
 154:     }
 155:     close(kmem);
 156:     free(routehash);
 157: }
 158: 
 159: char *
 160: routename(sa)
 161:     struct sockaddr *sa;
 162: {
 163:     register char *cp;
 164:     static char line[50];
 165:     struct hostent *hp;
 166:     static char domain[MAXHOSTNAMELEN + 1];
 167:     static int first = 1;
 168:     char *index();
 169:     char *ns_print();
 170: 
 171:     if (first) {
 172:         first = 0;
 173:         if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
 174:             (cp = index(domain, '.')))
 175:             (void) strcpy(domain, cp + 1);
 176:         else
 177:             domain[0] = 0;
 178:     }
 179:     switch (sa->sa_family) {
 180: 
 181:     case AF_INET:
 182:         {   struct in_addr in;
 183:         in = ((struct sockaddr_in *)sa)->sin_addr;
 184: 
 185:         cp = 0;
 186:         if (in.s_addr == INADDR_ANY)
 187:             cp = "default";
 188:         if (cp == 0 && !nflag) {
 189:             hp = gethostbyaddr(&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:             strcpy(line, cp);
 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:         break;
 207:         }
 208: 
 209:     case AF_NS:
 210:         return (ns_print((struct sockaddr_ns *)sa));
 211: 
 212:     default:
 213:         {   u_short *s = (u_short *)sa->sa_data;
 214: 
 215:         sprintf(line, "af %d: %x %x %x %x %x %x %x", sa->sa_family,
 216:             s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
 217:         break;
 218:         }
 219:     }
 220:     return (line);
 221: }
 222: 
 223: /*
 224:  * Return the name of the network whose address is given.
 225:  * The address is assumed to be that of a net or subnet, not a host.
 226:  */
 227: char *
 228: netname(sa)
 229:     struct sockaddr *sa;
 230: {
 231:     char *cp = 0;
 232:     static char line[50];
 233:     struct netent *np = 0;
 234:     u_long net, mask;
 235:     register i;
 236:     int subnetshift;
 237: 
 238:     switch (sa->sa_family) {
 239: 
 240:     case AF_INET:
 241:         {   struct in_addr in;
 242:         in = ((struct sockaddr_in *)sa)->sin_addr;
 243: 
 244:         in.s_addr = ntohl(in.s_addr);
 245:         if (in.s_addr == 0)
 246:             cp = "default";
 247:         else if (!nflag) {
 248:             if (IN_CLASSA(i)) {
 249:                 mask = IN_CLASSA_NET;
 250:                 subnetshift = 8;
 251:             } else if (IN_CLASSB(i)) {
 252:                 mask = IN_CLASSB_NET;
 253:                 subnetshift = 8;
 254:             } else {
 255:                 mask = IN_CLASSC_NET;
 256:                 subnetshift = 4;
 257:             }
 258:             /*
 259: 			 * If there are more bits than the standard mask
 260: 			 * would suggest, subnets must be in use.
 261: 			 * Guess at the subnet mask, assuming reasonable
 262: 			 * width subnet fields.
 263: 			 */
 264:             while (in.s_addr &~ mask)
 265:                 mask = (long)mask >> subnetshift;
 266:             net = in.s_addr & mask;
 267:             while ((mask & 1) == 0)
 268:                 mask >>= 1, net >>= 1;
 269:             np = getnetbyaddr(net, AF_INET);
 270:             if (np)
 271:                 cp = np->n_name;
 272:         }
 273:         if (cp)
 274:             strcpy(line, cp);
 275:         else if ((in.s_addr & 0xffffff) == 0)
 276:             sprintf(line, "%u", C(in.s_addr >> 24));
 277:         else if ((in.s_addr & 0xffff) == 0)
 278:             sprintf(line, "%u.%u", C(in.s_addr >> 24),
 279:                 C(in.s_addr >> 16));
 280:         else if ((in.s_addr & 0xff) == 0)
 281:             sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
 282:                 C(in.s_addr >> 16), C(in.s_addr >> 8));
 283:         else
 284:             sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
 285:                 C(in.s_addr >> 16), C(in.s_addr >> 8),
 286:                 C(in.s_addr));
 287:         break;
 288:         }
 289: 
 290:     case AF_NS:
 291:         return (ns_print((struct sockaddr_ns *)sa));
 292:         break;
 293: 
 294:     default:
 295:         {   u_short *s = (u_short *)sa->sa_data;
 296: 
 297:         sprintf(line, "af %d: %x %x %x %x %x %x %x", sa->sa_family,
 298:             s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
 299:         break;
 300:         }
 301:     }
 302:     return (line);
 303: }
 304: 
 305: newroute(argc, argv)
 306:     int argc;
 307:     char *argv[];
 308: {
 309:     struct sockaddr_in *sin;
 310:     char *cmd, *dest, *gateway;
 311:     int ishost, metric = 0, ret, attempts, oerrno;
 312:     struct hostent *hp;
 313:     extern int errno;
 314: 
 315:     cmd = argv[0];
 316:     if ((strcmp(argv[1], "host")) == 0) {
 317:         forcehost++;
 318:         argc--, argv++;
 319:     } else if ((strcmp(argv[1], "net")) == 0) {
 320:         forcenet++;
 321:         argc--, argv++;
 322:     }
 323:     if (*cmd == 'a') {
 324:         if (argc != 4) {
 325:             printf("usage: %s destination gateway metric\n", cmd);
 326:             printf("(metric of 0 if gateway is this host)\n");
 327:             return;
 328:         }
 329:         metric = atoi(argv[3]);
 330:     } else {
 331:         if (argc < 3) {
 332:             printf("usage: %s destination gateway\n", cmd);
 333:             return;
 334:         }
 335:     }
 336:     sin = (struct sockaddr_in *)&route.rt_dst;
 337:     ishost = getaddr(argv[1], &route.rt_dst, &hp, &dest, forcenet);
 338:     if (forcehost)
 339:         ishost = 1;
 340:     if (forcenet)
 341:         ishost = 0;
 342:     sin = (struct sockaddr_in *)&route.rt_gateway;
 343:     (void) getaddr(argv[2], &route.rt_gateway, &hp, &gateway, 0);
 344:     route.rt_flags = RTF_UP;
 345:     if (ishost)
 346:         route.rt_flags |= RTF_HOST;
 347:     if (metric > 0)
 348:         route.rt_flags |= RTF_GATEWAY;
 349:     for (attempts = 1; ; attempts++) {
 350:         errno = 0;
 351:         if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT,
 352:              (caddr_t)&route)) == 0)
 353:             break;
 354:         if (errno != ENETUNREACH && errno != ESRCH)
 355:             break;
 356:         if (hp && hp->h_addr_list[1]) {
 357:             hp->h_addr_list++;
 358:             bcopy(hp->h_addr_list[0], (caddr_t)&sin->sin_addr,
 359:                 hp->h_length);
 360:         } else
 361:             break;
 362:     }
 363:     oerrno = errno;
 364:     printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net",
 365:         dest, gateway);
 366:     if (attempts > 1 && ret == 0)
 367:         printf(" (%s)",
 368:         inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
 369:     if (ret == 0)
 370:         printf("\n");
 371:     else {
 372:         printf(": ");
 373:         fflush(stdout);
 374:         errno = oerrno;
 375:         error(0);
 376:     }
 377: }
 378: 
 379: changeroute(argc, argv)
 380:     int argc;
 381:     char *argv[];
 382: {
 383:     printf("not supported\n");
 384: }
 385: 
 386: error(cmd)
 387:     char *cmd;
 388: {
 389: 
 390:     if (errno == ESRCH)
 391:         fprintf(stderr, "not in table\n");
 392:     else if (errno == EBUSY)
 393:         fprintf(stderr, "entry in use\n");
 394:     else if (errno == ENOBUFS)
 395:         fprintf(stderr, "routing table overflow\n");
 396:     else
 397:         perror(cmd);
 398: }
 399: 
 400: char *
 401: savestr(s)
 402:     char *s;
 403: {
 404:     char *sav;
 405: 
 406:     sav = malloc(strlen(s) + 1);
 407:     if (sav == NULL) {
 408:         fprintf("route: out of memory\n");
 409:         exit(1);
 410:     }
 411:     strcpy(sav, s);
 412:     return (sav);
 413: }
 414: 
 415: /*
 416:  * Interpret an argument as a network address of some kind,
 417:  * returning 1 if a host address, 0 if a network address.
 418:  */
 419: getaddr(s, sin, hpp, name, isnet)
 420:     char *s;
 421:     struct sockaddr_in *sin;
 422:     struct hostent **hpp;
 423:     char **name;
 424:     int isnet;
 425: {
 426:     struct hostent *hp;
 427:     struct netent *np;
 428:     u_long val;
 429: 
 430:     *hpp = 0;
 431:     if (strcmp(s, "default") == 0) {
 432:         sin->sin_family = AF_INET;
 433:         sin->sin_addr = inet_makeaddr(0, INADDR_ANY);
 434:         *name = "default";
 435:         return(0);
 436:     }
 437:     sin->sin_family = AF_INET;
 438:     if (isnet == 0) {
 439:         val = inet_addr(s);
 440:         if (val != -1) {
 441:             sin->sin_addr.s_addr = val;
 442:             *name = s;
 443:             return(inet_lnaof(sin->sin_addr) != INADDR_ANY);
 444:         }
 445:     }
 446:     val = inet_network(s);
 447:     if (val != -1) {
 448:         sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
 449:         *name = s;
 450:         return(0);
 451:     }
 452:     np = getnetbyname(s);
 453:     if (np) {
 454:         sin->sin_family = np->n_addrtype;
 455:         sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
 456:         *name = savestr(np->n_name);
 457:         return(0);
 458:     }
 459:     hp = gethostbyname(s);
 460:     if (hp) {
 461:         *hpp = hp;
 462:         sin->sin_family = hp->h_addrtype;
 463:         bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
 464:         *name = savestr(hp->h_name);
 465:         return(1);
 466:     }
 467:     fprintf(stderr, "%s: bad value\n", s);
 468:     exit(1);
 469: }
 470: 
 471: short ns_nullh[] = {0,0,0};
 472: short ns_bh[] = {-1,-1,-1};
 473: 
 474: char *
 475: ns_print(sns)
 476: struct sockaddr_ns *sns;
 477: {
 478:     struct ns_addr work;
 479:     union { union ns_net net_e; u_long long_e; } net;
 480:     u_short port;
 481:     static char mybuf[50], cport[10], chost[25];
 482:     char *host = "";
 483:     register char *p; register u_char *q; u_char *q_lim;
 484: 
 485:     work = sns->sns_addr;
 486:     port = ntohs(work.x_port);
 487:     work.x_port = 0;
 488:     net.net_e  = work.x_net;
 489:     if (ns_nullhost(work) && net.long_e == 0) {
 490:         if (port ) {
 491:             sprintf(mybuf, "*.%xH", port);
 492:             upHex(mybuf);
 493:         } else
 494:             sprintf(mybuf, "*.*");
 495:         return (mybuf);
 496:     }
 497: 
 498:     if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
 499:         host = "any";
 500:     } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
 501:         host = "*";
 502:     } else {
 503:         q = work.x_host.c_host;
 504:         sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
 505:             q[0], q[1], q[2], q[3], q[4], q[5]);
 506:         for (p = chost; *p == '0' && p < chost + 12; p++);
 507:         host = p;
 508:     }
 509:     if (port)
 510:         sprintf(cport, ".%xH", htons(port));
 511:     else
 512:         *cport = 0;
 513: 
 514:     sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
 515:     upHex(mybuf);
 516:     return(mybuf);
 517: }
 518: 
 519: upHex(p0)
 520: char *p0;
 521: {
 522:     register char *p = p0;
 523:     for (; *p; p++) switch (*p) {
 524: 
 525:     case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 526:         *p += ('A' - 'a');
 527:     }
 528: }

Defined functions

changeroute defined in line 379; used 1 times
  • in line 71
error defined in line 386; used 2 times
flushroutes defined in line 93; used 1 times
  • in line 64
getaddr defined in line 419; used 2 times
main defined in line 38; never used
netname defined in line 227; used 2 times
newroute defined in line 305; used 2 times
ns_print defined in line 474; used 3 times
routename defined in line 159; used 3 times
savestr defined in line 400; used 2 times
upHex defined in line 519; used 2 times

Defined variables

copyright defined in line 8; never used
doflush defined in line 33; used 2 times
forcehost defined in line 33; used 2 times
forcenet defined in line 33; used 3 times
nflag defined in line 33; used 3 times
nl defined in line 83; used 7 times
ns_bh defined in line 472; used 1 times
ns_nullh defined in line 471; used 1 times
route defined in line 31; used 9 times
s defined in line 32; used 34 times
sccsid defined in line 14; never used
sin defined in line 34; used 16 times

Defined macros

C defined in line 201; used 14 times
N_RTHASHSIZE defined in line 88; used 2 times
N_RTHOST defined in line 84; used 2 times
N_RTNET defined in line 86; used 2 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2397
Valid CSS Valid XHTML 1.0 Strict