home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / E-zine / Magazines / crh / freebsd / rootkit / ifconfig / ifconfig.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-27  |  28.8 KB  |  1,247 lines

  1. /*
  2.  * Copyright (c) 1983, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static const char copyright[] =
  36. "@(#) Copyright (c) 1983, 1993\n\
  37.     The Regents of the University of California.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. /*
  42. static char sccsid[] = "@(#)ifconfig.c    8.2 (Berkeley) 2/16/94";
  43. */
  44. static const char rcsid[] =
  45.     "$Id: ifconfig.c,v 1.19.2.1 1997/06/30 11:02:00 peter Exp $";
  46. #endif /* not lint */
  47.  
  48. #include <sys/param.h>
  49. #include <sys/ioctl.h>
  50. #include <sys/socket.h>
  51. #include <sys/sysctl.h>
  52. #include <sys/time.h>
  53.  
  54. #include <net/if.h>
  55. #include <net/if_dl.h>
  56. #include <net/if_types.h>
  57. #include <net/route.h>
  58.  
  59. /* IP */
  60. #include <netinet/in.h>
  61. #include <netinet/in_var.h>
  62. #include <arpa/inet.h>
  63. #include <netdb.h>
  64.  
  65. /* IPX */
  66. #define    IPXIP
  67. #define IPTUNNEL
  68. #include <netipx/ipx.h>
  69. #include <netipx/ipx_if.h>
  70.  
  71. /* Appletalk */
  72. #include <netatalk/at.h>
  73.  
  74. /* XNS */
  75. #ifdef NS
  76. #define    NSIP
  77. #include <netns/ns.h>
  78. #include <netns/ns_if.h>
  79. #endif
  80.  
  81. /* OSI */
  82. #ifdef ISO
  83. #define EON
  84. #include <netiso/iso.h>
  85. #include <netiso/iso_var.h>
  86. #endif
  87.  
  88. #include <ctype.h>
  89. #include <err.h>
  90. #include <errno.h>
  91. #include <fcntl.h>
  92. #include <stdio.h>
  93. #include <stdlib.h>
  94. #include <string.h>
  95. #include <unistd.h>
  96.  
  97. #include "ifconfig.h"
  98.  
  99. struct    ifreq        ifr, ridreq;
  100. struct    ifaliasreq    addreq;
  101. #ifdef ISO
  102. struct    iso_ifreq    iso_ridreq;
  103. struct    iso_aliasreq    iso_addreq;
  104. #endif
  105. struct    sockaddr_in    netmask;
  106. struct    netrange    at_nr;        /* AppleTalk net range */
  107.  
  108. char    name[32];
  109. int    flags;
  110. int    metric;
  111. int    mtu;
  112. #ifdef ISO
  113. int    nsellength = 1;
  114. #endif
  115. int    setaddr;
  116. int    setipdst;
  117. int    doalias;
  118. int    clearaddr;
  119. int    newaddr = 1;
  120. int    allmedia;
  121.  
  122. struct    afswtch;
  123.  
  124. void    Perror __P((const char *cmd));
  125. void    checkatrange __P((struct sockaddr_at *));
  126. int    ifconfig __P((int argc, char *const *argv, const struct afswtch *afp));
  127. void    notealias __P((const char *, int, int, const struct afswtch *afp));
  128. void    printb __P((const char *s, unsigned value, const char *bits));
  129. void    rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
  130. void    status __P((const struct afswtch *afp, int addrcount,
  131.             struct sockaddr_dl *sdl, struct if_msghdr *ifm,
  132.             struct ifa_msghdr *ifam));
  133. void    usage __P((void));
  134.  
  135. typedef    void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp));
  136. c_func    setatphase, setatrange;
  137. c_func    setifaddr, setifbroadaddr, setifdstaddr, setifnetmask;
  138. c_func    setifipdst;
  139. c_func    setifflags, setifmetric, setifmtu;
  140.  
  141. #ifdef ISO
  142. c_func    setsnpaoffset, setnsellength;
  143. #endif
  144.  
  145. #define    NEXTARG        0xffffff
  146.  
  147. const
  148. struct    cmd {
  149.     const    char *c_name;
  150.     int    c_parameter;        /* NEXTARG means next argv */
  151.     void    (*c_func) __P((const char *, int, int, const struct afswtch *afp));
  152. } cmds[] = {
  153.     { "up",        IFF_UP,        setifflags } ,
  154.     { "down",    -IFF_UP,    setifflags },
  155.     { "arp",    -IFF_NOARP,    setifflags },
  156.     { "-arp",    IFF_NOARP,    setifflags },
  157.     { "debug",    IFF_DEBUG,    setifflags },
  158.     { "-debug",    -IFF_DEBUG,    setifflags },
  159.     { "alias",    IFF_UP,        notealias },
  160.     { "-alias",    -IFF_UP,    notealias },
  161.     { "delete",    -IFF_UP,    notealias },
  162. #ifdef notdef
  163. #define    EN_SWABIPS    0x1000
  164.     { "swabips",    EN_SWABIPS,    setifflags },
  165.     { "-swabips",    -EN_SWABIPS,    setifflags },
  166. #endif
  167.     { "netmask",    NEXTARG,    setifnetmask },
  168.     { "range",    NEXTARG,    setatrange },
  169.     { "phase",    NEXTARG,    setatphase },
  170.     { "metric",    NEXTARG,    setifmetric },
  171.     { "broadcast",    NEXTARG,    setifbroadaddr },
  172.     { "ipdst",    NEXTARG,    setifipdst },
  173. #ifdef ISO
  174.     { "snpaoffset",    NEXTARG,    setsnpaoffset },
  175.     { "nsellength",    NEXTARG,    setnsellength },
  176. #endif
  177.     { "link0",    IFF_LINK0,    setifflags },
  178.     { "-link0",    -IFF_LINK0,    setifflags },
  179.     { "link1",    IFF_LINK1,    setifflags },
  180.     { "-link1",    -IFF_LINK1,    setifflags },
  181.     { "link2",    IFF_LINK2,    setifflags },
  182.     { "-link2",    -IFF_LINK2,    setifflags },
  183. #ifdef USE_IF_MEDIA
  184.     { "media",    NEXTARG,    setmedia },
  185.     { "mediaopt",    NEXTARG,    setmediaopt },
  186.     { "-mediaopt",    NEXTARG,    unsetmediaopt },
  187. #endif
  188.     { "normal",    -IFF_LINK0,    setifflags },
  189.     { "compress",    IFF_LINK0,    setifflags },
  190.     { "noicmp",    IFF_LINK1,    setifflags },
  191.     { "mtu",    NEXTARG,    setifmtu },
  192.     { 0,        0,        setifaddr },
  193.     { 0,        0,        setifdstaddr },
  194. };
  195.  
  196. /*
  197.  * XNS support liberally adapted from code written at the University of
  198.  * Maryland principally by James O'Toole and Chris Torek.
  199.  */
  200. typedef    void af_status __P((int, struct rt_addrinfo *));
  201. typedef    void af_getaddr __P((const char *, int));
  202.  
  203. af_status    in_status, ipx_status, at_status, ether_status;
  204. af_getaddr    in_getaddr, ipx_getaddr, at_getaddr;
  205.  
  206. #ifdef NS
  207. af_status    xns_status;
  208. af_getaddr    xns_getaddr;
  209. #endif
  210. #ifdef ISO
  211. af_status    iso_status;
  212. af_getaddr    iso_getaddr;
  213. #endif
  214.  
  215. /* Known address families */
  216. const
  217. struct    afswtch {
  218.     const char *af_name;
  219.     short af_af;
  220.     af_status *af_status;
  221.     af_getaddr *af_getaddr;
  222.     int af_difaddr;
  223.     int af_aifaddr;
  224.     caddr_t af_ridreq;
  225.     caddr_t af_addreq;
  226. } afs[] = {
  227. #define C(x) ((caddr_t) &x)
  228.     { "inet", AF_INET, in_status, in_getaddr,
  229.          SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
  230.     { "ipx", AF_IPX, ipx_status, ipx_getaddr,
  231.          SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
  232.     { "atalk", AF_APPLETALK, at_status, at_getaddr,
  233.          SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) },
  234. #ifdef NS
  235.     { "ns", AF_NS, xns_status, xns_getaddr,
  236.          SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
  237. #endif
  238. #ifdef ISO
  239.     { "iso", AF_ISO, iso_status, iso_getaddr,
  240.          SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) },
  241. #endif
  242.     { "ether", AF_INET, ether_status, NULL },    /* XXX not real!! */
  243. #if 0    /* XXX conflicts with the media command */
  244. #ifdef USE_IF_MEDIA
  245.     { "media", AF_INET, media_status, NULL },    /* XXX not real!! */
  246. #endif
  247. #endif
  248.     { 0,    0,        0,        0 }
  249. };
  250.  
  251. /*
  252.  * Expand the compacted form of addresses as returned via the
  253.  * configuration read via sysctl().
  254.  */
  255.  
  256. #define ROUNDUP(a) \
  257.     ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  258. #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
  259.  
  260. void
  261. rt_xaddrs(cp, cplim, rtinfo)
  262.     caddr_t cp, cplim;
  263.     struct rt_addrinfo *rtinfo;
  264. {
  265.     struct sockaddr *sa;
  266.     int i;
  267.  
  268.     memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
  269.     for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
  270.         if ((rtinfo->rti_addrs & (1 << i)) == 0)
  271.             continue;
  272.         rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
  273.         ADVANCE(cp, sa);
  274.     }
  275. }
  276.  
  277.  
  278. void
  279. usage()
  280. {
  281.     fputs("usage: ifconfig -a [ -m ] [ -d ] [ -u ] [ af ]\n", stderr);
  282.     fputs("       ifconfig -l [ -d ] [ -u ]\n", stderr);
  283.     fputs("       ifconfig [ -m ] interface\n", stderr);
  284.     fputs("        [ af [ address [ dest_addr ] ] [ netmask mask ] [ broadcast addr ]\n", stderr);
  285.     fputs("             [ alias ] [ delete ] ]\n", stderr);
  286.     fputs("        [ up ] [ down ]\n", stderr);
  287.     fputs("        [ metric n ]\n", stderr);
  288.     fputs("        [ mtu n ]\n", stderr);
  289.     fputs("        [ arp | -arp ]\n", stderr);
  290.     fputs("        [ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n", stderr);
  291. #ifdef USE_IF_MEDIA
  292.     fputs("        [ media mtype ]\n", stderr);
  293.     fputs("        [ mediaopt mopts ]\n", stderr);
  294.     fputs("        [ -mediaopt mopts ]\n", stderr);
  295. #endif
  296.     exit(1);
  297. }
  298.  
  299. int
  300. main(argc, argv)
  301.     int argc;
  302.     char *const *argv;
  303. {
  304.     int c;
  305.     int all, namesonly, downonly, uponly;
  306.     int foundit = 0, need_nl = 0;
  307.     const struct afswtch *afp = 0;
  308.     int addrcount;
  309.     struct    if_msghdr *ifm, *nextifm;
  310.     struct    ifa_msghdr *ifam;
  311.     struct    sockaddr_dl *sdl;
  312.     char    *buf, *lim, *next;
  313.  
  314.  
  315.     size_t needed;
  316.     int mib[6];
  317.  
  318.     /* Parse leading line options */
  319.     all = allmedia = downonly = uponly = namesonly = 0;
  320.     while ((c = getopt(argc, argv, "adlmu")) != -1) {
  321.         switch (c) {
  322.         case 'a':    /* scan all interfaces */
  323.             all++;
  324.             break;
  325.         case 'l':    /* scan interface names only */
  326.             namesonly++;
  327.             break;
  328.         case 'd':    /* restrict scan to "down" interfaces */
  329.             downonly++;
  330.             break;
  331.         case 'u':    /* restrict scan to "down" interfaces */
  332.             uponly++;
  333.             break;
  334.         case 'm':    /* show media choices in status */
  335. #ifdef USE_IF_MEDIA
  336.             allmedia++;
  337. #else
  338.             fputs("WARNING: if_media not compiled in!\n", stderr);
  339.             usage();
  340. #endif
  341.             break;
  342.         default:
  343.             usage();
  344.             break;
  345.         }
  346.     }
  347.     argc -= optind;
  348.     argv += optind;
  349.  
  350.     /* -l cannot be used with -a or -m */
  351.     if (namesonly && (all || allmedia))
  352.         usage();
  353.  
  354.     /* nonsense.. */
  355.     if (uponly && downonly)
  356.         usage();
  357.  
  358.     /* -a and -l allow an address family arg to limit the output */
  359.     if (all || namesonly) {
  360.         if (argc > 1)
  361.             usage();
  362.  
  363.         if (argc == 1) {
  364.             for (afp = afs; afp->af_name; afp++)
  365.                 if (strcmp(afp->af_name, *argv) == 0) {
  366.                     argc--, argv++;
  367.                     break;
  368.                 }
  369.             if (afp->af_name == NULL)
  370.                 usage();
  371.             /* leave with afp non-zero */
  372.         }
  373.     } else {
  374.         /* not listsing, need an argument */
  375.         if (argc < 1)
  376.             usage();
  377.  
  378.         strncpy(name, *argv, sizeof(name));
  379.         argc--, argv++;
  380.     }
  381.  
  382.     /* Check for address family */
  383.     if (argc > 0) {
  384.         for (afp = afs; afp->af_name; afp++)
  385.             if (strcmp(afp->af_name, *argv) == 0) {
  386.                 argc--, argv++;
  387.                 break;
  388.             }
  389.         if (afp->af_name == NULL)
  390.             afp = NULL;    /* not a family, NULL */
  391.     }
  392.  
  393.     mib[0] = CTL_NET;
  394.     mib[1] = PF_ROUTE;
  395.     mib[2] = 0;
  396.     mib[3] = 0;    /* address family */
  397.     mib[4] = NET_RT_IFLIST;
  398.     mib[5] = 0;
  399.  
  400.     /* if particular family specified, only ask about it */
  401.     if (afp)
  402.         mib[3] = afp->af_af;
  403.  
  404.     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
  405.         errx(1, "iflist-sysctl-estimate");
  406.     if ((buf = malloc(needed)) == NULL)
  407.         errx(1, "malloc");
  408.     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
  409.         errx(1, "actual retrieval of interface table");
  410.     lim = buf + needed;
  411.  
  412.     next = buf;
  413.     while (next < lim) {
  414.  
  415.         ifm = (struct if_msghdr *)next;
  416.         
  417.         if (ifm->ifm_type == RTM_IFINFO) {
  418.             sdl = (struct sockaddr_dl *)(ifm + 1);
  419.             flags = ifm->ifm_flags;
  420.         } else {
  421.             fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n");
  422.             fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO,
  423.                 ifm->ifm_type);
  424.             fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
  425.             fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next,
  426.                 lim);
  427.             exit (1);
  428.         }
  429.  
  430.         next += ifm->ifm_msglen;
  431.         ifam = NULL;
  432.         addrcount = 0;
  433.         while (next < lim) {
  434.  
  435.             nextifm = (struct if_msghdr *)next;
  436.  
  437.             if (nextifm->ifm_type != RTM_NEWADDR)
  438.                 break;
  439.  
  440.             if (ifam == NULL)
  441.                 ifam = (struct ifa_msghdr *)nextifm;
  442.  
  443.             addrcount++;
  444.             next += nextifm->ifm_msglen;
  445.         }
  446.  
  447.         if (all || namesonly) {
  448.             if (uponly)
  449.                 if ((flags & IFF_UP) == 0)
  450.                     continue; /* not up */
  451.             if (downonly)
  452.                 if (flags & IFF_UP)
  453.                     continue; /* not down */
  454.             strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
  455.             name[sdl->sdl_nlen] = '\0';
  456.             if (namesonly) {
  457.                 if (need_nl)
  458.                     putchar(' ');
  459.                 fputs(name, stdout);
  460.                 need_nl++;
  461.                 continue;
  462.             }
  463.         } else {
  464.             if (strlen(name) != sdl->sdl_nlen)
  465.                 continue; /* not same len */
  466.             if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
  467.                 continue; /* not same name */
  468.         }
  469.  
  470.         if (argc > 0)
  471.             ifconfig(argc, argv, afp);
  472.         else
  473.             status(afp, addrcount, sdl, ifm, ifam);
  474.  
  475.         if (all == 0 && namesonly == 0) {
  476.             foundit++; /* flag it as 'done' */
  477.             break;
  478.         }
  479.     }
  480.     free(buf);
  481.  
  482.     if (namesonly && need_nl > 0)
  483.         putchar('\n');
  484.  
  485.     if (all == 0 && namesonly == 0 && foundit == 0)
  486.         errx(1, "interface %s does not exist", name);
  487.  
  488.  
  489.     exit (0);
  490. }
  491.  
  492.  
  493. int
  494. ifconfig(argc, argv, afp)
  495.     int argc;
  496.     char *const *argv;
  497.     const struct afswtch *afp;
  498. {
  499.     int s;
  500.  
  501.     if (afp == NULL)
  502.         afp = &afs[0];
  503.     ifr.ifr_addr.sa_family = afp->af_af;
  504.     strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
  505.  
  506.     if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
  507.         perror("ifconfig: socket");
  508.         exit(1);
  509.     }
  510.  
  511.     while (argc > 0) {
  512.         register const struct cmd *p;
  513.  
  514.         for (p = cmds; p->c_name; p++)
  515.             if (strcmp(*argv, p->c_name) == 0)
  516.                 break;
  517.         if (p->c_name == 0 && setaddr)
  518.             p++;    /* got src, do dst */
  519.         if (p->c_func) {
  520.             if (p->c_parameter == NEXTARG) {
  521.                 if (argv[1] == NULL)
  522.                     errx(1, "'%s' requires argument",
  523.                         p->c_name);
  524.                 (*p->c_func)(argv[1], 0, s, afp);
  525.                 argc--, argv++;
  526.             } else
  527.                 (*p->c_func)(*argv, p->c_parameter, s, afp);
  528.         }
  529.         argc--, argv++;
  530.     }
  531. #ifdef ISO
  532.     if (af == AF_ISO)
  533.         adjust_nsellength();
  534. #endif
  535.     if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) {
  536.         struct ipxip_req rq;
  537.         int size = sizeof(rq);
  538.  
  539.         rq.rq_ipx = addreq.ifra_addr;
  540.         rq.rq_ip = addreq.ifra_dstaddr;
  541.  
  542.         if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0)
  543.             Perror("Encapsulation Routing");
  544.     }
  545.     if (ifr.ifr_addr.sa_family == AF_APPLETALK)
  546.         checkatrange((struct sockaddr_at *) &addreq.ifra_addr);
  547. #ifdef NS
  548.     if (setipdst && ifr.ifr_addr.sa_family == AF_NS) {
  549.         struct nsip_req rq;
  550.         int size = sizeof(rq);
  551.  
  552.         rq.rq_ns = addreq.ifra_addr;
  553.         rq.rq_ip = addreq.ifra_dstaddr;
  554.  
  555.         if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
  556.             Perror("Encapsulation Routing");
  557.     }
  558. #endif
  559.     if (clearaddr) {
  560.         if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
  561.             warnx("interface %s cannot change %s addresses!",
  562.                   name, afp->af_name);
  563.             clearaddr = NULL;
  564.         }
  565.     }
  566.     if (clearaddr) {
  567.         int ret;
  568.         strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
  569.         if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) {
  570.             if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
  571.                 /* means no previous address for interface */
  572.             } else
  573.                 Perror("ioctl (SIOCDIFADDR)");
  574.         }
  575.     }
  576.     if (newaddr) {
  577.         if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
  578.             warnx("interface %s cannot change %s addresses!",
  579.                   name, afp->af_name);
  580.             newaddr = NULL;
  581.         }
  582.     }
  583.     if (newaddr) {
  584.         strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
  585.         if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
  586.             Perror("ioctl (SIOCAIFADDR)");
  587.     }
  588.     close(s);
  589.     return(0);
  590. }
  591. #define RIDADDR 0
  592. #define ADDR    1
  593. #define MASK    2
  594. #define DSTADDR    3
  595.  
  596. /*ARGSUSED*/
  597. void
  598. setifaddr(addr, param, s, afp)
  599.     const char *addr;
  600.     int param;
  601.     int s;
  602.     const struct afswtch *afp;
  603. {
  604.     /*
  605.      * Delay the ioctl to set the interface addr until flags are all set.
  606.      * The address interpretation may depend on the flags,
  607.      * and the flags may change when the address is set.
  608.      */
  609.     setaddr++;
  610.     if (doalias == 0)
  611.         clearaddr = 1;
  612.     (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
  613. }
  614.  
  615. void
  616. setifnetmask(addr, dummy, s, afp)
  617.     const char *addr;
  618.     int dummy __unused;
  619.     int s;
  620.     const struct afswtch *afp;
  621. {
  622.     (*afp->af_getaddr)(addr, MASK);
  623. }
  624.  
  625. void
  626. setifbroadaddr(addr, dummy, s, afp)
  627.     const char *addr;
  628.     int dummy __unused;
  629.     int s;
  630.     const struct afswtch *afp;
  631. {
  632.     (*afp->af_getaddr)(addr, DSTADDR);
  633. }
  634.  
  635. void
  636. setifipdst(addr, dummy, s, afp)
  637.     const char *addr;
  638.     int dummy __unused;
  639.     int s;
  640.     const struct afswtch *afp;
  641. {
  642.     in_getaddr(addr, DSTADDR);
  643.     setipdst++;
  644.     clearaddr = 0;
  645.     newaddr = 0;
  646. }
  647. #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
  648.  
  649. void
  650. notealias(addr, param, s, afp)
  651.     const char *addr;
  652.     int param;
  653.     int s;
  654.     const struct afswtch *afp;
  655. {
  656.     if (setaddr && doalias == 0 && param < 0)
  657.         bcopy((caddr_t)rqtosa(af_addreq),
  658.               (caddr_t)rqtosa(af_ridreq),
  659.               rqtosa(af_addreq)->sa_len);
  660.     doalias = param;
  661.     if (param < 0) {
  662.         clearaddr = 1;
  663.         newaddr = 0;
  664.     } else
  665.         clearaddr = 0;
  666. }
  667.  
  668. /*ARGSUSED*/
  669. void
  670. setifdstaddr(addr, param, s, afp)
  671.     const char *addr;
  672.     int param __unused;
  673.     int s;
  674.     const struct afswtch *afp;
  675. {
  676.     (*afp->af_getaddr)(addr, DSTADDR);
  677. }
  678.  
  679. void
  680. setifflags(vname, value, s, afp)
  681.     const char *vname;
  682.     int value;
  683.     int s;
  684.     const struct afswtch *afp;
  685. {
  686.      if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
  687.          Perror("ioctl (SIOCGIFFLAGS)");
  688.          exit(1);
  689.      }
  690.     strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
  691.      flags = ifr.ifr_flags;
  692.  
  693.     if (value < 0) {
  694.         value = -value;
  695.         flags &= ~value;
  696.     } else
  697.         flags |= value;
  698.     ifr.ifr_flags = flags;
  699.     if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
  700.         Perror(vname);
  701. }
  702.  
  703. void
  704. setifmetric(val, dummy, s, afp)
  705.     const char *val;
  706.     int dummy __unused;
  707.     int s;
  708.     const struct afswtch *afp;
  709. {
  710.     strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
  711.     ifr.ifr_metric = atoi(val);
  712.     if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
  713.         perror("ioctl (set metric)");
  714. }
  715.  
  716. void
  717. setifmtu(val, dummy, s, afp)
  718.     const char *val;
  719.     int dummy __unused;
  720.     int s;
  721.     const struct afswtch *afp;
  722. {
  723.     strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
  724.     ifr.ifr_mtu = atoi(val);
  725.     if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
  726.         perror("ioctl (set mtu)");
  727. }
  728.  
  729. #ifdef ISO
  730. void
  731. setsnpaoffset(val, dummy)
  732.     char *val;
  733.     int dummy __unused;
  734. {
  735.     iso_addreq.ifra_snpaoffset = atoi(val);
  736. }
  737. #endif
  738.  
  739. #define    IFFBITS \
  740. "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6b6\7RUNNING" \
  741. "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
  742. "\20MULTICAST"
  743.  
  744. /*
  745.  * Print the status of the interface.  If an address family was
  746.  * specified, show it and it only; otherwise, show them all.
  747.  */
  748. void
  749. status(afp, addrcount, sdl, ifm, ifam)
  750.     const struct afswtch *afp;
  751.     int addrcount;
  752.     struct    sockaddr_dl *sdl;
  753.     struct if_msghdr *ifm;
  754.     struct ifa_msghdr *ifam;
  755. {
  756.     const struct afswtch *p = NULL;
  757.     struct    rt_addrinfo info;
  758.     int allfamilies, s;
  759.  
  760.     if (afp == NULL) {
  761.         allfamilies = 1;
  762.         afp = &afs[0];
  763.     } else
  764.         allfamilies = 0;
  765.  
  766.     ifr.ifr_addr.sa_family = afp->af_af;
  767.     strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
  768.  
  769.     if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
  770.         perror("ifconfig: socket");
  771.         exit(1);
  772.     }
  773.  
  774.     /*
  775.      * XXX is it we are doing a SIOCGIFMETRIC etc for one family.
  776.      * is it possible that the metric and mtu can be different for
  777.      * each family?  If so, we have a format problem, because the
  778.      * metric and mtu is printed on the global the flags line.
  779.      */
  780.     if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
  781.         perror("ioctl (SIOCGIFMETRIC)");
  782.     else
  783.         metric = ifr.ifr_metric;
  784.  
  785.     if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
  786.         perror("ioctl (SIOCGIFMTU)");
  787.     else
  788.         mtu = ifr.ifr_mtu;
  789.  
  790.     printf("%s: ", name);
  791.     printb("flags", (flags & IFF_PROMISC) ? (flags ^ IFF_PROMISC) : flags, IFFBITS);
  792.     if (metric)
  793.         printf(" metric %d", metric);
  794.     if (mtu)
  795.         printf(" mtu %d", mtu);
  796.     putchar('\n');
  797.  
  798.     while (addrcount > 0) {
  799.         
  800.         info.rti_addrs = ifam->ifam_addrs;
  801.  
  802.         /* Expand the compacted addresses */
  803.         rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
  804.               &info);
  805.  
  806.         if (!allfamilies) {
  807.             if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family &&
  808. #ifdef USE_IF_MEDIA
  809.                 afp->af_status != media_status &&
  810. #endif
  811.                 afp->af_status != ether_status) {
  812.                 p = afp;
  813.                 (*p->af_status)(s, &info);
  814.             }
  815.         } else for (p = afs; p->af_name; p++) {
  816.             if (p->af_af == info.rti_info[RTAX_IFA]->sa_family &&
  817. #ifdef USE_IF_MEDIA
  818.                 p->af_status != media_status &&
  819. #endif
  820.                 p->af_status != ether_status) 
  821.                 (*p->af_status)(s, &info);
  822.         }
  823.         addrcount--;
  824.         ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
  825.     }
  826.     if (allfamilies || afp->af_status == ether_status)
  827.         ether_status(s, (struct rt_addrinfo *)sdl);
  828. #ifdef USE_IF_MEDIA
  829.     if (allfamilies || afp->af_status == media_status)
  830.         media_status(s, NULL);
  831. #endif
  832.     if (!allfamilies && !p && afp->af_status != media_status &&
  833.         afp->af_status != ether_status)
  834.         warnx("%s has no %s interface address!", name, afp->af_name);
  835.  
  836.     close(s);
  837.     return;
  838. }
  839.  
  840. void
  841. in_status(s, info)
  842.     int s __unused;
  843.     struct rt_addrinfo * info;
  844. {
  845.     struct sockaddr_in *sin, null_sin;
  846.     
  847.     memset(&null_sin, 0, sizeof(null_sin));
  848.  
  849.     sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA];
  850.     printf("\tinet %s ", inet_ntoa(sin->sin_addr));
  851.  
  852.     if (flags & IFF_POINTOPOINT) {
  853.         /* note RTAX_BRD overlap with IFF_BROADCAST */
  854.         sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD];
  855.         if (!sin)
  856.             sin = &null_sin;
  857.         printf("--> %s ", inet_ntoa(sin->sin_addr));
  858.     }
  859.  
  860.     sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK];
  861.     if (!sin)
  862.         sin = &null_sin;
  863.     printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
  864.  
  865.     if (flags & IFF_BROADCAST) {
  866.         /* note RTAX_BRD overlap with IFF_POINTOPOINT */
  867.         sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD];
  868.         if (sin && sin->sin_addr.s_addr != 0)
  869.             printf("broadcast %s", inet_ntoa(sin->sin_addr));
  870.     }
  871.     putchar('\n');
  872. }
  873.  
  874. void
  875. ipx_status(s, info)
  876.     int s __unused;
  877.     struct rt_addrinfo * info;
  878. {
  879.     struct sockaddr_ipx *sipx, null_sipx;
  880.  
  881.     memset(&null_sipx, 0, sizeof(null_sipx));
  882.  
  883.     sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA];
  884.     printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr));
  885.  
  886.     if (flags & IFF_POINTOPOINT) {
  887.         sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD];
  888.         if (!sipx)
  889.             sipx = &null_sipx;
  890.         printf("--> %s ", ipx_ntoa(sipx->sipx_addr));
  891.     }
  892.     putchar('\n');
  893. }
  894.  
  895. void
  896. at_status(s, info)
  897.     int s __unused;
  898.     struct rt_addrinfo * info;
  899. {
  900.     struct sockaddr_at *sat, null_sat;
  901.     struct netrange *nr;
  902.  
  903.     memset(&null_sat, 0, sizeof(null_sat));
  904.  
  905.     sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA];
  906.     nr = &sat->sat_range.r_netrange;
  907.     printf("\tatalk %d.%d range %d-%d phase %d",
  908.         ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
  909.         ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
  910.     if (flags & IFF_POINTOPOINT) {
  911.         /* note RTAX_BRD overlap with IFF_BROADCAST */
  912.         sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD];
  913.         if (!sat)
  914.             sat = &null_sat;
  915.         printf("--> %d.%d",
  916.             ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
  917.     }
  918.     if (flags & IFF_BROADCAST) {
  919.         /* note RTAX_BRD overlap with IFF_POINTOPOINT */
  920.         sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD];
  921.         if (sat)
  922.             printf(" broadcast %d.%d",
  923.                 ntohs(sat->sat_addr.s_net),
  924.                 sat->sat_addr.s_node);
  925.     }
  926.  
  927.     putchar('\n');
  928. }
  929.  
  930. #ifdef NS
  931. void
  932. xns_status(s, info)
  933.     int s __unused;
  934.     struct rt_addrinfo * info;
  935. {
  936.     struct sockaddr_ns *sns, null_sns;
  937.  
  938.     memset(&null_sns, 0, sizeof(null_sns));
  939.  
  940.     sns = (struct sockaddr_ns *)info->rti_info[RTAX_IFA];
  941.     printf("\tns %s ", ns_ntoa(sns->sns_addr));
  942.  
  943.     if (flags & IFF_POINTOPOINT) {
  944.         sns = (struct sockaddr_ns *)info->rti_info[RTAX_BRD];
  945.         if (!sns)
  946.             sns = &null_sns;
  947.         printf("--> %s ", ns_ntoa(sns->sns_addr));
  948.     }
  949.  
  950.     putchar('\n');
  951.     close(s);
  952. }
  953. #endif
  954.  
  955. #ifdef ISO
  956. void
  957. iso_status(s, info)
  958.     int s __unused;
  959.     struct rt_addrinfo * info;
  960. {
  961.     struct sockaddr_iso *siso, null_siso;
  962.  
  963.     memset(&null_siso, 0, sizeof(null_siso));
  964.  
  965.     siso = (struct sockaddr_iso *)info->rti_info[RTAX_IFA];
  966.     printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
  967.  
  968.     if (flags & IFF_POINTOPOINT) {
  969.         siso = (struct sockaddr_iso *)info->rti_info[RTAX_BRD];
  970.         if (!siso)
  971.             siso = &null_siso;
  972.         printf("--> %s ", iso_ntoa(&siso->siso_addr));
  973.     }
  974.  
  975.     siso = (struct sockaddr_iso *)info->rti_info[RTAX_NETMASK];
  976.     if (siso)
  977.         printf(" netmask %s ", iso_ntoa(&siso->siso_addr));
  978.  
  979.     putchar('\n');
  980. }
  981. #endif
  982.  
  983. void
  984. ether_status(s, info)
  985.     int s __unused;
  986.     struct rt_addrinfo *info;
  987. {
  988.     char *cp;
  989.     int n;
  990.     struct sockaddr_dl *sdl = (struct sockaddr_dl *)info;
  991.  
  992.     cp = (char *)LLADDR(sdl);
  993.     if ((n = sdl->sdl_alen) > 0) {
  994.         if (sdl->sdl_type == IFT_ETHER)
  995.             printf ("\tether ");
  996.         else
  997.             printf ("\tlladdr ");
  998.                  while (--n >= 0)
  999.             printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' ');
  1000.         putchar('\n');
  1001.     }
  1002. }
  1003.  
  1004. void
  1005. Perror(cmd)
  1006.     const char *cmd;
  1007. {
  1008.     switch (errno) {
  1009.  
  1010.     case ENXIO:
  1011.         errx(1, "%s: no such interface", cmd);
  1012.         break;
  1013.  
  1014.     case EPERM:
  1015.         errx(1, "%s: permission denied", cmd);
  1016.         break;
  1017.  
  1018.     default:
  1019.         err(1, "%s", cmd);
  1020.     }
  1021. }
  1022.  
  1023. #define SIN(x) ((struct sockaddr_in *) &(x))
  1024. struct sockaddr_in *sintab[] = {
  1025. SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
  1026. SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
  1027.  
  1028. void
  1029. in_getaddr(s, which)
  1030.     const char *s;
  1031.     int which;
  1032. {
  1033.     register struct sockaddr_in *sin = sintab[which];
  1034.     struct hostent *hp;
  1035.     struct netent *np;
  1036.  
  1037.     sin->sin_len = sizeof(*sin);
  1038.     if (which != MASK)
  1039.         sin->sin_family = AF_INET;
  1040.  
  1041.     if (inet_aton(s, &sin->sin_addr))
  1042.         return;
  1043.     if ((hp = gethostbyname(s)) != 0)
  1044.         bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
  1045.     else if ((np = getnetbyname(s)) != 0)
  1046.         sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
  1047.     else
  1048.         errx(1, "%s: bad value", s);
  1049. }
  1050.  
  1051. /*
  1052.  * Print a value a la the %b format of the kernel's printf
  1053.  */
  1054. void
  1055. printb(s, v, bits)
  1056.     const char *s;
  1057.     register unsigned v;
  1058.     register const char *bits;
  1059. {
  1060.     register int i, any = 0;
  1061.     register char c;
  1062.  
  1063.     if (bits && *bits == 8)
  1064.         printf("%s=%o", s, v);
  1065.     else
  1066.         printf("%s=%x", s, v);
  1067.     bits++;
  1068.     if (bits) {
  1069.         putchar('<');
  1070.         while ((i = *bits++) != '\0') {
  1071.             if (v & (1 << (i-1))) {
  1072.                 if (any)
  1073.                     putchar(',');
  1074.                 any = 1;
  1075.                 for (; (c = *bits) > 32; bits++)
  1076.                     putchar(c);
  1077.             } else
  1078.                 for (; *bits > 32; bits++)
  1079.                     ;
  1080.         }
  1081.         putchar('>');
  1082.     }
  1083. }
  1084.  
  1085. #define SIPX(x) ((struct sockaddr_ipx *) &(x))
  1086. struct sockaddr_ipx *sipxtab[] = {
  1087. SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr),
  1088. SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)};
  1089.  
  1090. void
  1091. ipx_getaddr(addr, which)
  1092.     const char *addr;
  1093.     int which;
  1094. {
  1095.     struct sockaddr_ipx *sipx = sipxtab[which];
  1096.  
  1097.     sipx->sipx_family = AF_IPX;
  1098.     sipx->sipx_len = sizeof(*sipx);
  1099.     sipx->sipx_addr = ipx_addr(addr);
  1100.     if (which == MASK)
  1101.         printf("Attempt to set IPX netmask will be ineffectual\n");
  1102. }
  1103.  
  1104. void
  1105. at_getaddr(addr, which)
  1106.     const char *addr;
  1107.     int which;
  1108. {
  1109.     struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr;
  1110.     u_int net, node;
  1111.  
  1112.     sat->sat_family = AF_APPLETALK;
  1113.     sat->sat_len = sizeof(*sat);
  1114.     if (which == MASK)
  1115.         errx(1, "AppleTalk does not use netmasks\n");
  1116.     if (sscanf(addr, "%u.%u", &net, &node) != 2
  1117.         || net > 0xffff || node > 0xfe)
  1118.         errx(1, "%s: illegal address", addr);
  1119.     sat->sat_addr.s_net = htons(net);
  1120.     sat->sat_addr.s_node = node;
  1121. }
  1122.  
  1123. /* XXX  FIXME -- should use strtoul for better parsing. */
  1124. void
  1125. setatrange(range, dummy, s, afp)
  1126.     const char *range;
  1127.     int dummy __unused;
  1128.     int s;
  1129.     const struct afswtch *afp;
  1130. {
  1131.     u_short    first = 123, last = 123;
  1132.  
  1133.     if (sscanf(range, "%hu-%hu", &first, &last) != 2
  1134.         || first == 0 || first > 0xffff
  1135.         || last == 0 || last > 0xffff || first > last)
  1136.         errx(1, "%s: illegal net range: %u-%u", range, first, last);
  1137.     at_nr.nr_firstnet = htons(first);
  1138.     at_nr.nr_lastnet = htons(last);
  1139. }
  1140.  
  1141. void
  1142. setatphase(phase, dummy, s, afp)
  1143.     const char *phase;
  1144.     int dummy __unused;
  1145.     int s;
  1146.     const struct afswtch *afp;
  1147. {
  1148.     if (!strcmp(phase, "1"))
  1149.         at_nr.nr_phase = 1;
  1150.     else if (!strcmp(phase, "2"))
  1151.         at_nr.nr_phase = 2;
  1152.     else
  1153.         errx(1, "%s: illegal phase", phase);
  1154. }
  1155.  
  1156. void
  1157. checkatrange(struct sockaddr_at *sat)
  1158. {
  1159.     if (at_nr.nr_phase == 0)
  1160.         at_nr.nr_phase = 2;    /* Default phase 2 */
  1161.     if (at_nr.nr_firstnet == 0)
  1162.         at_nr.nr_firstnet =    /* Default range of one */
  1163.         at_nr.nr_lastnet = sat->sat_addr.s_net;
  1164. printf("\tatalk %d.%d range %d-%d phase %d\n",
  1165.     ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
  1166.     ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase);
  1167.     if ((u_short) ntohs(at_nr.nr_firstnet) >
  1168.             (u_short) ntohs(sat->sat_addr.s_net)
  1169.             || (u_short) ntohs(at_nr.nr_lastnet) <
  1170.             (u_short) ntohs(sat->sat_addr.s_net))
  1171.         errx(1, "AppleTalk address is not in range");
  1172.     sat->sat_range.r_netrange = at_nr;
  1173. }
  1174.  
  1175. #ifdef NS
  1176. #define SNS(x) ((struct sockaddr_ns *) &(x))
  1177. struct sockaddr_ns *snstab[] = {
  1178. SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
  1179. SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
  1180.  
  1181. void
  1182. xns_getaddr(addr, which)
  1183.     const char *addr;
  1184.     int which;
  1185. {
  1186.     struct sockaddr_ns *sns = snstab[which];
  1187.  
  1188.     sns->sns_family = AF_NS;
  1189.     sns->sns_len = sizeof(*sns);
  1190.     sns->sns_addr = ns_addr(addr);
  1191.     if (which == MASK)
  1192.         printf("Attempt to set XNS netmask will be ineffectual\n");
  1193. }
  1194. #endif
  1195.  
  1196. #ifdef ISO
  1197. #define SISO(x) ((struct sockaddr_iso *) &(x))
  1198. struct sockaddr_iso *sisotab[] = {
  1199. SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr),
  1200. SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
  1201.  
  1202. void
  1203. iso_getaddr(addr, which)
  1204. char *addr;
  1205. {
  1206.     register struct sockaddr_iso *siso = sisotab[which];
  1207.     struct iso_addr *iso_addr();
  1208.     siso->siso_addr = *iso_addr(addr);
  1209.  
  1210.     if (which == MASK) {
  1211.         siso->siso_len = TSEL(siso) - (caddr_t)(siso);
  1212.         siso->siso_nlen = 0;
  1213.     } else {
  1214.         siso->siso_len = sizeof(*siso);
  1215.         siso->siso_family = AF_ISO;
  1216.     }
  1217. }
  1218.  
  1219. void
  1220. setnsellength(val)
  1221.     char *val;
  1222. {
  1223.     nsellength = atoi(val);
  1224.     if (nsellength < 0)
  1225.         errx(1, "Negative NSEL length is absurd");
  1226.     if (afp == 0 || afp->af_af != AF_ISO)
  1227.         errx(1, "Setting NSEL length valid only for iso");
  1228. }
  1229.  
  1230. void
  1231. fixnsel(s)
  1232. register struct sockaddr_iso *s;
  1233. {
  1234.     if (s->siso_family == 0)
  1235.         return;
  1236.     s->siso_tlen = nsellength;
  1237. }
  1238.  
  1239. void
  1240. adjust_nsellength()
  1241. {
  1242.     fixnsel(sisotab[RIDADDR]);
  1243.     fixnsel(sisotab[ADDR]);
  1244.     fixnsel(sisotab[DSTADDR]);
  1245. }
  1246. #endif
  1247.