home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / net / if.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-06  |  15.2 KB  |  635 lines

  1. /*
  2.  * Copyright (c) 1980, 1986 Regents of the University of California.
  3.  * 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.  *    @(#)if.c    7.14 (Berkeley) 4/20/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "mbuf.h"
  38. #include "systm.h"
  39. #include "socket.h"
  40. #include "socketvar.h"
  41. #include "protosw.h"
  42. #include "proc.h"
  43. #include "kernel.h"
  44. #include "ioctl.h"
  45.  
  46. #include "if.h"
  47. #include "af.h"
  48. #include "if_dl.h"
  49. #include "if_types.h"
  50.  
  51. #include "ether.h"
  52.  
  53. int    ifqmaxlen = IFQ_MAXLEN;
  54.  
  55. /*
  56.  * Network interface utility routines.
  57.  *
  58.  * Routines with ifa_ifwith* names take sockaddr *'s as
  59.  * parameters.
  60.  */
  61.  
  62. ifinit()
  63. {
  64.     register struct ifnet *ifp;
  65.  
  66.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  67.         if (ifp->if_snd.ifq_maxlen == 0)
  68.             ifp->if_snd.ifq_maxlen = ifqmaxlen;
  69.     if_slowtimo();
  70. }
  71.  
  72. #ifdef vax
  73. /*
  74.  * Call each interface on a Unibus reset.
  75.  */
  76. ifubareset(uban)
  77.     int uban;
  78. {
  79.     register struct ifnet *ifp;
  80.  
  81.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  82.         if (ifp->if_reset)
  83.             (*ifp->if_reset)(ifp->if_unit, uban);
  84. }
  85. #endif
  86.  
  87. int if_index = 0;
  88. struct ifaddr **ifnet_addrs;
  89. static char *sprint_d();
  90.  
  91. /*
  92.  * Attach an interface to the
  93.  * list of "active" interfaces.
  94.  */
  95. if_attach(ifp)
  96.     struct ifnet *ifp;
  97. {
  98.     unsigned socksize, ifasize;
  99.     int namelen, unitlen;
  100.     char workbuf[12], *unitname;
  101.     register struct ifnet **p = &ifnet;
  102.     register struct sockaddr_dl *sdl;
  103.     register struct ifaddr *ifa;
  104.     static int if_indexlim = 8;
  105.     extern link_rtrequest(), ether_output();
  106.  
  107.     while (*p)
  108.         p = &((*p)->if_next);
  109.     *p = ifp;
  110.     ifp->if_index = ++if_index;
  111.     if (ifnet_addrs == 0 || if_index >= if_indexlim) {
  112.         unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
  113.         struct ifaddr **q = (struct ifaddr **)
  114.                     malloc(n, M_IFADDR, M_WAITOK);
  115.         if (ifnet_addrs) {
  116.             bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
  117.             free((caddr_t)ifnet_addrs, M_IFADDR);
  118.         }
  119.         ifnet_addrs = q;
  120.     }
  121.     /* XXX -- Temporary fix before changing 10 ethernet drivers */
  122.     if (ifp->if_output == ether_output) {
  123.         ifp->if_type = IFT_ETHER;
  124.         ifp->if_addrlen = 6;
  125.         ifp->if_hdrlen = 14;
  126.     }
  127.     /*
  128.      * create a Link Level name for this device
  129.      */
  130.     unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
  131.     namelen = strlen(ifp->if_name);
  132.     unitlen = strlen(unitname);
  133. #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
  134.     socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
  135.                    unitlen + namelen + ifp->if_addrlen;
  136. #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  137.     socksize = ROUNDUP(socksize);
  138.     if (socksize < sizeof(*sdl))
  139.         socksize = sizeof(*sdl);
  140.     ifasize = sizeof(*ifa) + 2 * socksize;
  141.     ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
  142.     if (ifa == 0)
  143.         return;
  144.     ifnet_addrs[if_index - 1] = ifa;
  145.     bzero((caddr_t)ifa, ifasize);
  146.     sdl = (struct sockaddr_dl *)(ifa + 1);
  147.     ifa->ifa_addr = (struct sockaddr *)sdl;
  148.     ifa->ifa_ifp = ifp;
  149.     sdl->sdl_len = socksize;
  150.     sdl->sdl_family = AF_LINK;
  151.     bcopy(ifp->if_name, sdl->sdl_data, namelen);
  152.     bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
  153.     sdl->sdl_nlen = (namelen += unitlen);
  154.     sdl->sdl_index = ifp->if_index;
  155.     sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  156.     ifa->ifa_netmask = (struct sockaddr *)sdl;
  157.     sdl->sdl_len = socksize - ifp->if_addrlen;
  158.     while (namelen != 0)
  159.         sdl->sdl_data[--namelen] = 0xff;
  160.     ifa->ifa_next = ifp->if_addrlist;
  161.     ifa->ifa_rtrequest = link_rtrequest;
  162.     ifp->if_addrlist = ifa;
  163. }
  164. /*
  165.  * Locate an interface based on a complete address.
  166.  */
  167. /*ARGSUSED*/
  168. struct ifaddr *
  169. ifa_ifwithaddr(addr)
  170.     register struct sockaddr *addr;
  171. {
  172.     register struct ifnet *ifp;
  173.     register struct ifaddr *ifa;
  174.  
  175. #define    equal(a1, a2) \
  176.   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  177.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  178.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  179.         if (ifa->ifa_addr->sa_family != addr->sa_family)
  180.             continue;
  181.         if (equal(addr, ifa->ifa_addr))
  182.             return (ifa);
  183.         if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
  184.             equal(ifa->ifa_broadaddr, addr))
  185.             return (ifa);
  186.     }
  187.     return ((struct ifaddr *)0);
  188. }
  189. /*
  190.  * Locate the point to point interface with a given destination address.
  191.  */
  192. /*ARGSUSED*/
  193. struct ifaddr *
  194. ifa_ifwithdstaddr(addr)
  195.     register struct sockaddr *addr;
  196. {
  197.     register struct ifnet *ifp;
  198.     register struct ifaddr *ifa;
  199.  
  200.     for (ifp = ifnet; ifp; ifp = ifp->if_next) 
  201.         if (ifp->if_flags & IFF_POINTOPOINT)
  202.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  203.             if (ifa->ifa_addr->sa_family != addr->sa_family)
  204.                 continue;
  205.             if (equal(addr, ifa->ifa_dstaddr))
  206.                 return (ifa);
  207.     }
  208.     return ((struct ifaddr *)0);
  209. }
  210.  
  211. /*
  212.  * Find an interface on a specific network.  If many, choice
  213.  * is first found.
  214.  */
  215. struct ifaddr *
  216. ifa_ifwithnet(addr)
  217.     struct sockaddr *addr;
  218. {
  219.     register struct ifnet *ifp;
  220.     register struct ifaddr *ifa;
  221.     u_int af = addr->sa_family;
  222.  
  223.     if (af >= AF_MAX)
  224.         return (0);
  225.     if (af == AF_LINK) {
  226.         register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
  227.         if (sdl->sdl_index && sdl->sdl_index <= if_index)
  228.         return (ifnet_addrs[sdl->sdl_index - 1]);
  229.     }
  230.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  231.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  232.         register char *cp, *cp2, *cp3;
  233.         register char *cplim;
  234.         if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
  235.             continue;
  236.         cp = addr->sa_data;
  237.         cp2 = ifa->ifa_addr->sa_data;
  238.         cp3 = ifa->ifa_netmask->sa_data;
  239.         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  240.         for (; cp3 < cplim; cp3++)
  241.             if ((*cp++ ^ *cp2++) & *cp3)
  242.                 break;
  243.         if (cp3 == cplim)
  244.             return (ifa);
  245.         }
  246.     return ((struct ifaddr *)0);
  247. }
  248.  
  249. /*
  250.  * Find an interface using a specific address family
  251.  */
  252. struct ifaddr *
  253. ifa_ifwithaf(af)
  254.     register int af;
  255. {
  256.     register struct ifnet *ifp;
  257.     register struct ifaddr *ifa;
  258.  
  259.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  260.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  261.         if (ifa->ifa_addr->sa_family == af)
  262.             return (ifa);
  263.     return ((struct ifaddr *)0);
  264. }
  265.  
  266. /*
  267.  * Find an interface address specific to an interface best matching
  268.  * a given address.
  269.  */
  270. struct ifaddr *
  271. ifaof_ifpforaddr(addr, ifp)
  272.     struct sockaddr *addr;
  273.     register struct ifnet *ifp;
  274. {
  275.     register struct ifaddr *ifa;
  276.     register char *cp, *cp2, *cp3;
  277.     register char *cplim;
  278.     struct ifaddr *ifa_maybe = 0;
  279.     u_int af = addr->sa_family;
  280.  
  281.     if (af >= AF_MAX)
  282.         return (0);
  283.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  284.         if (ifa->ifa_addr->sa_family != af)
  285.             continue;
  286.         ifa_maybe = ifa;
  287.         if (ifa->ifa_netmask == 0) {
  288.             if (equal(addr, ifa->ifa_addr) ||
  289.                 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
  290.                 return (ifa);
  291.             continue;
  292.         }
  293.         cp = addr->sa_data;
  294.         cp2 = ifa->ifa_addr->sa_data;
  295.         cp3 = ifa->ifa_netmask->sa_data;
  296.         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  297.         for (; cp3 < cplim; cp3++)
  298.             if ((*cp++ ^ *cp2++) & *cp3)
  299.                 break;
  300.         if (cp3 == cplim)
  301.             return (ifa);
  302.     }
  303.     return (ifa_maybe);
  304. }
  305. #include "route.h"
  306. /*
  307.  * Default action when installing a route with a Link Level gateway.
  308.  * Lookup an appropriate real ifa to point to.
  309.  * This should be moved to /sys/net/link.c eventually.
  310.  */
  311. link_rtrequest(cmd, rt, sa)
  312. register struct rtentry *rt;
  313. struct sockaddr *sa;
  314. {
  315.     register struct ifaddr *ifa;
  316.     struct sockaddr *dst;
  317.     struct ifnet *ifp, *oldifnet = ifnet;
  318.  
  319.     if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
  320.         ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
  321.         return;
  322.     if (ifa = ifaof_ifpforaddr(dst, ifp)) {
  323.         rt->rt_ifa = ifa;
  324.         if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
  325.             ifa->ifa_rtrequest(cmd, rt, sa);
  326.     }
  327. }
  328.  
  329. /*
  330.  * Mark an interface down and notify protocols of
  331.  * the transition.
  332.  * NOTE: must be called at splnet or eqivalent.
  333.  */
  334. if_down(ifp)
  335.     register struct ifnet *ifp;
  336. {
  337.     register struct ifaddr *ifa;
  338.  
  339.     ifp->if_flags &= ~IFF_UP;
  340.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  341.         pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
  342.     if_qflush(&ifp->if_snd);
  343. }
  344.  
  345. /*
  346.  * Flush an interface queue.
  347.  */
  348. if_qflush(ifq)
  349.     register struct ifqueue *ifq;
  350. {
  351.     register struct mbuf *m, *n;
  352.  
  353.     n = ifq->ifq_head;
  354.     while (m = n) {
  355.         n = m->m_act;
  356.         m_freem(m);
  357.     }
  358.     ifq->ifq_head = 0;
  359.     ifq->ifq_tail = 0;
  360.     ifq->ifq_len = 0;
  361. }
  362.  
  363. /*
  364.  * Handle interface watchdog timer routines.  Called
  365.  * from softclock, we decrement timers (if set) and
  366.  * call the appropriate interface routine on expiration.
  367.  */
  368. if_slowtimo()
  369. {
  370.     register struct ifnet *ifp;
  371.     int s = splimp();
  372.  
  373.     for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  374.         if (ifp->if_timer == 0 || --ifp->if_timer)
  375.             continue;
  376.         if (ifp->if_watchdog)
  377.             (*ifp->if_watchdog)(ifp->if_unit);
  378.     }
  379.     splx(s);
  380.     timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
  381. }
  382.  
  383. /*
  384.  * Map interface name to
  385.  * interface structure pointer.
  386.  */
  387. struct ifnet *
  388. ifunit(name)
  389.     register char *name;
  390. {
  391.     register char *cp;
  392.     register struct ifnet *ifp;
  393.     int unit;
  394.     unsigned len;
  395.     char *ep, c;
  396.  
  397.     for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
  398.         if (*cp >= '0' && *cp <= '9')
  399.             break;
  400.     if (*cp == '\0' || cp == name + IFNAMSIZ)
  401.         return ((struct ifnet *)0);
  402.     /*
  403.      * Save first char of unit, and pointer to it,
  404.      * so we can put a null there to avoid matching
  405.      * initial substrings of interface names.
  406.      */
  407.     len = cp - name + 1;
  408.     c = *cp;
  409.     ep = cp;
  410.     for (unit = 0; *cp >= '0' && *cp <= '9'; )
  411.         unit = unit * 10 + *cp++ - '0';
  412.     *ep = 0;
  413.     for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  414.         if (bcmp(ifp->if_name, name, len))
  415.             continue;
  416.         if (unit == ifp->if_unit)
  417.             break;
  418.     }
  419.     *ep = c;
  420.     return (ifp);
  421. }
  422.  
  423. /*
  424.  * Interface ioctls.
  425.  */
  426. ifioctl(so, cmd, data, p)
  427.     struct socket *so;
  428.     int cmd;
  429.     caddr_t data;
  430.     struct proc *p;
  431. {
  432.     register struct ifnet *ifp;
  433.     register struct ifreq *ifr;
  434.     int error;
  435.  
  436.     switch (cmd) {
  437.  
  438.     case SIOCGIFCONF:
  439.     case OSIOCGIFCONF:
  440.         return (ifconf(cmd, data));
  441.  
  442. #if defined(INET) && NETHER > 0
  443.     case SIOCSARP:
  444.     case SIOCDARP:
  445.         if (error = suser(p->p_ucred, &p->p_acflag))
  446.             return (error);
  447.         /* FALL THROUGH */
  448.     case SIOCGARP:
  449.     case OSIOCGARP:
  450.         return (arpioctl(cmd, data));
  451. #endif
  452.     }
  453.     ifr = (struct ifreq *)data;
  454.     ifp = ifunit(ifr->ifr_name);
  455.     if (ifp == 0)
  456.         return (ENXIO);
  457.     switch (cmd) {
  458.  
  459.     case SIOCGIFFLAGS:
  460.         ifr->ifr_flags = ifp->if_flags;
  461.         break;
  462.  
  463.     case SIOCGIFMETRIC:
  464.         ifr->ifr_metric = ifp->if_metric;
  465.         break;
  466.  
  467.     case SIOCSIFFLAGS:
  468.         if (error = suser(p->p_ucred, &p->p_acflag))
  469.             return (error);
  470.         if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
  471.             int s = splimp();
  472.             if_down(ifp);
  473.             splx(s);
  474.         }
  475.         ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
  476.             (ifr->ifr_flags &~ IFF_CANTCHANGE);
  477.         if (ifp->if_ioctl)
  478.             (void) (*ifp->if_ioctl)(ifp, cmd, data);
  479.         break;
  480.  
  481.     case SIOCSIFMETRIC:
  482.         if (error = suser(p->p_ucred, &p->p_acflag))
  483.             return (error);
  484.         ifp->if_metric = ifr->ifr_metric;
  485.         break;
  486.  
  487.     default:
  488.         if (so->so_proto == 0)
  489.             return (EOPNOTSUPP);
  490. #ifndef COMPAT_43
  491.         return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
  492.             cmd, data, ifp));
  493. #else
  494.         {
  495.         int ocmd = cmd;
  496.  
  497.         switch (cmd) {
  498.  
  499.         case SIOCSIFDSTADDR:
  500.         case SIOCSIFADDR:
  501.         case SIOCSIFBRDADDR:
  502.         case SIOCSIFNETMASK:
  503. #if BYTE_ORDER != BIG_ENDIAN
  504.             if (ifr->ifr_addr.sa_family == 0 &&
  505.                 ifr->ifr_addr.sa_len < 16) {
  506.                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
  507.                 ifr->ifr_addr.sa_len = 16;
  508.             }
  509. #else
  510.             if (ifr->ifr_addr.sa_len == 0)
  511.                 ifr->ifr_addr.sa_len = 16;
  512. #endif
  513.             break;
  514.  
  515.         case OSIOCGIFADDR:
  516.             cmd = SIOCGIFADDR;
  517.             break;
  518.  
  519.         case OSIOCGIFDSTADDR:
  520.             cmd = SIOCGIFDSTADDR;
  521.             break;
  522.  
  523.         case OSIOCGIFBRDADDR:
  524.             cmd = SIOCGIFBRDADDR;
  525.             break;
  526.  
  527.         case OSIOCGIFNETMASK:
  528.             cmd = SIOCGIFNETMASK;
  529.         }
  530.         error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
  531.                                 cmd, data, ifp));
  532.         switch (ocmd) {
  533.  
  534.         case OSIOCGIFADDR:
  535.         case OSIOCGIFDSTADDR:
  536.         case OSIOCGIFBRDADDR:
  537.         case OSIOCGIFNETMASK:
  538.             *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
  539.         }
  540.         return (error);
  541.  
  542.         }
  543. #endif
  544.     }
  545.     return (0);
  546. }
  547.  
  548. /*
  549.  * Return interface configuration
  550.  * of system.  List may be used
  551.  * in later ioctl's (above) to get
  552.  * other information.
  553.  */
  554. /*ARGSUSED*/
  555. ifconf(cmd, data)
  556.     int cmd;
  557.     caddr_t data;
  558. {
  559.     register struct ifconf *ifc = (struct ifconf *)data;
  560.     register struct ifnet *ifp = ifnet;
  561.     register struct ifaddr *ifa;
  562.     register char *cp, *ep;
  563.     struct ifreq ifr, *ifrp;
  564.     int space = ifc->ifc_len, error = 0;
  565.  
  566.     ifrp = ifc->ifc_req;
  567.     ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
  568.     for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
  569.         bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
  570.         for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
  571.             ;
  572.         *cp++ = '0' + ifp->if_unit; *cp = '\0';
  573.         if ((ifa = ifp->if_addrlist) == 0) {
  574.             bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
  575.             error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
  576.             if (error)
  577.                 break;
  578.             space -= sizeof (ifr), ifrp++;
  579.         } else 
  580.             for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
  581.             register struct sockaddr *sa = ifa->ifa_addr;
  582. #ifdef COMPAT_43
  583.             if (cmd == OSIOCGIFCONF) {
  584.                 struct osockaddr *osa =
  585.                      (struct osockaddr *)&ifr.ifr_addr;
  586.                 ifr.ifr_addr = *sa;
  587.                 osa->sa_family = sa->sa_family;
  588.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  589.                         sizeof (ifr));
  590.                 ifrp++;
  591.             } else
  592. #endif
  593.             if (sa->sa_len <= sizeof(*sa)) {
  594.                 ifr.ifr_addr = *sa;
  595.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  596.                         sizeof (ifr));
  597.                 ifrp++;
  598.             } else {
  599.                 space -= sa->sa_len - sizeof(*sa);
  600.                 if (space < sizeof (ifr))
  601.                     break;
  602.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  603.                         sizeof (ifr.ifr_name));
  604.                 if (error == 0)
  605.                     error = copyout((caddr_t)sa,
  606.                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
  607.                 ifrp = (struct ifreq *)
  608.                     (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
  609.             }
  610.             if (error)
  611.                 break;
  612.             space -= sizeof (ifr);
  613.         }
  614.     }
  615.     ifc->ifc_len -= space;
  616.     return (error);
  617. }
  618.  
  619. static char *
  620. sprint_d(n, buf, buflen)
  621.     u_int n;
  622.     char *buf;
  623.     int buflen;
  624. {
  625.     register char *cp = buf + buflen - 1;
  626.  
  627.     *cp = 0;
  628.     do {
  629.         cp--;
  630.         *cp = "0123456789"[n % 10];
  631.         n /= 10;
  632.     } while (n != 0);
  633.     return (cp);
  634. }
  635.