home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / new / comm / net / amitcp / amitcp-2.2 / src / util / route / route.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-21  |  31.5 KB  |  1,359 lines

  1. RCS_ID_C = "$Id: route.c,v 1.6 1993/08/10 20:46:23 jraja Exp $";
  2. /* 
  3.  * route.c
  4.  *
  5.  * Author: jraja <Jarno.Rajahalme@hut.fi>
  6.  *
  7.  * Last modified: Tue Aug 10 23:38:41 1993 jraja
  8.  */
  9.  
  10. static const char version[] = "$VER: route 2.0 (13.8.93)";
  11.  
  12. char copyright[] =
  13. "@(#) Copyright © 1983, 1989 The Regents of the University of California.\n"
  14.                       "All rights reserved.\n"
  15.      "Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
  16.                       "Helsinki University of Technology, Finland.\n"
  17.                       "All rights reserved.\n";
  18.  
  19. /*
  20.  * Copyright © 1983, 1989 The Regents of the University of California.
  21.  * All rights reserved.
  22.  *
  23.  * Redistribution and use in source and binary forms, with or without
  24.  * modification, are permitted provided that the following conditions
  25.  * are met:
  26.  * 1. Redistributions of source code must retain the above copyright
  27.  *    notice, this list of conditions and the following disclaimer.
  28.  * 2. Redistributions in binary form must reproduce the above copyright
  29.  *    notice, this list of conditions and the following disclaimer in the
  30.  *    documentation and/or other materials provided with the distribution.
  31.  * 3. All advertising materials mentioning features or use of this software
  32.  *    must display the following acknowledgement:
  33.  *    This product includes software developed by the University of
  34.  *    California, Berkeley and its contributors.
  35.  * 4. Neither the name of the University nor the names of its contributors
  36.  *    may be used to endorse or promote products derived from this software
  37.  *    without specific prior written permission.
  38.  *
  39.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  40.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  42.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  43.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  44.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  45.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  46.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  47.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  48.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  49.  * SUCH DAMAGE.
  50.  */
  51.  
  52. static char sccsid[] = "@(#)route.c    5.35 (Berkeley) 6/27/91";
  53.  
  54. /****** netutil.doc/route ***************************************************
  55. *
  56. *   NAME
  57. *        route - manually manipulate the routing tables
  58. *   
  59. *   SYNOPSIS
  60. *        route [-n] [-q] [-v] command [modifiers] destination gateway
  61. *   
  62. *   DESCRIPTION
  63. *        Route is a program used to manually manipulate the network routing
  64. *        tables. 
  65. *   
  66. *        Options supported by route:
  67. *   
  68. *        -n      Prevent attempts to print host and network names
  69. *                symbolically when reporting actions.
  70. *   
  71. *        -v      (verbose) Print additional details.
  72. *   
  73. *        -q      Suppress all output.
  74. *   
  75. *        Commands accepted by route:
  76. *   
  77. *        add         Add a route.
  78. *        delete      Delete a specific route.
  79. *   
  80. *        The destination is the destination host or network, gateway is the
  81. *        next-hop gateway to which packets should be addressed. Routes to a
  82. *        particular host are distinguished from those to a network by
  83. *        interpreting the Internet address associated with destination. The
  84. *        optional modifiers -net and -host force the destination to be
  85. *        interpreted as a network or a host, respectively.  Otherwise, if the
  86. *        destination has a ``local address part'' of INADDR_ANY, or if the
  87. *        destination is the symbolic name of a network, then the route is
  88. *        assumed to be to a network; otherwise, it is presumed to be a route
  89. *        to a host.
  90. *   
  91. *        For example, 128.32 is interpreted as -host 128.0.0.32; 128.32.130
  92. *        is interpreted as -host 128.32.0.130; -net 128.32 is interpreted as
  93. *        128.32.0.0; and -net 128.32.130 is interpreted as 128.32.130.0.
  94. *   
  95. *        To add a default route, give the destination as 'default'.
  96. *    
  97. *        If the route is via an interface rather than via a gateway, the
  98. *        -interface modifier should be specified; the gateway given is the
  99. *        address of this host on the common network, indicating the interface
  100. *        to be used for transmission.
  101. *   
  102. *        The optional -netmask qualifier is used to specify the netmask of
  103. *        the interface. One specifies an additional ensuing address parameter
  104. *        (to be interpreted as a network mask).  The implicit network mask
  105. *        generated can be overridden by making sure this option follows the
  106. *        destination parameter.
  107. *   
  108. *        All symbolic names specified for a destination or gateway are looked
  109. *        up first as a host name using gethostbyname(). If this lookup fails,
  110. *        getnetbyname() is then used to interpret the name as that of a
  111. *        network.
  112. *   
  113. *   DIAGNOSTICS
  114. *        add [host | network ] %s: gateway %s flags %x
  115. *                The specified route is being added to the tables. The values
  116. *                printed are from the routing table entry supplied in the
  117. *                IoctlSocket() call. If the gateway address used was not the
  118. *                primary address of the gateway (the first one returned by
  119. *                gethostbyname()), the gateway address is printed numerically
  120. *                as well as symbolically.
  121. *   
  122. *        delete [ host | network ] %s: gateway %s flags %x
  123. *                As above, but when deleting an entry.
  124. *   
  125. *        Network is unreachable
  126. *                An attempt to add a route failed because the gateway listed
  127. *                was not on a directly-connected network.  The next-hop
  128. *                gateway must be given.
  129. *   
  130. *        not in table
  131. *                A delete operation was attempted for an entry which wasn't
  132. *                present in the tables.
  133. *   
  134. *        routing table overflow
  135. *                An add operation was attempted, but the system was low on
  136. *                resources and was unable to allocate memory to create the
  137. *                new entry.
  138. *   
  139. *   SEE ALSO
  140. *        ifconfig, protocols/routing
  141. *   
  142. *   HISTORY
  143. *        The route command appeared in 4.2BSD.
  144. *   
  145. *****************************************************************************
  146. *
  147. */
  148.  
  149. #include <sys/param.h>
  150. #include <sys/socket.h>
  151. #include <sys/ioctl.h>
  152.  
  153. #include <net/route.h>
  154. #include <netinet/in.h>
  155. #include <arpa/inet.h>
  156. #include <netdb.h>
  157.  
  158. #include <errno.h>
  159. #include <stdio.h>
  160. #include <ctype.h>
  161. #include <stdlib.h>
  162. #include <string.h>
  163.  
  164. #ifdef AMIGA
  165. #if __SASC
  166. #include <proto/socket.h>
  167. #elif __GNUC__
  168. #include <inline/socket.h>
  169. #else
  170. #include <clib/socket_protos.h>
  171. #endif
  172. #define herror(x) perror(x)
  173. #define ioctl IoctlSocket
  174. #endif /* AMIGA */
  175.  
  176. struct keytab {
  177.     char    *kt_cp;
  178.     int    kt_i;
  179. } keywords[] = {
  180. #include "keywords.h"
  181. {0, 0}
  182. };
  183.  
  184. struct    ortentry route;
  185. union    sockunion {
  186.     struct    sockaddr sa;
  187.     struct    sockaddr_in sin;
  188. #if 0
  189.     struct    sockaddr_ns sns;
  190.     struct    sockaddr_iso siso;
  191.     struct    sockaddr_dl sdl;
  192.     struct    sockaddr_x25 sx25;
  193. #endif
  194. } so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
  195.  
  196. union sockunion *so_addrs[] =
  197.     { &so_dst, &so_gate, &so_mask, &so_genmask, &so_ifp, &so_ifa, 0}; 
  198.  
  199. typedef union sockunion *sup;
  200. int    rtm_addrs;
  201. int    s;
  202. int    forcehost, forcenet, doflush, nflag, af, qflag, tflag, Cflag, 
  203.   keyword(char *cp);
  204. int    iflag, verbose, aflen = sizeof (struct sockaddr_in);
  205. int    locking, lockrest, debugonly;
  206. struct    sockaddr_in sin = { sizeof(sin), AF_INET };
  207. struct    rt_metrics rt_metrics;
  208. u_long  rtm_inits;
  209. #if 0
  210. struct    in_addr inet_makeaddr();
  211. #endif
  212. char    *routename(struct sockaddr *sa), *netname(struct sockaddr *sa);
  213. void    flushroutes(int argc, char *argv[]), 
  214.   newroute(int argc, char **argv), monitor(void), sockaddr();
  215. void    print_getmsg(), print_rtmsg(), pmsg_common(), sodump(), bprintf();
  216. int    getaddr(int which, char *s, struct hostent **hpp), rtmsg();
  217. #if 0
  218. extern    char *inet_ntoa(), *iso_ntoa(), *link_ntoa();
  219. #endif
  220.  
  221. void
  222. usage(cp)
  223.     char *cp;
  224. {
  225.     if (cp)
  226.         (void) fprintf(stderr, "route: botched keyword: %s\n", cp);
  227.     (void) fprintf(stderr,
  228.         "usage: route [ -Cnqv ] cmd [[ -<qualifers> ] args ]\n");
  229.     exit(1);
  230.     /* NOTREACHED */
  231. }
  232.  
  233. void
  234. quit(s)
  235.     char *s;
  236. {
  237.     int sverrno = errno;
  238.  
  239.     (void) fprintf(stderr, "route: ");
  240.     if (s)
  241.         (void) fprintf(stderr, "%s: ", s);
  242.     (void) fprintf(stderr, "%s\n", strerror(sverrno));
  243.     exit(1);
  244.     /* NOTREACHED */
  245. }
  246.  
  247. #define ROUNDUP(a) \
  248.     ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  249. #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  250.  
  251. main(argc, argv)
  252.     int argc;
  253.     char **argv;
  254. {
  255.     extern int optind;
  256.     int ch;
  257.     char *argvp;
  258.  
  259.     if (argc < 2)
  260.         usage((char *)NULL);
  261.  
  262.     while ((ch = getopt(argc, argv, "Cnqtv")) != EOF)
  263.         switch(ch) {
  264.         case 'C':
  265.             Cflag = 1;    /* Use old ioctls. */
  266.             break;
  267.         case 'n':
  268.             nflag = 1;
  269.             break;
  270.         case 'q':
  271.             qflag = 1;
  272.             break;
  273.         case 'v':
  274.             verbose = 1;
  275.             break;
  276.         case 't':
  277.             tflag = 1;
  278.             break;
  279.         case '?':
  280.         default:
  281.             usage();
  282.         }
  283.     argc -= optind;
  284.     argv += optind;
  285.  
  286.     Cflag = 1;    /* Force old ioctls. */
  287.  
  288.     if (Cflag)
  289.         s = socket(AF_INET, SOCK_RAW, 0);
  290.     if (s < 0)
  291.         quit("socket");
  292.     if (*argv)
  293.         switch (keyword(*argv)) {
  294.         case K_GET:
  295. #if 0
  296.             uid = 0;
  297. #endif
  298.             /* FALLTHROUGH */
  299.  
  300.         case K_CHANGE:
  301.             if (Cflag)
  302.                 usage("change or get with -C");
  303.             /* FALLTHROUGH */
  304.  
  305.         case K_ADD:
  306.         case K_DELETE:
  307.             newroute(argc, argv);
  308.             exit(0);
  309.             /* NOTREACHED */
  310.  
  311.         case K_MONITOR:
  312.             monitor();
  313.             /* NOTREACHED */
  314.  
  315.         case K_FLUSH:
  316.             flushroutes(argc, argv);
  317.             exit(0);
  318.             /* NOTREACHED */
  319.         }
  320.     usage(*argv);
  321.     /* NOTREACHED */
  322. }
  323.  
  324. /*
  325.  * Purge all entries in the routing tables not
  326.  * associated with network interfaces.
  327.  */
  328. void
  329. flushroutes(argc, argv)
  330.     int argc;
  331.     char *argv[];
  332. {
  333. #if 0
  334.     int needed, seqno, rlen;
  335.     char *buf, *next, *lim;
  336.     register struct rt_msghdr *rtm;
  337.  
  338.     if (uid)
  339.         quit("must be root to alter routing table");
  340.     shutdown(s, 0); /* Don't want to read back our messages */
  341.     if (argc > 1) {
  342.         argv++;
  343.         if (argc == 2 && **argv == '-')
  344.             switch (keyword(*argv + 1)) {
  345.             case K_INET:
  346.                 af = AF_INET;
  347.                 break;
  348.             case K_XNS:
  349.                 af = AF_NS;
  350.                 break;
  351.             case K_LINK:
  352.                 af = AF_LINK;
  353.                 break;
  354.             case K_ISO:
  355.             case K_OSI:
  356.                 af = AF_ISO;
  357.                 break;
  358.             case K_X25:
  359.                 af = AF_CCITT;
  360.             default:
  361.                 goto bad;
  362.         } else
  363. bad:            usage(*argv);
  364.     }
  365.     if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0)
  366.         quit("route-getkerninfo-estimate");
  367.     if ((buf = malloc(needed)) == NULL)
  368.         quit("malloc");
  369.     if ((rlen = getkerninfo(KINFO_RT_DUMP, buf, &needed, 0)) < 0)
  370.         quit("actual retrieval of routing table");
  371.     lim = buf + rlen;
  372.     seqno = 0;        /* ??? */
  373.     for (next = buf; next < lim; next += rtm->rtm_msglen) {
  374.         rtm = (struct rt_msghdr *)next;
  375.         if ((rtm->rtm_flags & RTF_GATEWAY) == 0)
  376.             continue;
  377.         if (af) {
  378.             struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
  379.  
  380.             if (sa->sa_family != af)
  381.                 continue;
  382.         }
  383.         rtm->rtm_type = RTM_DELETE;
  384.         rtm->rtm_seq = seqno;
  385.         rlen = write(s, next, rtm->rtm_msglen);
  386.         if (rlen < (int)rtm->rtm_msglen) {
  387.             (void) fprintf(stderr,
  388.                 "route: write to routing socket: %s\n",
  389.                 strerror(errno));
  390.             (void) printf("got only %d for rlen\n", rlen);
  391.             break;
  392.         }
  393.         seqno++;
  394.         if (qflag)
  395.             continue;
  396.         if (verbose)
  397.             print_rtmsg(rtm, rlen);
  398.         else {
  399.             struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
  400.             (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
  401.                 routename(sa) : netname(sa));
  402.             sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
  403.             (void) printf("%-20.20s ", routename(sa));
  404.             (void) printf("done\n");
  405.         }
  406.     }
  407. #endif /* 0 */
  408. }
  409.     
  410. char *
  411. routename(sa)
  412.     struct sockaddr *sa;
  413. {
  414.     register char *cp;
  415.     static char line[50];
  416.     struct hostent *hp;
  417.     static char domain[MAXHOSTNAMELEN + 1];
  418.     static int first = 1;
  419.     char *ns_print();
  420.  
  421.     if (first) {
  422.         first = 0;
  423.         if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
  424.             (cp = index(domain, '.')))
  425.             (void) strcpy(domain, cp + 1);
  426.         else
  427.             domain[0] = 0;
  428.     }
  429.     switch (sa->sa_family) {
  430.  
  431.     case AF_INET:
  432.         {    struct in_addr in;
  433.         in = ((struct sockaddr_in *)sa)->sin_addr;
  434.  
  435.         cp = 0;
  436.         if (in.s_addr == INADDR_ANY)
  437.             cp = "default";
  438.         if (cp == 0 && !nflag) {
  439.             hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
  440.                 AF_INET);
  441.             if (hp) {
  442.                 if ((cp = index(hp->h_name, '.')) &&
  443.                     !strcmp(cp + 1, domain))
  444.                     *cp = 0;
  445.                 cp = hp->h_name;
  446.             }
  447.         }
  448.         if (cp)
  449.             strcpy(line, cp);
  450.         else {
  451. #define C(x)    ((x) & 0xff)
  452.             in.s_addr = ntohl(in.s_addr);
  453.             (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
  454.                C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
  455.         }
  456.         break;
  457.         }
  458. #if 0
  459.     case AF_NS:
  460.         return (ns_print((struct sockaddr_ns *)sa));
  461.  
  462.     case AF_LINK:
  463.         return (link_ntoa((struct sockaddr_dl *)sa));
  464.  
  465.     case AF_ISO:
  466.         (void) sprintf(line, "iso %s",
  467.             iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr));
  468.         break;
  469. #endif
  470.     default:
  471.         {    u_short *s = (u_short *)sa->sa_data;
  472.         u_short *slim = s + ((sa->sa_len + 1) >> 1);
  473.         char *cp = line + sprintf(line, "(%d)", sa->sa_family);
  474.  
  475.         while (s < slim)
  476.             cp += sprintf(cp, " %x", *s++);
  477.         break;
  478.         }
  479.     }
  480.     return (line);
  481. }
  482.  
  483. /*
  484.  * Return the name of the network whose address is given.
  485.  * The address is assumed to be that of a net or subnet, not a host.
  486.  */
  487. char *
  488. netname(sa)
  489.     struct sockaddr *sa;
  490. {
  491.     char *cp = 0;
  492.     static char line[50];
  493.     struct netent *np = 0;
  494.     u_long net, mask;
  495.     register u_long i;
  496.     int subnetshift;
  497.     char *ns_print();
  498.  
  499.     switch (sa->sa_family) {
  500.  
  501.     case AF_INET:
  502.         {    struct in_addr in;
  503.         in = ((struct sockaddr_in *)sa)->sin_addr;
  504.  
  505.         i = in.s_addr = ntohl(in.s_addr);
  506.         if (in.s_addr == 0)
  507.             cp = "default";
  508.         else if (!nflag) {
  509.             if (IN_CLASSA(i)) {
  510.                 mask = IN_CLASSA_NET;
  511.                 subnetshift = 8;
  512.             } else if (IN_CLASSB(i)) {
  513.                 mask = IN_CLASSB_NET;
  514.                 subnetshift = 8;
  515.             } else {
  516.                 mask = IN_CLASSC_NET;
  517.                 subnetshift = 4;
  518.             }
  519.             /*
  520.              * If there are more bits than the standard mask
  521.              * would suggest, subnets must be in use.
  522.              * Guess at the subnet mask, assuming reasonable
  523.              * width subnet fields.
  524.              */
  525.             while (in.s_addr &~ mask)
  526.                 mask = (long)mask >> subnetshift;
  527.             net = in.s_addr & mask;
  528.             while ((mask & 1) == 0)
  529.                 mask >>= 1, net >>= 1;
  530.             np = getnetbyaddr(net, AF_INET);
  531.             if (np)
  532.                 cp = np->n_name;
  533.         }
  534.         if (cp)
  535.             strcpy(line, cp);
  536.         else if ((in.s_addr & 0xffffff) == 0)
  537.             (void) sprintf(line, "%u", C(in.s_addr >> 24));
  538.         else if ((in.s_addr & 0xffff) == 0)
  539.             (void) sprintf(line, "%u.%u", C(in.s_addr >> 24),
  540.                 C(in.s_addr >> 16));
  541.         else if ((in.s_addr & 0xff) == 0)
  542.             (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
  543.                 C(in.s_addr >> 16), C(in.s_addr >> 8));
  544.         else
  545.             (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
  546.                 C(in.s_addr >> 16), C(in.s_addr >> 8),
  547.                 C(in.s_addr));
  548.         break;
  549.         }
  550. #if 0
  551.     case AF_NS:
  552.         return (ns_print((struct sockaddr_ns *)sa));
  553.         break;
  554.  
  555.     case AF_LINK:
  556.         return (link_ntoa((struct sockaddr_dl *)sa));
  557.  
  558.     case AF_ISO:
  559.         (void) sprintf(line, "iso %s",
  560.             iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr));
  561.         break;
  562. #endif
  563.     default:
  564.         {    u_short *s = (u_short *)sa->sa_data;
  565.         u_short *slim = s + ((sa->sa_len + 1)>>1);
  566.         char *cp = line + sprintf(line, "af %d:", sa->sa_family);
  567.  
  568.         while (s < slim)
  569.             cp += sprintf(cp, " %x", *s++);
  570.         break;
  571.         }
  572.     }
  573.     return (line);
  574. }
  575.  
  576. void
  577. set_metric(value, key)
  578.     char *value;
  579.     int key;
  580. {
  581. #if 0
  582.     int flag = 0; 
  583.     u_long noval, *valp = &noval;
  584.  
  585.     switch (key) {
  586. #define caseof(x, y, z)    case x: valp = &rt_metrics.z; flag = y; break
  587.     caseof(K_MTU, RTV_MTU, rmx_mtu);
  588.     caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount);
  589.     caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire);
  590.     caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe);
  591.     caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe);
  592.     caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh);
  593.     caseof(K_RTT, RTV_RTT, rmx_rtt);
  594.     caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar);
  595.     }
  596.     rtm_inits |= flag;
  597.     if (lockrest || locking)
  598.         rt_metrics.rmx_locks |= flag;
  599.     if (locking)
  600.         locking = 0;
  601.     *valp = atoi(value);
  602. #endif
  603. }
  604.  
  605. void
  606. newroute(argc, argv)
  607.     int argc;
  608.     register char **argv;
  609. {
  610.     char *cmd, *dest = "", *gateway = "", *err;
  611.     int ishost = 0, ret, attempts, oerrno, flags = 0;
  612.     int key;
  613.     struct hostent *hp = 0;
  614.  
  615. #if 0
  616.     if (uid)
  617.         quit("must be root to alter routing table");
  618. #endif
  619.     cmd = argv[0];
  620.     if (*cmd != 'g')
  621.         shutdown(s, 0); /* Don't want to read back our messages */
  622.     while (--argc > 0) {
  623.         if (**(++argv)== '-') {
  624.             switch (key = keyword(1 + *argv)) {
  625. #if 0
  626.             case K_LINK:
  627.                 af = AF_LINK;
  628.                 aflen = sizeof(struct sockaddr_dl);
  629.                 break;
  630.             case K_OSI:
  631.             case K_ISO:
  632.                 af = AF_ISO;
  633.                 aflen = sizeof(struct sockaddr_iso);
  634.                 break;
  635. #endif
  636.             case K_INET:
  637.                 af = AF_INET;
  638.                 aflen = sizeof(struct sockaddr_in);
  639.                 break;
  640. #if 0
  641.             case K_X25:
  642.                 af = AF_CCITT;
  643.                 aflen = sizeof(struct sockaddr_x25);
  644.                 break;
  645.             case K_SA:
  646.                 af = 0;
  647.                 aflen = sizeof(union sockunion);
  648.                 break;
  649.             case K_XNS:
  650.                 af = AF_NS;
  651.                 aflen = sizeof(struct sockaddr_ns);
  652.                 break;
  653. #endif
  654.             case K_IFACE:
  655.             case K_INTERFACE:
  656.                 iflag++;
  657.                 break;
  658.             case K_LOCK:
  659.                 locking = 1;
  660.                 break;
  661.             case K_LOCKREST:
  662.                 lockrest = 1;
  663.                 break;
  664.             case K_HOST:
  665.                 forcehost++;
  666.                 break;
  667.             case K_REJECT:
  668.                 flags |= RTF_REJECT;
  669.                 break;
  670.             case K_PROTO1:
  671.                 flags |= RTF_PROTO1;
  672.                 break;
  673.             case K_PROTO2:
  674.                 flags |= RTF_PROTO2;
  675.                 break;
  676.             case K_CLONING:
  677.                 flags |= RTF_CLONING;
  678.                 break;
  679.             case K_XRESOLVE:
  680.                 flags |= RTF_XRESOLVE;
  681.                 break;
  682.             case K_IFA:
  683.                 argc--;
  684.                 (void) getaddr(RTA_IFA, *++argv, 0);
  685.                 break;
  686.             case K_IFP:
  687.                 argc--;
  688.                 (void) getaddr(RTA_IFP, *++argv, 0);
  689.                 break;
  690.             case K_GENMASK:
  691.                 argc--;
  692.                 (void) getaddr(RTA_GENMASK, *++argv, 0);
  693.                 break;
  694.             case K_GATEWAY:
  695.                 argc--;
  696.                 (void) getaddr(RTA_GATEWAY, *++argv, 0);
  697.                 break;
  698.             case K_DST:
  699.                 argc--;
  700.                 ishost = getaddr(RTA_DST, *++argv, &hp);
  701.                 dest = *argv;
  702.                 break;
  703.             case K_NETMASK:
  704.                 argc--;
  705.                 (void) getaddr(RTA_NETMASK, *++argv, 0);
  706.                 /* FALLTHROUGH */
  707.             case K_NET:
  708.                 forcenet++;
  709.                 break;
  710.             case K_MTU:
  711.             case K_HOPCOUNT:
  712.             case K_EXPIRE:
  713.             case K_RECVPIPE:
  714.             case K_SENDPIPE:
  715.             case K_SSTHRESH:
  716.             case K_RTT:
  717.             case K_RTTVAR:
  718.                 argc--;
  719.                 set_metric(*++argv, key);
  720.                 break;
  721.             default:
  722.                 usage(1+*argv);
  723.             }
  724.         } else {
  725.             if ((rtm_addrs & RTA_DST) == 0) {
  726.                 dest = *argv;
  727.                 ishost = getaddr(RTA_DST, *argv, &hp);
  728.             } else if ((rtm_addrs & RTA_GATEWAY) == 0) {
  729.                 gateway = *argv;
  730.                 (void) getaddr(RTA_GATEWAY, *argv, &hp);
  731.             } else {
  732.                 int ret = atoi(*argv);
  733.                 if (ret == 0) {
  734.                     printf("%s,%s", "old usage of trailing 0",
  735.                        "assuming route to if\n");
  736.                     iflag = 1;
  737.                     continue;
  738.                 } else if (ret > 0 && ret < 10) {
  739.                     printf("old usage of trailing digit, ");
  740.                     printf("assuming route via gateway\n");
  741.                     iflag = 0;
  742.                     continue;
  743.                 }
  744.                 (void) getaddr(RTA_NETMASK, *argv, 0);
  745.             }
  746.         }
  747.     }
  748.     if (forcehost)
  749.         ishost = 1;
  750.     if (forcenet)
  751.         ishost = 0;
  752.     flags |= RTF_UP;
  753.     if (ishost)
  754.         flags |= RTF_HOST;
  755.     if (iflag == 0)
  756.         flags |= RTF_GATEWAY;
  757.     for (attempts = 1; ; attempts++) {
  758.         errno = 0;
  759.         if (Cflag && (af == AF_INET || af == AF_NS)) {
  760.             route.rt_flags = flags;
  761.             route.rt_dst = so_dst.sa;
  762.             route.rt_gateway = so_gate.sa;
  763.             if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT,
  764.                  (caddr_t)&route)) == 0)
  765.                 break;
  766. #if 0
  767.         } else {
  768.             if ((ret = rtmsg(*cmd, flags)) == 0)
  769.                 break;
  770. #endif
  771.         }
  772.         if (errno != ENETUNREACH && errno != ESRCH)
  773.             break;
  774.         if (af == AF_INET && hp && hp->h_addr_list[1]) {
  775.             hp->h_addr_list++;
  776.             bcopy(hp->h_addr_list[0], (caddr_t)&so_dst.sin.sin_addr,
  777.                 hp->h_length);
  778.         } else
  779.             break;
  780.     }
  781.     if (*cmd == 'g')
  782.         exit(0);
  783.     oerrno = errno;
  784.     (void) printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net",
  785.         dest, gateway);
  786.     if (attempts > 1 && ret == 0)
  787.         (void) printf(" (%s)",
  788.         inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
  789.     if (ret == 0)
  790.         (void) printf("\n");
  791.     else {
  792.         switch (oerrno) {
  793.         case ESRCH:
  794.             err = "not in table";
  795.             break;
  796.         case EBUSY:
  797.             err = "entry in use";
  798.             break;
  799.         case ENOBUFS:
  800.             err = "routing table overflow";
  801.             break;
  802.         default:
  803.             err = strerror(oerrno);
  804.             break;
  805.         }
  806.         (void) printf(": %s\n", err);
  807.     }
  808. }
  809.  
  810. void
  811. inet_makenetandmask(net, sin)
  812.     u_long net;
  813.     register struct sockaddr_in *sin;
  814. {
  815.     u_long addr, mask = 0;
  816.     register char *cp;
  817.  
  818.     rtm_addrs |= RTA_NETMASK;
  819.     if (net == 0)
  820.         mask = addr = 0;
  821.     else if (net < 128) {
  822.         addr = net << IN_CLASSA_NSHIFT;
  823.         mask = IN_CLASSA_NET;
  824.     } else if (net < 65536) {
  825.         addr = net << IN_CLASSB_NSHIFT;
  826.         mask = IN_CLASSB_NET;
  827.     } else if (net < 16777216L) {
  828.         addr = net << IN_CLASSC_NSHIFT;
  829.         mask = IN_CLASSC_NET;
  830.     } else {
  831.         addr = net;
  832.         if ((addr & IN_CLASSA_HOST) == 0)
  833.             mask =  IN_CLASSA_NET;
  834.         else if ((addr & IN_CLASSB_HOST) == 0)
  835.             mask =  IN_CLASSB_NET;
  836.         else if ((addr & IN_CLASSC_HOST) == 0)
  837.             mask =  IN_CLASSC_NET;
  838.         else
  839.             mask = -1;
  840.     }
  841.     sin->sin_addr.s_addr = htonl(addr);
  842.     sin = &so_mask.sin;
  843.     sin->sin_addr.s_addr = htonl(mask);
  844.     sin->sin_len = 0;
  845.     sin->sin_family = 0;
  846.     cp = (char *)(&sin->sin_addr + 1);
  847.     while (*--cp == 0 && cp > (char *)sin)
  848.         ;
  849.     sin->sin_len = 1 + cp - (char *)sin;
  850. }
  851.  
  852. /*
  853.  * Interpret an argument as a network address of some kind,
  854.  * returning 1 if a host address, 0 if a network address.
  855.  */
  856. int
  857. getaddr(which, s, hpp)
  858.     int which;
  859.     char *s;
  860.     struct hostent **hpp;
  861. {
  862.     register sup su;
  863. #if 0
  864.     struct ns_addr ns_addr();
  865.     struct iso_addr *iso_addr();
  866. #endif
  867.     struct hostent *hp;
  868.     struct netent *np;
  869.     u_long val;
  870.  
  871.     if (af == 0) {
  872.         af = AF_INET;
  873.         aflen = sizeof(struct sockaddr_in);
  874.     }
  875.     rtm_addrs |= which;
  876.     switch (which) {
  877.     case RTA_DST:        su = so_addrs[0]; su->sa.sa_family = af; break;
  878.     case RTA_GATEWAY:    su = so_addrs[1]; su->sa.sa_family = af; break;
  879.     case RTA_NETMASK:    su = so_addrs[2]; break;
  880.     case RTA_GENMASK:    su = so_addrs[3]; break;
  881.     case RTA_IFP:        su = so_addrs[4]; su->sa.sa_family = af; break;
  882.     case RTA_IFA:        su = so_addrs[5]; su->sa.sa_family = af; break;
  883.     default:        usage("Internal Error"); /*NOTREACHED*/
  884.     }
  885.     su->sa.sa_len = aflen;
  886.     if (strcmp(s, "default") == 0) {
  887.         switch (which) {
  888.         case RTA_DST:
  889.             forcenet++;
  890.             (void) getaddr(RTA_NETMASK, s, 0);
  891.             break;
  892.         case RTA_NETMASK:
  893.         case RTA_GENMASK:
  894.             su->sa.sa_len = 0;
  895.         }
  896.         return 0;
  897.     }
  898. #if 0
  899.     if (af == AF_NS)
  900.         goto do_xns;
  901.     if (af == AF_OSI)
  902.         goto do_osi;
  903.     if (af == AF_LINK)
  904.         goto do_link;
  905.     if (af == AF_CCITT)
  906.         goto do_ccitt;
  907.     if (af == 0)
  908.         goto do_sa;
  909. #endif
  910.     if (hpp == NULL)
  911.         hpp = &hp;
  912.     *hpp = NULL;
  913.     if (((val = inet_addr(s)) != -1) &&
  914.         (which != RTA_DST || forcenet == 0)) {
  915.         su->sin.sin_addr.s_addr = val;
  916.         if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
  917.             return (1);
  918.         else {
  919.             val = ntohl(val);
  920.         out:    if (which == RTA_DST)
  921.                 inet_makenetandmask(val, &su->sin);
  922.             return (0);
  923.         }
  924.     }
  925.     val = inet_network(s);
  926.     if (val != -1) {
  927.         goto out;
  928.     }
  929.     np = getnetbyname(s);
  930.     if (np) {
  931.         val = np->n_net;
  932.         goto out;
  933.     }
  934.     hp = gethostbyname(s);
  935.     if (hp) {
  936.         *hpp = hp;
  937.         su->sin.sin_family = hp->h_addrtype;
  938.         bcopy(hp->h_addr, (char *)&su->sin.sin_addr, hp->h_length);
  939.         return (1);
  940.     }
  941.     (void) fprintf(stderr, "%s: bad value\n", s);
  942.     exit(1);
  943. #if 0
  944. do_xns:
  945.     if (which == RTA_DST) {
  946.         extern short ns_bh[3];
  947.         struct sockaddr_ns *sms = &(so_mask.sns);
  948.         bzero((char *)sms, sizeof(*sms));
  949.         sms->sns_family = 0;
  950.         sms->sns_len = 6;
  951.         sms->sns_addr.x_net = *(union ns_net *)ns_bh;
  952.         rtm_addrs |= RTA_NETMASK;
  953.     }
  954.     su->sns.sns_addr = ns_addr(s);
  955.     return (!ns_nullhost(su->sns.sns_addr));
  956. do_osi:
  957.     su->siso.siso_addr = *iso_addr(s);
  958.     if (which == RTA_NETMASK || which == RTA_GENMASK) {
  959.         register char *cp = (char *)TSEL(&su->siso);
  960.         su->siso.siso_nlen = 0;
  961.         do {--cp ;} while ((cp > (char *)su) && (*cp == 0));
  962.         su->siso.siso_len = 1 + cp - (char *)su;
  963.     }
  964.     return (1);
  965. do_ccitt:
  966.     ccitt_addr(s, &su->sx25);
  967.     return (1);
  968. do_link:
  969.     link_addr(s, &su->sdl);
  970.     return (1);
  971. do_sa:
  972.     su->sa.sa_len = sizeof(*su);
  973.     sockaddr(s, &su->sa);
  974.     return (1);
  975. #endif
  976. }
  977.  
  978. short ns_nullh[] = {0,0,0};
  979. short ns_bh[] = {-1,-1,-1};
  980.  
  981. #if 0
  982. char *
  983. ns_print(sns)
  984.     struct sockaddr_ns *sns;
  985. {
  986.     struct ns_addr work;
  987.     union { union ns_net net_e; u_long long_e; } net;
  988.     u_short port;
  989.     static char mybuf[50], cport[10], chost[25];
  990.     char *host = "";
  991.     register char *p;
  992.     register u_char *q;
  993.  
  994.     work = sns->sns_addr;
  995.     port = ntohs(work.x_port);
  996.     work.x_port = 0;
  997.     net.net_e  = work.x_net;
  998.     if (ns_nullhost(work) && net.long_e == 0) {
  999.         if (!port)
  1000.             return ("*.*");
  1001.         (void) sprintf(mybuf, "*.%XH", port);
  1002.         return (mybuf);
  1003.     }
  1004.  
  1005.     if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0) 
  1006.         host = "any";
  1007.     else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0)
  1008.         host = "*";
  1009.     else {
  1010.         q = work.x_host.c_host;
  1011.         (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH",
  1012.             q[0], q[1], q[2], q[3], q[4], q[5]);
  1013.         for (p = chost; *p == '0' && p < chost + 12; p++)
  1014.             /* void */;
  1015.         host = p;
  1016.     }
  1017.     if (port)
  1018.         (void) sprintf(cport, ".%XH", htons(port));
  1019.     else
  1020.         *cport = 0;
  1021.  
  1022.     (void) sprintf(mybuf,"%XH.%s%s", ntohl(net.long_e), host, cport);
  1023.     return (mybuf);
  1024. }
  1025. #endif
  1026.  
  1027. void
  1028. monitor(void)
  1029. {
  1030. #if 0
  1031.     int n;
  1032.     char msg[2048];
  1033.  
  1034.     verbose = 1;
  1035.     for(;;) {
  1036.         n = read(s, msg, 2048);
  1037.         (void) printf("got message of size %d\n", n);
  1038.         print_rtmsg((struct rt_msghdr *)msg);
  1039.     }
  1040. #endif
  1041. }
  1042.  
  1043. #if 0
  1044. struct {
  1045.     struct    rt_msghdr m_rtm;
  1046.     char    m_space[512];
  1047. } m_rtmsg;
  1048.  
  1049. int
  1050. rtmsg(cmd, flags)
  1051.     int cmd, flags;
  1052. {
  1053.     static int seq;
  1054.     int rlen;
  1055.     register char *cp = m_rtmsg.m_space;
  1056.     register int l;
  1057.  
  1058. #define NEXTADDR(w, u) \
  1059.     if (rtm_addrs & (w)) {\
  1060.         l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
  1061.         if (verbose) sodump(&(u),"u");\
  1062.     }
  1063.  
  1064.     errno = 0;
  1065.     bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
  1066.     if (cmd == 'a')
  1067.         cmd = RTM_ADD;
  1068.     else if (cmd == 'c')
  1069.         cmd = RTM_CHANGE;
  1070.     else if (cmd == 'g')
  1071.         cmd = RTM_GET;
  1072.     else
  1073.         cmd = RTM_DELETE;
  1074. #define rtm m_rtmsg.m_rtm
  1075.     rtm.rtm_type = cmd;
  1076.     rtm.rtm_flags = flags;
  1077.     rtm.rtm_version = RTM_VERSION;
  1078.     rtm.rtm_seq = ++seq;
  1079.     rtm.rtm_addrs = rtm_addrs;
  1080.     rtm.rtm_rmx = rt_metrics;
  1081.     rtm.rtm_inits = rtm_inits;
  1082.  
  1083.     if (rtm_addrs & RTA_NETMASK)
  1084.         mask_addr();
  1085.     NEXTADDR(RTA_DST, so_dst);
  1086.     NEXTADDR(RTA_GATEWAY, so_gate);
  1087.     NEXTADDR(RTA_NETMASK, so_mask);
  1088.     NEXTADDR(RTA_GENMASK, so_genmask);
  1089.     NEXTADDR(RTA_IFP, so_ifp);
  1090.     NEXTADDR(RTA_IFA, so_ifa);
  1091.     rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
  1092.     if (verbose)
  1093.         print_rtmsg(&rtm, l);
  1094.     if (debugonly)
  1095.         return 0;
  1096.     if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
  1097.         perror("writing to routing socket");
  1098.         return (-1);
  1099.     }
  1100.     if (cmd == RTM_GET) {
  1101.         do {
  1102.             l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
  1103.         } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
  1104.         if (l < 0)
  1105.             (void) fprintf(stderr,
  1106.                 "route: read from routing socket: %s\n",
  1107.                 strerror(errno));
  1108.         else
  1109.             print_getmsg(&rtm, l);
  1110.     }
  1111. #undef rtm
  1112.     return (0);
  1113. }
  1114. #endif
  1115.  
  1116. #if 0
  1117. mask_addr() {
  1118.     register char *cp1, *cp2;
  1119.     int olen;
  1120.  
  1121.     if ((rtm_addrs & RTA_DST) == 0)
  1122.         return;
  1123.     switch(so_dst.sa.sa_family) {
  1124.     case AF_NS: case AF_INET: case 0:
  1125.         return;
  1126.     case AF_ISO:
  1127.         olen = MIN(so_dst.siso.siso_nlen, so_mask.sa.sa_len - 6);
  1128.     }
  1129.     cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst;
  1130.     cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst;
  1131.     while (cp2 > cp1)
  1132.         *--cp2 = 0;
  1133.     cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask;
  1134.     while (cp1 > so_dst.sa.sa_data)
  1135.         *--cp1 &= *--cp2;
  1136.     switch(so_dst.sa.sa_family) {
  1137.     case AF_ISO:
  1138.         so_dst.siso.siso_nlen = olen;
  1139.     }
  1140. }
  1141.  
  1142. char *msgtypes[] = {
  1143.     "",
  1144.     "RTM_ADD: Add Route",
  1145.     "RTM_DELETE: Delete Route",
  1146.     "RTM_CHANGE: Change Metrics or flags",
  1147.     "RTM_GET: Report Metrics",
  1148.     "RTM_LOSING: Kernel Suspects Partitioning",
  1149.     "RTM_REDIRECT: Told to use different route",
  1150.     "RTM_MISS: Lookup failed on this address",
  1151.     "RTM_LOCK: fix specified metrics",
  1152.     "RTM_OLDADD: caused by SIOCADDRT",
  1153.     "RTM_OLDDEL: caused by SIOCDELRT",
  1154.     0,
  1155. };
  1156.  
  1157. char metricnames[] =
  1158. "\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
  1159. char routeflags[] = 
  1160. "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\017PROTO2\020PROTO1";
  1161.  
  1162.  
  1163. void
  1164. print_rtmsg(rtm, msglen)
  1165.     register struct rt_msghdr *rtm;
  1166.     int msglen;
  1167. {
  1168.     if (verbose == 0)
  1169.         return;
  1170.     if (rtm->rtm_version != RTM_VERSION) {
  1171.         (void) printf("routing message version %d not understood\n",
  1172.             rtm->rtm_version);
  1173.         return;
  1174.     }
  1175.     (void) printf("%s\npid: %d, len %d, seq %d, errno %d, flags:",
  1176.         msgtypes[rtm->rtm_type], rtm->rtm_pid, rtm->rtm_msglen,
  1177.         rtm->rtm_seq, rtm->rtm_errno); 
  1178.     bprintf(stdout, rtm->rtm_flags, routeflags);
  1179.     pmsg_common(rtm);
  1180. }
  1181.  
  1182. void
  1183. print_getmsg(rtm, msglen)
  1184.     register struct rt_msghdr *rtm;
  1185.     int msglen;
  1186. {
  1187.     if (rtm->rtm_version != RTM_VERSION) {
  1188.         (void)printf("routing message version %d not understood\n",
  1189.             rtm->rtm_version);
  1190.         return;
  1191.     }
  1192.     if (rtm->rtm_msglen > msglen) {
  1193.         (void)printf("get length mismatch, in packet %d, returned %d\n",
  1194.             rtm->rtm_msglen, msglen);
  1195.     }
  1196.     (void) printf("RTM_GET: errno %d, flags:", rtm->rtm_errno); 
  1197.     bprintf(stdout, rtm->rtm_flags, routeflags);
  1198.     (void) printf("\nmetric values:\n  ");
  1199. #define metric(f, e)\
  1200.     printf("%s: %d%s", __STRING(f), rtm->rtm_rmx.__CONCAT(rmx_,f), e)
  1201.     metric(recvpipe, ", ");
  1202.     metric(sendpipe, ", ");
  1203.     metric(ssthresh, ", ");
  1204.     metric(rtt, "\n  ");
  1205.     metric(rttvar, ", ");
  1206.     metric(hopcount, ", ");
  1207.     metric(mtu, ", ");
  1208.     metric(expire, "\n");
  1209. #undef metric
  1210.     pmsg_common(rtm);
  1211. }
  1212.  
  1213. void
  1214. pmsg_common(rtm)
  1215.     register struct rt_msghdr *rtm;
  1216. {
  1217.     char *cp;
  1218.     register struct sockaddr *sa;
  1219.     int i;
  1220.  
  1221.     (void) printf("\nlocks: ");
  1222.     bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
  1223.     (void) printf(" inits: ");
  1224.     bprintf(stdout, rtm->rtm_inits, metricnames);
  1225.     (void) printf("\nsockaddrs: ");
  1226.     bprintf(stdout, rtm->rtm_addrs,
  1227.         "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR");
  1228.     (void) putchar('\n');
  1229.     cp = ((char *)(rtm + 1));
  1230.     if (rtm->rtm_addrs)
  1231.         for (i = 1; i; i <<= 1)
  1232.             if (i & rtm->rtm_addrs) {
  1233.                 sa = (struct sockaddr *)cp;
  1234.                 (void) printf(" %s", routename(sa));
  1235.                 ADVANCE(cp, sa);
  1236.             }
  1237.     (void) putchar('\n');
  1238.     (void) fflush(stdout);
  1239. }
  1240.  
  1241. void
  1242. bprintf(fp, b, s)
  1243.     register FILE *fp;
  1244.     register int b;
  1245.     register u_char *s;
  1246. {
  1247.     register int i;
  1248.     int gotsome = 0;
  1249.  
  1250.     if (b == 0)
  1251.         return;
  1252.     while (i = *s++) {
  1253.         if (b & (1 << (i-1))) {
  1254.             if (gotsome == 0)
  1255.                 i = '<';
  1256.             else
  1257.                 i = ',';
  1258.             (void) putc(i, fp);
  1259.             gotsome = 1;
  1260.             for (; (i = *s) > 32; s++)
  1261.                 (void) putc(i, fp);
  1262.         } else
  1263.             while (*s > 32)
  1264.                 s++;
  1265.     }
  1266.     if (gotsome)
  1267.         (void) putc('>', fp);
  1268. }
  1269. #endif
  1270.  
  1271. int
  1272. keyword(cp)
  1273.     char *cp;
  1274. {
  1275.     register struct keytab *kt = keywords;
  1276.  
  1277.     while (kt->kt_cp && strcmp(kt->kt_cp, cp))
  1278.         kt++;
  1279.     return kt->kt_i;
  1280. }
  1281. #if 0
  1282. void
  1283. sodump(su, which)
  1284.     register sup su;
  1285.     char *which;
  1286. {
  1287.     switch (su->sa.sa_family) {
  1288.     case AF_LINK:
  1289.         (void) printf("%s: link %s; ",
  1290.             which, link_ntoa(&su->sdl));
  1291.         break;
  1292.     case AF_ISO:
  1293.         (void) printf("%s: iso %s; ",
  1294.             which, iso_ntoa(&su->siso.siso_addr));
  1295.         break;
  1296.     case AF_INET:
  1297.         (void) printf("%s: inet %s; ",
  1298.             which, inet_ntoa(su->sin.sin_addr));
  1299.         break;
  1300.     case AF_NS:
  1301.         (void) printf("%s: xns %s; ",
  1302.             which, ns_ntoa(su->sns.sns_addr));
  1303.         break;
  1304.     }
  1305.     (void) fflush(stdout);
  1306. }
  1307. /* States*/
  1308. #define VIRGIN    0
  1309. #define GOTONE    1
  1310. #define GOTTWO    2
  1311. /* Inputs */
  1312. #define    DIGIT    (4*0)
  1313. #define    END    (4*1)
  1314. #define DELIM    (4*2)
  1315.  
  1316. void
  1317. sockaddr(addr, sa)
  1318. register char *addr;
  1319. register struct sockaddr *sa;
  1320. {
  1321.     register char *cp = (char *)sa;
  1322.     int size = sa->sa_len;
  1323.     char *cplim = cp + size;
  1324.     register int byte = 0, state = VIRGIN, new;
  1325.  
  1326.     bzero(cp, size);
  1327.     do {
  1328.         if ((*addr >= '0') && (*addr <= '9')) {
  1329.             new = *addr - '0';
  1330.         } else if ((*addr >= 'a') && (*addr <= 'f')) {
  1331.             new = *addr - 'a' + 10;
  1332.         } else if ((*addr >= 'A') && (*addr <= 'F')) {
  1333.             new = *addr - 'A' + 10;
  1334.         } else if (*addr == 0) 
  1335.             state |= END;
  1336.         else
  1337.             state |= DELIM;
  1338.         addr++;
  1339.         switch (state /* | INPUT */) {
  1340.         case GOTTWO | DIGIT:
  1341.             *cp++ = byte; /*FALLTHROUGH*/
  1342.         case VIRGIN | DIGIT:
  1343.             state = GOTONE; byte = new; continue;
  1344.         case GOTONE | DIGIT:
  1345.             state = GOTTWO; byte = new + (byte << 4); continue;
  1346.         default: /* | DELIM */
  1347.             state = VIRGIN; *cp++ = byte; byte = 0; continue;
  1348.         case GOTONE | END:
  1349.         case GOTTWO | END:
  1350.             *cp++ = byte; /* FALLTHROUGH */
  1351.         case VIRGIN | END:
  1352.             break;
  1353.         }
  1354.         break;
  1355.     } while (cp < cplim); 
  1356.     sa->sa_len = cp - (char *)sa;
  1357. }
  1358. #endif
  1359.