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

Defined functions

changeroute defined in line 426; used 1 times
  • in line 71
error defined in line 433; used 2 times
flushroutes defined in line 102; used 1 times
  • in line 64
getaddr defined in line 472; used 2 times
main defined in line 38; never used
netname defined in line 271; used 2 times
newroute defined in line 352; used 2 times
ns_print defined in line 527; used 4 times
routename defined in line 199; used 3 times
savestr defined in line 453; used 2 times
upHex defined in line 572; used 2 times

Defined variables

base2_10 defined in line 94; used 6 times
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
kl defined in line 95; used 3 times
nflag defined in line 33; used 3 times
nl defined in line 83; used 11 times
ns_bh defined in line 525; used 1 times
ns_nullh defined in line 524; used 1 times
route defined in line 31; used 9 times
s defined in line 32; used 34 times
sccsid defined in line 12; never used
sin defined in line 34; used 16 times

Defined macros

C defined in line 244; used 14 times
N_NETDATA defined in line 96; used 2 times
N_RTHASHSIZE defined in line 88; used 3 times
N_RTHOST defined in line 84; used 3 times
N_RTNET defined in line 86; used 3 times
Last modified: 1994-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6066
Valid CSS Valid XHTML 1.0 Strict