home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / bsdss4.tz / bsdss4 / bsdss / server / net / if.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-22  |  16.5 KB  |  675 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1992 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon 
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    if.c,v $
  29.  * Revision 2.1  92/04/21  17:13:56  rwd
  30.  * BSDSS
  31.  * 
  32.  *
  33.  */
  34.  
  35. /*
  36.  * Copyright (c) 1980, 1986 Regents of the University of California.
  37.  * All rights reserved.
  38.  *
  39.  * Redistribution and use in source and binary forms, with or without
  40.  * modification, are permitted provided that the following conditions
  41.  * are met:
  42.  * 1. Redistributions of source code must retain the above copyright
  43.  *    notice, this list of conditions and the following disclaimer.
  44.  * 2. Redistributions in binary form must reproduce the above copyright
  45.  *    notice, this list of conditions and the following disclaimer in the
  46.  *    documentation and/or other materials provided with the distribution.
  47.  * 3. All advertising materials mentioning features or use of this software
  48.  *    must display the following acknowledgement:
  49.  *    This product includes software developed by the University of
  50.  *    California, Berkeley and its contributors.
  51.  * 4. Neither the name of the University nor the names of its contributors
  52.  *    may be used to endorse or promote products derived from this software
  53.  *    without specific prior written permission.
  54.  *
  55.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  56.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  57.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  58.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  59.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  60.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  61.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  62.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  63.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  64.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  65.  * SUCH DAMAGE.
  66.  *
  67.  *    @(#)if.c    7.14 (Berkeley) 4/20/91
  68.  */
  69.  
  70. #include <sys/param.h>
  71. #include <sys/mbuf.h>
  72. #include <sys/systm.h>
  73. #include <sys/socket.h>
  74. #include <sys/socketvar.h>
  75. #include <sys/protosw.h>
  76. #include <sys/proc.h>
  77. #include <sys/kernel.h>
  78. #include <sys/ioctl.h>
  79. #include <sys/synch.h>
  80.  
  81. #include <net/if.h>
  82. #include <net/af.h>
  83. #include <net/if_dl.h>
  84. #include <net/if_types.h>
  85.  
  86. #include <ether.h>
  87.  
  88. int    ifqmaxlen = IFQ_MAXLEN;
  89.  
  90. /*
  91.  * Network interface utility routines.
  92.  *
  93.  * Routines with ifa_ifwith* names take sockaddr *'s as
  94.  * parameters.
  95.  */
  96.  
  97. ifinit()
  98. {
  99.     register struct ifnet *ifp;
  100.  
  101.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  102.         if (ifp->if_snd.ifq_maxlen == 0)
  103.             ifp->if_snd.ifq_maxlen = ifqmaxlen;
  104.     if_slowtimo();
  105. }
  106.  
  107. #ifdef vax
  108. /*
  109.  * Call each interface on a Unibus reset.
  110.  */
  111. ifubareset(uban)
  112.     int uban;
  113. {
  114.     register struct ifnet *ifp;
  115.  
  116.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  117.         if (ifp->if_reset)
  118.             (*ifp->if_reset)(ifp->if_unit, uban);
  119. }
  120. #endif
  121.  
  122. int if_index = 0;
  123. struct ifaddr **ifnet_addrs;
  124. static char *sprint_d();
  125.  
  126. /*
  127.  * Attach an interface to the
  128.  * list of "active" interfaces.
  129.  */
  130. if_attach(ifp)
  131.     struct ifnet *ifp;
  132. {
  133.     unsigned socksize, ifasize;
  134.     int namelen, unitlen;
  135.     char workbuf[12], *unitname;
  136.     register struct ifnet **p = &ifnet;
  137.     register struct sockaddr_dl *sdl;
  138.     register struct ifaddr *ifa;
  139.     static int if_indexlim = 8;
  140.     extern link_rtrequest(), ether_output();
  141.  
  142.     while (*p)
  143.         p = &((*p)->if_next);
  144.     *p = ifp;
  145.     ifp->if_index = ++if_index;
  146.     if (ifnet_addrs == 0 || if_index >= if_indexlim) {
  147.         unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
  148.         struct ifaddr **q = (struct ifaddr **)
  149.                     bsd_malloc(n, M_IFADDR, M_WAITOK);
  150.         if (ifnet_addrs) {
  151.             bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
  152.             bsd_free((caddr_t)ifnet_addrs, M_IFADDR);
  153.         }
  154.         ifnet_addrs = q;
  155.     }
  156.     /* XXX -- Temporary fix before changing 10 ethernet drivers */
  157.     if (ifp->if_output == ether_output) {
  158.         ifp->if_type = IFT_ETHER;
  159.         ifp->if_addrlen = 6;
  160.         ifp->if_hdrlen = 14;
  161.     }
  162.     /*
  163.      * create a Link Level name for this device
  164.      */
  165.     unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
  166.     namelen = strlen(ifp->if_name);
  167.     unitlen = strlen(unitname);
  168. #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
  169.     socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
  170.                    unitlen + namelen + ifp->if_addrlen;
  171. #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  172.     socksize = ROUNDUP(socksize);
  173.     if (socksize < sizeof(*sdl))
  174.         socksize = sizeof(*sdl);
  175.     ifasize = sizeof(*ifa) + 2 * socksize;
  176.     ifa = (struct ifaddr *)bsd_malloc(ifasize, M_IFADDR, M_WAITOK);
  177.     if (ifa == 0)
  178.         return;
  179.     ifnet_addrs[if_index - 1] = ifa;
  180.     bzero((caddr_t)ifa, ifasize);
  181.     sdl = (struct sockaddr_dl *)(ifa + 1);
  182.     ifa->ifa_addr = (struct sockaddr *)sdl;
  183.     ifa->ifa_ifp = ifp;
  184.     sdl->sdl_len = socksize;
  185.     sdl->sdl_family = AF_LINK;
  186.     bcopy(ifp->if_name, sdl->sdl_data, namelen);
  187.     bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
  188.     sdl->sdl_nlen = (namelen += unitlen);
  189.     sdl->sdl_index = ifp->if_index;
  190.     sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  191.     ifa->ifa_netmask = (struct sockaddr *)sdl;
  192.     sdl->sdl_len = socksize - ifp->if_addrlen;
  193.     while (namelen != 0)
  194.         sdl->sdl_data[--namelen] = 0xff;
  195.     ifa->ifa_next = ifp->if_addrlist;
  196.     ifa->ifa_rtrequest = link_rtrequest;
  197.     ifp->if_addrlist = ifa;
  198. }
  199. /*
  200.  * Locate an interface based on a complete address.
  201.  */
  202. /*ARGSUSED*/
  203. struct ifaddr *
  204. ifa_ifwithaddr(addr)
  205.     register struct sockaddr *addr;
  206. {
  207.     register struct ifnet *ifp;
  208.     register struct ifaddr *ifa;
  209.  
  210. #define    equal(a1, a2) \
  211.   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  212.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  213.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  214.         if (ifa->ifa_addr->sa_family != addr->sa_family)
  215.             continue;
  216.         if (equal(addr, ifa->ifa_addr))
  217.             return (ifa);
  218.         if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
  219.             equal(ifa->ifa_broadaddr, addr))
  220.             return (ifa);
  221.     }
  222.     return ((struct ifaddr *)0);
  223. }
  224. /*
  225.  * Locate the point to point interface with a given destination address.
  226.  */
  227. /*ARGSUSED*/
  228. struct ifaddr *
  229. ifa_ifwithdstaddr(addr)
  230.     register struct sockaddr *addr;
  231. {
  232.     register struct ifnet *ifp;
  233.     register struct ifaddr *ifa;
  234.  
  235.     for (ifp = ifnet; ifp; ifp = ifp->if_next) 
  236.         if (ifp->if_flags & IFF_POINTOPOINT)
  237.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  238.             if (ifa->ifa_addr->sa_family != addr->sa_family)
  239.                 continue;
  240.             if (equal(addr, ifa->ifa_dstaddr))
  241.                 return (ifa);
  242.     }
  243.     return ((struct ifaddr *)0);
  244. }
  245.  
  246. /*
  247.  * Find an interface on a specific network.  If many, choice
  248.  * is first found.
  249.  */
  250. struct ifaddr *
  251. ifa_ifwithnet(addr)
  252.     struct sockaddr *addr;
  253. {
  254.     register struct ifnet *ifp;
  255.     register struct ifaddr *ifa;
  256.     u_int af = addr->sa_family;
  257.  
  258.     if (af >= AF_MAX)
  259.         return (0);
  260.     if (af == AF_LINK) {
  261.         register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
  262.         if (sdl->sdl_index && sdl->sdl_index <= if_index)
  263.         return (ifnet_addrs[sdl->sdl_index - 1]);
  264.     }
  265.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  266.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  267.         register char *cp, *cp2, *cp3;
  268.         register char *cplim;
  269.         if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
  270.             continue;
  271.         cp = addr->sa_data;
  272.         cp2 = ifa->ifa_addr->sa_data;
  273.         cp3 = ifa->ifa_netmask->sa_data;
  274.         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  275.         for (; cp3 < cplim; cp3++)
  276.             if ((*cp++ ^ *cp2++) & *cp3)
  277.                 break;
  278.         if (cp3 == cplim)
  279.             return (ifa);
  280.         }
  281.     return ((struct ifaddr *)0);
  282. }
  283.  
  284. /*
  285.  * Find an interface using a specific address family
  286.  */
  287. struct ifaddr *
  288. ifa_ifwithaf(af)
  289.     register int af;
  290. {
  291.     register struct ifnet *ifp;
  292.     register struct ifaddr *ifa;
  293.  
  294.     for (ifp = ifnet; ifp; ifp = ifp->if_next)
  295.         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  296.         if (ifa->ifa_addr->sa_family == af)
  297.             return (ifa);
  298.     return ((struct ifaddr *)0);
  299. }
  300.  
  301. /*
  302.  * Find an interface address specific to an interface best matching
  303.  * a given address.
  304.  */
  305. struct ifaddr *
  306. ifaof_ifpforaddr(addr, ifp)
  307.     struct sockaddr *addr;
  308.     register struct ifnet *ifp;
  309. {
  310.     register struct ifaddr *ifa;
  311.     register char *cp, *cp2, *cp3;
  312.     register char *cplim;
  313.     struct ifaddr *ifa_maybe = 0;
  314.     u_int af = addr->sa_family;
  315.  
  316.     if (af >= AF_MAX)
  317.         return (0);
  318.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
  319.         if (ifa->ifa_addr->sa_family != af)
  320.             continue;
  321.         ifa_maybe = ifa;
  322.         if (ifa->ifa_netmask == 0) {
  323.             if (equal(addr, ifa->ifa_addr) ||
  324.                 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
  325.                 return (ifa);
  326.             continue;
  327.         }
  328.         cp = addr->sa_data;
  329.         cp2 = ifa->ifa_addr->sa_data;
  330.         cp3 = ifa->ifa_netmask->sa_data;
  331.         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  332.         for (; cp3 < cplim; cp3++)
  333.             if ((*cp++ ^ *cp2++) & *cp3)
  334.                 break;
  335.         if (cp3 == cplim)
  336.             return (ifa);
  337.     }
  338.     return (ifa_maybe);
  339. }
  340. #include <net/route.h>
  341. /*
  342.  * Default action when installing a route with a Link Level gateway.
  343.  * Lookup an appropriate real ifa to point to.
  344.  * This should be moved to /sys/net/link.c eventually.
  345.  */
  346. link_rtrequest(cmd, rt, sa)
  347. register struct rtentry *rt;
  348. struct sockaddr *sa;
  349. {
  350.     register struct ifaddr *ifa;
  351.     struct sockaddr *dst;
  352.     struct ifnet *ifp, *oldifnet = ifnet;
  353.  
  354.     if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
  355.         ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
  356.         return;
  357.     if (ifa = ifaof_ifpforaddr(dst, ifp)) {
  358.         rt->rt_ifa = ifa;
  359.         if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
  360.             ifa->ifa_rtrequest(cmd, rt, sa);
  361.     }
  362. }
  363.  
  364. /*
  365.  * Mark an interface down and notify protocols of
  366.  * the transition.
  367.  * NOTE: must be called at splnet or eqivalent.
  368.  */
  369. if_down(ifp)
  370.     register struct ifnet *ifp;
  371. {
  372.     register struct ifaddr *ifa;
  373.  
  374.     ifp->if_flags &= ~IFF_UP;
  375.     for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
  376.         pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
  377.     if_qflush(&ifp->if_snd);
  378. }
  379.  
  380. /*
  381.  * Flush an interface queue.
  382.  */
  383. if_qflush(ifq)
  384.     register struct ifqueue *ifq;
  385. {
  386.     register struct mbuf *m, *n;
  387.  
  388.     n = ifq->ifq_head;
  389.     while (m = n) {
  390.         n = m->m_act;
  391.         m_freem(m);
  392.     }
  393.     ifq->ifq_head = 0;
  394.     ifq->ifq_tail = 0;
  395.     ifq->ifq_len = 0;
  396. }
  397.  
  398. /*
  399.  * Handle interface watchdog timer routines.  Called
  400.  * from softclock, we decrement timers (if set) and
  401.  * call the appropriate interface routine on expiration.
  402.  */
  403. if_slowtimo()
  404. {
  405.     register struct ifnet *ifp;
  406.     int s = splimp();
  407.  
  408.     for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  409.         if (ifp->if_timer == 0 || --ifp->if_timer)
  410.             continue;
  411.         if (ifp->if_watchdog)
  412.             (*ifp->if_watchdog)(ifp->if_unit);
  413.     }
  414.     splx(s);
  415.     timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
  416. }
  417.  
  418. /*
  419.  * Map interface name to
  420.  * interface structure pointer.
  421.  */
  422. struct ifnet *
  423. ifunit(name)
  424.     register char *name;
  425. {
  426.     register char *cp;
  427.     register struct ifnet *ifp;
  428.     int unit;
  429.     unsigned len;
  430.     char *ep, c;
  431.  
  432.     for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
  433.         if (*cp >= '0' && *cp <= '9')
  434.             break;
  435.     if (*cp == '\0' || cp == name + IFNAMSIZ)
  436.         return ((struct ifnet *)0);
  437.     /*
  438.      * Save first char of unit, and pointer to it,
  439.      * so we can put a null there to avoid matching
  440.      * initial substrings of interface names.
  441.      */
  442.     len = cp - name + 1;
  443.     c = *cp;
  444.     ep = cp;
  445.     for (unit = 0; *cp >= '0' && *cp <= '9'; )
  446.         unit = unit * 10 + *cp++ - '0';
  447.     *ep = 0;
  448.     for (ifp = ifnet; ifp; ifp = ifp->if_next) {
  449.         if (bcmp(ifp->if_name, name, len))
  450.             continue;
  451.         if (unit == ifp->if_unit)
  452.             break;
  453.     }
  454.     *ep = c;
  455.     {
  456.         extern struct ifnet *iface_find();
  457.         if (ifp == 0)
  458.         ifp = iface_find(name);
  459.     }
  460.     return (ifp);
  461. }
  462.  
  463. /*
  464.  * Interface ioctls.
  465.  */
  466. ifioctl(so, cmd, data, p)
  467.     struct socket *so;
  468.     int cmd;
  469.     caddr_t data;
  470.     struct proc *p;
  471. {
  472.     register struct ifnet *ifp;
  473.     register struct ifreq *ifr;
  474.     int error;
  475.  
  476.     switch (cmd) {
  477.  
  478.     case SIOCGIFCONF:
  479.     case OSIOCGIFCONF:
  480.         return (ifconf(cmd, data));
  481.  
  482. #if INET && NETHER > 0
  483.     case SIOCSARP:
  484.     case SIOCDARP:
  485.         if (error = suser(p->p_ucred, &p->p_acflag))
  486.             return (error);
  487.         /* FALL THROUGH */
  488.     case SIOCGARP:
  489.     case OSIOCGARP:
  490.         return (arpioctl(cmd, data));
  491. #endif
  492.     }
  493.     ifr = (struct ifreq *)data;
  494.     ifp = ifunit(ifr->ifr_name);
  495.     if (ifp == 0)
  496.         return (ENXIO);
  497.     switch (cmd) {
  498.  
  499.     case SIOCGIFFLAGS:
  500.         ifr->ifr_flags = ifp->if_flags;
  501.         break;
  502.  
  503.     case SIOCGIFMETRIC:
  504.         ifr->ifr_metric = ifp->if_metric;
  505.         break;
  506.  
  507.     case SIOCSIFFLAGS:
  508.         if (error = suser(p->p_ucred, &p->p_acflag))
  509.             return (error);
  510.         if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
  511.             int s = splimp();
  512.             if_down(ifp);
  513.             splx(s);
  514.         }
  515.         ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
  516.             (ifr->ifr_flags &~ IFF_CANTCHANGE);
  517.         if (ifp->if_ioctl)
  518.             (void) (*ifp->if_ioctl)(ifp, cmd, data);
  519.         break;
  520.  
  521.     case SIOCSIFMETRIC:
  522.         if (error = suser(p->p_ucred, &p->p_acflag))
  523.             return (error);
  524.         ifp->if_metric = ifr->ifr_metric;
  525.         break;
  526.  
  527.     default:
  528.         if (so->so_proto == 0)
  529.             return (EOPNOTSUPP);
  530. #ifndef COMPAT_43
  531.         return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
  532.             cmd, data, ifp));
  533. #else
  534.         {
  535.         int ocmd = cmd;
  536.  
  537.         switch (cmd) {
  538.  
  539.         case SIOCSIFDSTADDR:
  540.         case SIOCSIFADDR:
  541.         case SIOCSIFBRDADDR:
  542.         case SIOCSIFNETMASK:
  543. #if BYTE_ORDER != BIG_ENDIAN
  544.             if (ifr->ifr_addr.sa_family == 0 &&
  545.                 ifr->ifr_addr.sa_len < 16) {
  546.                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
  547.                 ifr->ifr_addr.sa_len = 16;
  548.             }
  549. #else
  550.             if (ifr->ifr_addr.sa_len == 0)
  551.                 ifr->ifr_addr.sa_len = 16;
  552. #endif
  553.             break;
  554.  
  555.         case OSIOCGIFADDR:
  556.             cmd = SIOCGIFADDR;
  557.             break;
  558.  
  559.         case OSIOCGIFDSTADDR:
  560.             cmd = SIOCGIFDSTADDR;
  561.             break;
  562.  
  563.         case OSIOCGIFBRDADDR:
  564.             cmd = SIOCGIFBRDADDR;
  565.             break;
  566.  
  567.         case OSIOCGIFNETMASK:
  568.             cmd = SIOCGIFNETMASK;
  569.         }
  570.         error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
  571.                                 cmd, data, ifp));
  572.         switch (ocmd) {
  573.  
  574.         case OSIOCGIFADDR:
  575.         case OSIOCGIFDSTADDR:
  576.         case OSIOCGIFBRDADDR:
  577.         case OSIOCGIFNETMASK:
  578.             *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
  579.         }
  580.         return (error);
  581.  
  582.         }
  583. #endif
  584.     }
  585.     return (0);
  586. }
  587.  
  588. /*
  589.  * Return interface configuration
  590.  * of system.  List may be used
  591.  * in later ioctl's (above) to get
  592.  * other information.
  593.  */
  594. /*ARGSUSED*/
  595. ifconf(cmd, data)
  596.     int cmd;
  597.     caddr_t data;
  598. {
  599.     register struct ifconf *ifc = (struct ifconf *)data;
  600.     register struct ifnet *ifp = ifnet;
  601.     register struct ifaddr *ifa;
  602.     register char *cp, *ep;
  603.     struct ifreq ifr, *ifrp;
  604.     int space = ifc->ifc_len, error = 0;
  605.  
  606.     ifrp = ifc->ifc_req;
  607.     ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
  608.     for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
  609.         bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
  610.         for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
  611.             ;
  612.         *cp++ = '0' + ifp->if_unit; *cp = '\0';
  613.         if ((ifa = ifp->if_addrlist) == 0) {
  614.             bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
  615.             error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
  616.             if (error)
  617.                 break;
  618.             space -= sizeof (ifr), ifrp++;
  619.         } else 
  620.             for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
  621.             register struct sockaddr *sa = ifa->ifa_addr;
  622. #ifdef COMPAT_43
  623.             if (cmd == OSIOCGIFCONF) {
  624.                 struct osockaddr *osa =
  625.                      (struct osockaddr *)&ifr.ifr_addr;
  626.                 ifr.ifr_addr = *sa;
  627.                 osa->sa_family = sa->sa_family;
  628.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  629.                         sizeof (ifr));
  630.                 ifrp++;
  631.             } else
  632. #endif
  633.             if (sa->sa_len <= sizeof(*sa)) {
  634.                 ifr.ifr_addr = *sa;
  635.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  636.                         sizeof (ifr));
  637.                 ifrp++;
  638.             } else {
  639.                 space -= sa->sa_len - sizeof(*sa);
  640.                 if (space < sizeof (ifr))
  641.                     break;
  642.                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  643.                         sizeof (ifr.ifr_name));
  644.                 if (error == 0)
  645.                     error = copyout((caddr_t)sa,
  646.                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
  647.                 ifrp = (struct ifreq *)
  648.                     (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
  649.             }
  650.             if (error)
  651.                 break;
  652.             space -= sizeof (ifr);
  653.         }
  654.     }
  655.     ifc->ifc_len -= space;
  656.     return (error);
  657. }
  658.  
  659. static char *
  660. sprint_d(n, buf, buflen)
  661.     u_int n;
  662.     char *buf;
  663.     int buflen;
  664. {
  665.     register char *cp = buf + buflen - 1;
  666.  
  667.     *cp = 0;
  668.     do {
  669.         cp--;
  670.         *cp = "0123456789"[n % 10];
  671.         n /= 10;
  672.     } while (n != 0);
  673.     return (cp);
  674. }
  675.