# 2.11BSD#431 - /usr/src/sbin/route/route.c

##### Functions

    changeroute       X
    error             X
    flushroutes       X
    getaddr           X
    main              X
    netname           X
    newroute          X
    ns_print          X
    routename         X
    savestr           X
    upHex             X

##### Variables

    base2_10          X
    copyright         X
    doflush           X
    forcehost         X
    forcenet          X
    kl                X
    nflag             X
    nl                X
    ns_bh             X
    ns_nullh          X
    route             X
    s                 X
    sin               X

##### Macros

    C                 X
    N_NETDATA         X
    N_RTHASHSIZE      X
    N_RTHOST          X
    N_RTNET           X

       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

- in line 178, 422

flushroutes defined in line 102; used 1 times

- in line 64

getaddr defined in line 472; used 2 times

- in line 384, 390

main defined in line 38; never used
netname defined in line 271; used 2 times

- in line 109, 175

newroute defined in line 352; used 2 times

- in line 67-69(2)

ns_print defined in line 527; used 4 times

- in line 209, 254, 281, 338

routename defined in line 199; used 3 times

- in line 109, 174-176(2)

savestr defined in line 453; used 2 times

- in line 509, 517

upHex defined in line 572; used 2 times

- in line 545, 568

#### Defined variables

base2_10 defined in line 94; used 6 times

- in line 144-145(3), 153, 166, 187

copyright defined in line 8; never used
doflush defined in line 33; used 2 times

- in line 56, 63

forcehost defined in line 33; used 2 times

- in line 364, 385

forcenet defined in line 33; used 3 times

- in line 367, 384-387(2)

kl defined in line 95; used 3 times

- in line 112-113(2), 143

nflag defined in line 33; used 3 times

- in line 59, 228, 292

nl defined in line 83; used 11 times

- in line 117-129(5), 145-147(2), 153-155(2), 187-189(2)

ns_bh defined in line 525; used 1 times

- in line 551

ns_nullh defined in line 524; used 1 times

- in line 553

route defined in line 31; used 9 times

- in line 383-399(8), 415

s defined in line 32; used 34 times

- in line 46-47(2), 177, 257-260(8), 342-345(8), 398, 454-464(4), 472-473(2), 484, 492-505(5), 512, 520

sccsid defined in line 12; never used
sin defined in line 34; used 16 times

- in line 356, 383, 389, 405, 472-474(2), 485-501(6), 507-508(2), 515-516(2)

#### Defined macros

C defined in line 244; used 14 times

- in line 247-248(4), 323-333(10)

N_NETDATA defined in line 96; used 2 times

- in line 113, 143

N_RTHASHSIZE defined in line 88; used 3 times

- in line 129, 145-147(2)

N_RTHOST defined in line 84; used 3 times

- in line 121, 153-155(2)

N_RTNET defined in line 86; used 3 times

- in line 125, 187-189(2)

Last modified: 1994-01-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2470 |