The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1980, 1986, 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  *      @(#)if.c        8.3 (Berkeley) 1/4/94
   34  * $FreeBSD$
   35  */
   36 
   37 #include "opt_compat.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/systm.h>
   43 #include <sys/proc.h>
   44 #include <sys/socket.h>
   45 #include <sys/socketvar.h>
   46 #include <sys/protosw.h>
   47 #include <sys/kernel.h>
   48 #include <sys/sockio.h>
   49 #include <sys/syslog.h>
   50 #include <sys/sysctl.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_dl.h>
   54 #include <net/radix.h>
   55 
   56 /*
   57  * System initialization
   58  */
   59 
   60 static int ifconf __P((u_long, caddr_t));
   61 static void ifinit __P((void *));
   62 static void if_qflush __P((struct ifqueue *));
   63 static void if_slowtimo __P((void *));
   64 static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
   65 
   66 SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)
   67 
   68 MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
   69 MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
   70 
   71 int     ifqmaxlen = IFQ_MAXLEN;
   72 struct  ifnethead ifnet;        /* depend on static init XXX */
   73 
   74 /*
   75  * Network interface utility routines.
   76  *
   77  * Routines with ifa_ifwith* names take sockaddr *'s as
   78  * parameters.
   79  *
   80  * This routine assumes that it will be called at splimp() or higher.
   81  */
   82 /* ARGSUSED*/
   83 void
   84 ifinit(dummy)
   85         void *dummy;
   86 {
   87         register struct ifnet *ifp;
   88 
   89         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
   90                 if (ifp->if_snd.ifq_maxlen == 0)
   91                         ifp->if_snd.ifq_maxlen = ifqmaxlen;
   92         if_slowtimo(0);
   93 }
   94 
   95 int if_index = 0;
   96 struct ifaddr **ifnet_addrs;
   97 
   98 
   99 /*
  100  * Attach an interface to the
  101  * list of "active" interfaces.
  102  */
  103 void
  104 if_attach(ifp)
  105         struct ifnet *ifp;
  106 {
  107         unsigned socksize, ifasize;
  108         int namelen, masklen;
  109         char workbuf[64];
  110         register struct sockaddr_dl *sdl;
  111         register struct ifaddr *ifa;
  112         static int if_indexlim = 8;
  113         static int inited;
  114 
  115         if (!inited) {
  116                 TAILQ_INIT(&ifnet);
  117                 inited = 1;
  118         }
  119 
  120         TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
  121         ifp->if_index = ++if_index;
  122         /*
  123          * XXX -
  124          * The old code would work if the interface passed a pre-existing
  125          * chain of ifaddrs to this code.  We don't trust our callers to
  126          * properly initialize the tailq, however, so we no longer allow
  127          * this unlikely case.
  128          */
  129         TAILQ_INIT(&ifp->if_addrhead);
  130         LIST_INIT(&ifp->if_multiaddrs);
  131         getmicrotime(&ifp->if_lastchange);
  132         if (ifnet_addrs == 0 || if_index >= if_indexlim) {
  133                 unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
  134                 struct ifaddr **q = (struct ifaddr **)
  135                                         malloc(n, M_IFADDR, M_WAITOK);
  136                 bzero((caddr_t)q, n);
  137                 if (ifnet_addrs) {
  138                         bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
  139                         free((caddr_t)ifnet_addrs, M_IFADDR);
  140                 }
  141                 ifnet_addrs = q;
  142         }
  143         /*
  144          * create a Link Level name for this device
  145          */
  146         namelen = snprintf(workbuf, sizeof(workbuf),
  147             "%s%d", ifp->if_name, ifp->if_unit);
  148 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
  149         masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
  150         socksize = masklen + ifp->if_addrlen;
  151 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  152         if (socksize < sizeof(*sdl))
  153                 socksize = sizeof(*sdl);
  154         socksize = ROUNDUP(socksize);
  155         ifasize = sizeof(*ifa) + 2 * socksize;
  156         ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
  157         if (ifa) {
  158                 bzero((caddr_t)ifa, ifasize);
  159                 sdl = (struct sockaddr_dl *)(ifa + 1);
  160                 sdl->sdl_len = socksize;
  161                 sdl->sdl_family = AF_LINK;
  162                 bcopy(workbuf, sdl->sdl_data, namelen);
  163                 sdl->sdl_nlen = namelen;
  164                 sdl->sdl_index = ifp->if_index;
  165                 sdl->sdl_type = ifp->if_type;
  166                 ifnet_addrs[if_index - 1] = ifa;
  167                 ifa->ifa_ifp = ifp;
  168                 ifa->ifa_rtrequest = link_rtrequest;
  169                 ifa->ifa_addr = (struct sockaddr *)sdl;
  170                 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  171                 ifa->ifa_netmask = (struct sockaddr *)sdl;
  172                 sdl->sdl_len = masklen;
  173                 while (namelen != 0)
  174                         sdl->sdl_data[--namelen] = 0xff;
  175                 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
  176         }
  177 }
  178 /*
  179  * Locate an interface based on a complete address.
  180  */
  181 /*ARGSUSED*/
  182 struct ifaddr *
  183 ifa_ifwithaddr(addr)
  184         register struct sockaddr *addr;
  185 {
  186         register struct ifnet *ifp;
  187         register struct ifaddr *ifa;
  188 
  189 #define equal(a1, a2) \
  190   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  191         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
  192             for (ifa = ifp->if_addrhead.tqh_first; ifa; 
  193                  ifa = ifa->ifa_link.tqe_next) {
  194                 if (ifa->ifa_addr->sa_family != addr->sa_family)
  195                         continue;
  196                 if (equal(addr, ifa->ifa_addr))
  197                         return (ifa);
  198                 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
  199                     equal(ifa->ifa_broadaddr, addr))
  200                         return (ifa);
  201         }
  202         return ((struct ifaddr *)0);
  203 }
  204 /*
  205  * Locate the point to point interface with a given destination address.
  206  */
  207 /*ARGSUSED*/
  208 struct ifaddr *
  209 ifa_ifwithdstaddr(addr)
  210         register struct sockaddr *addr;
  211 {
  212         register struct ifnet *ifp;
  213         register struct ifaddr *ifa;
  214 
  215         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
  216             if (ifp->if_flags & IFF_POINTOPOINT)
  217                 for (ifa = ifp->if_addrhead.tqh_first; ifa; 
  218                      ifa = ifa->ifa_link.tqe_next) {
  219                         if (ifa->ifa_addr->sa_family != addr->sa_family)
  220                                 continue;
  221                         if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
  222                                 return (ifa);
  223         }
  224         return ((struct ifaddr *)0);
  225 }
  226 
  227 /*
  228  * Find an interface on a specific network.  If many, choice
  229  * is most specific found.
  230  */
  231 struct ifaddr *
  232 ifa_ifwithnet(addr)
  233         struct sockaddr *addr;
  234 {
  235         register struct ifnet *ifp;
  236         register struct ifaddr *ifa;
  237         struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
  238         u_int af = addr->sa_family;
  239         char *addr_data = addr->sa_data, *cplim;
  240 
  241         /*
  242          * AF_LINK addresses can be looked up directly by their index number,
  243          * so do that if we can.
  244          */
  245         if (af == AF_LINK) {
  246             register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
  247             if (sdl->sdl_index && sdl->sdl_index <= if_index)
  248                 return (ifnet_addrs[sdl->sdl_index - 1]);
  249         }
  250 
  251         /* 
  252          * Scan though each interface, looking for ones that have
  253          * addresses in this address family.
  254          */
  255         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
  256                 for (ifa = ifp->if_addrhead.tqh_first; ifa;
  257                      ifa = ifa->ifa_link.tqe_next) {
  258                         register char *cp, *cp2, *cp3;
  259 
  260                         if (ifa->ifa_addr->sa_family != af)
  261 next:                           continue;
  262                         if (ifp->if_flags & IFF_POINTOPOINT) {
  263                                 /*
  264                                  * This is a bit broken as it doesn't 
  265                                  * take into account that the remote end may 
  266                                  * be a single node in the network we are
  267                                  * looking for.
  268                                  * The trouble is that we don't know the 
  269                                  * netmask for the remote end.
  270                                  */
  271                                 if (ifa->ifa_dstaddr != 0
  272                                     && equal(addr, ifa->ifa_dstaddr))
  273                                         return (ifa);
  274                         } else {
  275                                 /*
  276                                  * if we have a special address handler,
  277                                  * then use it instead of the generic one.
  278                                  */
  279                                 if (ifa->ifa_claim_addr) {
  280                                         if ((*ifa->ifa_claim_addr)(ifa, addr)) {
  281                                                 return (ifa);
  282                                         } else {
  283                                                 continue;
  284                                         }
  285                                 }
  286 
  287                                 /*
  288                                  * Scan all the bits in the ifa's address.
  289                                  * If a bit dissagrees with what we are
  290                                  * looking for, mask it with the netmask
  291                                  * to see if it really matters.
  292                                  * (A byte at a time)
  293                                  */
  294                                 if (ifa->ifa_netmask == 0)
  295                                         continue;
  296                                 cp = addr_data;
  297                                 cp2 = ifa->ifa_addr->sa_data;
  298                                 cp3 = ifa->ifa_netmask->sa_data;
  299                                 cplim = ifa->ifa_netmask->sa_len
  300                                         + (char *)ifa->ifa_netmask;
  301                                 while (cp3 < cplim)
  302                                         if ((*cp++ ^ *cp2++) & *cp3++)
  303                                                 goto next; /* next address! */
  304                                 /*
  305                                  * If the netmask of what we just found
  306                                  * is more specific than what we had before
  307                                  * (if we had one) then remember the new one
  308                                  * before continuing to search
  309                                  * for an even better one.
  310                                  */
  311                                 if (ifa_maybe == 0 ||
  312                                     rn_refines((caddr_t)ifa->ifa_netmask,
  313                                     (caddr_t)ifa_maybe->ifa_netmask))
  314                                         ifa_maybe = ifa;
  315                         }
  316                 }
  317         }
  318         return (ifa_maybe);
  319 }
  320 
  321 /*
  322  * Find an interface address specific to an interface best matching
  323  * a given address.
  324  */
  325 struct ifaddr *
  326 ifaof_ifpforaddr(addr, ifp)
  327         struct sockaddr *addr;
  328         register struct ifnet *ifp;
  329 {
  330         register struct ifaddr *ifa;
  331         register char *cp, *cp2, *cp3;
  332         register char *cplim;
  333         struct ifaddr *ifa_maybe = 0;
  334         u_int af = addr->sa_family;
  335 
  336         if (af >= AF_MAX)
  337                 return (0);
  338         for (ifa = ifp->if_addrhead.tqh_first; ifa; 
  339              ifa = ifa->ifa_link.tqe_next) {
  340                 if (ifa->ifa_addr->sa_family != af)
  341                         continue;
  342                 if (ifa_maybe == 0)
  343                         ifa_maybe = ifa;
  344                 if (ifa->ifa_netmask == 0) {
  345                         if (equal(addr, ifa->ifa_addr) ||
  346                             (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
  347                                 return (ifa);
  348                         continue;
  349                 }
  350                 if (ifp->if_flags & IFF_POINTOPOINT) {
  351                         if (equal(addr, ifa->ifa_dstaddr))
  352                                 return (ifa);
  353                 } else {
  354                         cp = addr->sa_data;
  355                         cp2 = ifa->ifa_addr->sa_data;
  356                         cp3 = ifa->ifa_netmask->sa_data;
  357                         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  358                         for (; cp3 < cplim; cp3++)
  359                                 if ((*cp++ ^ *cp2++) & *cp3)
  360                                         break;
  361                         if (cp3 == cplim)
  362                                 return (ifa);
  363                 }
  364         }
  365         return (ifa_maybe);
  366 }
  367 
  368 #include <net/route.h>
  369 
  370 /*
  371  * Default action when installing a route with a Link Level gateway.
  372  * Lookup an appropriate real ifa to point to.
  373  * This should be moved to /sys/net/link.c eventually.
  374  */
  375 static void
  376 link_rtrequest(cmd, rt, sa)
  377         int cmd;
  378         register struct rtentry *rt;
  379         struct sockaddr *sa;
  380 {
  381         register struct ifaddr *ifa;
  382         struct sockaddr *dst;
  383         struct ifnet *ifp;
  384 
  385         if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
  386             ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
  387                 return;
  388         ifa = ifaof_ifpforaddr(dst, ifp);
  389         if (ifa) {
  390                 IFAFREE(rt->rt_ifa);
  391                 rt->rt_ifa = ifa;
  392                 ifa->ifa_refcnt++;
  393                 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
  394                         ifa->ifa_rtrequest(cmd, rt, sa);
  395         }
  396 }
  397 
  398 /*
  399  * Mark an interface down and notify protocols of
  400  * the transition.
  401  * NOTE: must be called at splnet or eqivalent.
  402  */
  403 void
  404 if_unroute(ifp, flag, fam)
  405         register struct ifnet *ifp;
  406         int flag, fam;
  407 {
  408         register struct ifaddr *ifa;
  409 
  410         ifp->if_flags &= ~flag;
  411         getmicrotime(&ifp->if_lastchange);
  412         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  413                 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
  414                         pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
  415         if_qflush(&ifp->if_snd);
  416         rt_ifmsg(ifp);
  417 }
  418 
  419 /*
  420  * Mark an interface up and notify protocols of
  421  * the transition.
  422  * NOTE: must be called at splnet or eqivalent.
  423  */
  424 void
  425 if_route(ifp, flag, fam)
  426         register struct ifnet *ifp;
  427         int flag, fam;
  428 {
  429         register struct ifaddr *ifa;
  430 
  431         ifp->if_flags |= flag;
  432         getmicrotime(&ifp->if_lastchange);
  433         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  434                 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
  435                         pfctlinput(PRC_IFUP, ifa->ifa_addr);
  436         rt_ifmsg(ifp);
  437 }
  438 
  439 /*
  440  * Mark an interface down and notify protocols of
  441  * the transition.
  442  * NOTE: must be called at splnet or eqivalent.
  443  */
  444 void
  445 if_down(ifp)
  446         register struct ifnet *ifp;
  447 {
  448 
  449         if_unroute(ifp, IFF_UP, AF_UNSPEC);
  450 }
  451 
  452 /*
  453  * Mark an interface up and notify protocols of
  454  * the transition.
  455  * NOTE: must be called at splnet or eqivalent.
  456  */
  457 void
  458 if_up(ifp)
  459         register struct ifnet *ifp;
  460 {
  461 
  462         if_route(ifp, IFF_UP, AF_UNSPEC);
  463 }
  464 
  465 /*
  466  * Flush an interface queue.
  467  */
  468 static void
  469 if_qflush(ifq)
  470         register struct ifqueue *ifq;
  471 {
  472         register struct mbuf *m, *n;
  473 
  474         n = ifq->ifq_head;
  475         while ((m = n) != 0) {
  476                 n = m->m_act;
  477                 m_freem(m);
  478         }
  479         ifq->ifq_head = 0;
  480         ifq->ifq_tail = 0;
  481         ifq->ifq_len = 0;
  482 }
  483 
  484 /*
  485  * Handle interface watchdog timer routines.  Called
  486  * from softclock, we decrement timers (if set) and
  487  * call the appropriate interface routine on expiration.
  488  */
  489 static void
  490 if_slowtimo(arg)
  491         void *arg;
  492 {
  493         register struct ifnet *ifp;
  494         int s = splimp();
  495 
  496         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
  497                 if (ifp->if_timer == 0 || --ifp->if_timer)
  498                         continue;
  499                 if (ifp->if_watchdog)
  500                         (*ifp->if_watchdog)(ifp);
  501         }
  502         splx(s);
  503         timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
  504 }
  505 
  506 /*
  507  * Map interface name to
  508  * interface structure pointer.
  509  */
  510 struct ifnet *
  511 ifunit(name)
  512         register char *name;
  513 {
  514         char namebuf[IFNAMSIZ + 1];
  515         register char *cp, *cp2;
  516         char *end;
  517         register struct ifnet *ifp;
  518         int unit;
  519         unsigned len;
  520         register char c = '\0';
  521 
  522         /*
  523          * Look for a non numeric part
  524          */
  525         end = name + IFNAMSIZ; 
  526         cp2 = namebuf;
  527         cp = name; 
  528         while ((cp < end) && (c = *cp)) {
  529                 if (c >= '' && c <= '9')
  530                         break;
  531                 *cp2++ = c;
  532                 cp++;
  533         }
  534         if ((cp == end) || (c == '\0') || (cp == name))
  535                 return ((struct ifnet *)0);
  536         *cp2 = '\0';
  537         /*
  538          * check we have a legal number (limit to 7 digits?)
  539          */
  540         len = cp - name + 1;
  541         for (unit = 0;
  542             ((c = *cp) >= '') && (c <= '9') && (unit < 1000000); cp++ ) 
  543                 unit = (unit * 10) + (c - '');
  544         if (*cp != '\0')
  545                 return 0;       /* no trailing garbage allowed */
  546         /*
  547          * Now search all the interfaces for this name/number
  548          */
  549         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
  550                 if (bcmp(ifp->if_name, namebuf, len))
  551                         continue;
  552                 if (unit == ifp->if_unit)
  553                         break;
  554         }
  555         return (ifp);
  556 }
  557 
  558 /*
  559  * Interface ioctls.
  560  */
  561 int
  562 ifioctl(so, cmd, data, p)
  563         struct socket *so;
  564         u_long cmd;
  565         caddr_t data;
  566         struct proc *p;
  567 {
  568         register struct ifnet *ifp;
  569         register struct ifreq *ifr;
  570         int error;
  571 
  572         switch (cmd) {
  573 
  574         case SIOCGIFCONF:
  575         case OSIOCGIFCONF:
  576                 return (ifconf(cmd, data));
  577         }
  578         ifr = (struct ifreq *)data;
  579         ifp = ifunit(ifr->ifr_name);
  580         if (ifp == 0)
  581                 return (ENXIO);
  582         switch (cmd) {
  583 
  584         case SIOCGIFFLAGS:
  585                 ifr->ifr_flags = ifp->if_flags;
  586                 break;
  587 
  588         case SIOCGIFMETRIC:
  589                 ifr->ifr_metric = ifp->if_metric;
  590                 break;
  591 
  592         case SIOCGIFMTU:
  593                 ifr->ifr_mtu = ifp->if_mtu;
  594                 break;
  595 
  596         case SIOCGIFPHYS:
  597                 ifr->ifr_phys = ifp->if_physical;
  598                 break;
  599 
  600         case SIOCSIFFLAGS:
  601                 error = suser(p->p_ucred, &p->p_acflag);
  602                 if (error)
  603                         return (error);
  604                 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
  605                         int s = splimp();
  606                         if_down(ifp);
  607                         splx(s);
  608                 }
  609                 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
  610                         int s = splimp();
  611                         if_up(ifp);
  612                         splx(s);
  613                 }
  614                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
  615                         (ifr->ifr_flags &~ IFF_CANTCHANGE);
  616                 if (ifp->if_ioctl)
  617                         (void) (*ifp->if_ioctl)(ifp, cmd, data);
  618                 getmicrotime(&ifp->if_lastchange);
  619                 break;
  620 
  621         case SIOCSIFMETRIC:
  622                 error = suser(p->p_ucred, &p->p_acflag);
  623                 if (error)
  624                         return (error);
  625                 ifp->if_metric = ifr->ifr_metric;
  626                 getmicrotime(&ifp->if_lastchange);
  627                 break;
  628 
  629         case SIOCSIFPHYS:
  630                 error = suser(p->p_ucred, &p->p_acflag);
  631                 if (error)
  632                         return error;
  633                 if (!ifp->if_ioctl)
  634                         return EOPNOTSUPP;
  635                 error = (*ifp->if_ioctl)(ifp, cmd, data);
  636                 if (error == 0)
  637                         getmicrotime(&ifp->if_lastchange);
  638                 return(error);
  639 
  640         case SIOCSIFMTU:
  641                 error = suser(p->p_ucred, &p->p_acflag);
  642                 if (error)
  643                         return (error);
  644                 if (ifp->if_ioctl == NULL)
  645                         return (EOPNOTSUPP);
  646                 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
  647                         return (EINVAL);
  648                 error = (*ifp->if_ioctl)(ifp, cmd, data);
  649                 if (error == 0) {
  650                         getmicrotime(&ifp->if_lastchange);
  651                         rt_ifmsg(ifp);
  652                 }
  653                 return(error);
  654 
  655         case SIOCADDMULTI:
  656         case SIOCDELMULTI:
  657                 error = suser(p->p_ucred, &p->p_acflag);
  658                 if (error)
  659                         return (error);
  660 
  661                 /* Don't allow group membership on non-multicast interfaces. */
  662                 if ((ifp->if_flags & IFF_MULTICAST) == 0)
  663                         return EOPNOTSUPP;
  664 
  665                 /* Don't let users screw up protocols' entries. */
  666                 if (ifr->ifr_addr.sa_family != AF_LINK)
  667                         return EINVAL;
  668 
  669                 if (cmd == SIOCADDMULTI) {
  670                         struct ifmultiaddr *ifma;
  671                         error = if_addmulti(ifp, &ifr->ifr_addr, &ifma);
  672                 } else {
  673                         error = if_delmulti(ifp, &ifr->ifr_addr);
  674                 }
  675                 if (error == 0)
  676                         getmicrotime(&ifp->if_lastchange);
  677                 return error;
  678 
  679         case SIOCSIFMEDIA:
  680         case SIOCSIFGENERIC:
  681                 error = suser(p->p_ucred, &p->p_acflag);
  682                 if (error)
  683                         return (error);
  684                 if (ifp->if_ioctl == 0)
  685                         return (EOPNOTSUPP);
  686                 error = (*ifp->if_ioctl)(ifp, cmd, data);
  687                 if (error == 0)
  688                         getmicrotime(&ifp->if_lastchange);
  689                 return error;
  690 
  691         case SIOCGIFMEDIA:
  692         case SIOCGIFGENERIC:
  693                 if (ifp->if_ioctl == 0)
  694                         return (EOPNOTSUPP);
  695                 return ((*ifp->if_ioctl)(ifp, cmd, data));
  696 
  697         default:
  698                 if (so->so_proto == 0)
  699                         return (EOPNOTSUPP);
  700 #ifndef COMPAT_43
  701                 return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
  702                                                                  data,
  703                                                                  ifp, p));
  704 #else
  705             {
  706                 int ocmd = cmd;
  707 
  708                 switch (cmd) {
  709 
  710                 case SIOCSIFDSTADDR:
  711                 case SIOCSIFADDR:
  712                 case SIOCSIFBRDADDR:
  713                 case SIOCSIFNETMASK:
  714 #if BYTE_ORDER != BIG_ENDIAN
  715                         if (ifr->ifr_addr.sa_family == 0 &&
  716                             ifr->ifr_addr.sa_len < 16) {
  717                                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
  718                                 ifr->ifr_addr.sa_len = 16;
  719                         }
  720 #else
  721                         if (ifr->ifr_addr.sa_len == 0)
  722                                 ifr->ifr_addr.sa_len = 16;
  723 #endif
  724                         break;
  725 
  726                 case OSIOCGIFADDR:
  727                         cmd = SIOCGIFADDR;
  728                         break;
  729 
  730                 case OSIOCGIFDSTADDR:
  731                         cmd = SIOCGIFDSTADDR;
  732                         break;
  733 
  734                 case OSIOCGIFBRDADDR:
  735                         cmd = SIOCGIFBRDADDR;
  736                         break;
  737 
  738                 case OSIOCGIFNETMASK:
  739                         cmd = SIOCGIFNETMASK;
  740                 }
  741                 error =  ((*so->so_proto->pr_usrreqs->pru_control)(so,
  742                                                                    cmd,
  743                                                                    data,
  744                                                                    ifp, p));
  745                 switch (ocmd) {
  746 
  747                 case OSIOCGIFADDR:
  748                 case OSIOCGIFDSTADDR:
  749                 case OSIOCGIFBRDADDR:
  750                 case OSIOCGIFNETMASK:
  751                         *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
  752                 }
  753                 return (error);
  754 
  755             }
  756 #endif
  757         }
  758         return (0);
  759 }
  760 
  761 /*
  762  * Set/clear promiscuous mode on interface ifp based on the truth value
  763  * of pswitch.  The calls are reference counted so that only the first
  764  * "on" request actually has an effect, as does the final "off" request.
  765  * Results are undefined if the "off" and "on" requests are not matched.
  766  */
  767 int
  768 ifpromisc(ifp, pswitch)
  769         struct ifnet *ifp;
  770         int pswitch;
  771 {
  772         struct ifreq ifr;
  773         int error;
  774 
  775         if (pswitch) {
  776                 /*
  777                  * If the device is not configured up, we cannot put it in
  778                  * promiscuous mode.
  779                  */
  780                 if ((ifp->if_flags & IFF_UP) == 0)
  781                         return (ENETDOWN);
  782                 if (ifp->if_pcount++ != 0)
  783                         return (0);
  784                 ifp->if_flags |= IFF_PROMISC;
  785                 log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
  786                     ifp->if_name, ifp->if_unit);
  787         } else {
  788                 if (--ifp->if_pcount > 0)
  789                         return (0);
  790                 ifp->if_flags &= ~IFF_PROMISC;
  791                 log(LOG_INFO, "%s%d: promiscuous mode disabled\n",
  792                     ifp->if_name, ifp->if_unit);
  793         }
  794         ifr.ifr_flags = ifp->if_flags;
  795         error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
  796         if (error == 0)
  797                 rt_ifmsg(ifp);
  798         return error;
  799 }
  800 
  801 /*
  802  * Return interface configuration
  803  * of system.  List may be used
  804  * in later ioctl's (above) to get
  805  * other information.
  806  */
  807 /*ARGSUSED*/
  808 static int
  809 ifconf(cmd, data)
  810         u_long cmd;
  811         caddr_t data;
  812 {
  813         register struct ifconf *ifc = (struct ifconf *)data;
  814         register struct ifnet *ifp = ifnet.tqh_first;
  815         register struct ifaddr *ifa;
  816         struct ifreq ifr, *ifrp;
  817         int space = ifc->ifc_len, error = 0;
  818 
  819         ifrp = ifc->ifc_req;
  820         for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) {
  821                 char workbuf[64];
  822                 int ifnlen;
  823 
  824                 ifnlen = snprintf(workbuf, sizeof(workbuf),
  825                     "%s%d", ifp->if_name, ifp->if_unit);
  826                 if(ifnlen + 1 > sizeof ifr.ifr_name) {
  827                         error = ENAMETOOLONG;
  828                         break;
  829                 } else {
  830                         strcpy(ifr.ifr_name, workbuf);
  831                 }
  832 
  833                 if ((ifa = ifp->if_addrhead.tqh_first) == 0) {
  834                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
  835                         error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  836                             sizeof (ifr));
  837                         if (error)
  838                                 break;
  839                         space -= sizeof (ifr), ifrp++;
  840                 } else
  841                     for ( ; space > sizeof (ifr) && ifa; 
  842                          ifa = ifa->ifa_link.tqe_next) {
  843                         register struct sockaddr *sa = ifa->ifa_addr;
  844 #ifdef COMPAT_43
  845                         if (cmd == OSIOCGIFCONF) {
  846                                 struct osockaddr *osa =
  847                                          (struct osockaddr *)&ifr.ifr_addr;
  848                                 ifr.ifr_addr = *sa;
  849                                 osa->sa_family = sa->sa_family;
  850                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  851                                                 sizeof (ifr));
  852                                 ifrp++;
  853                         } else
  854 #endif
  855                         if (sa->sa_len <= sizeof(*sa)) {
  856                                 ifr.ifr_addr = *sa;
  857                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  858                                                 sizeof (ifr));
  859                                 ifrp++;
  860                         } else {
  861                                 if (space < sizeof (ifr) + sa->sa_len -
  862                                             sizeof(*sa))
  863                                         break;
  864                                 space -= sa->sa_len - sizeof(*sa);
  865 
  866                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
  867                                                 sizeof (ifr.ifr_name));
  868                                 if (error == 0)
  869                                     error = copyout((caddr_t)sa,
  870                                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
  871                                 ifrp = (struct ifreq *)
  872                                         (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
  873                         }
  874                         if (error)
  875                                 break;
  876                         space -= sizeof (ifr);
  877                 }
  878         }
  879         ifc->ifc_len -= space;
  880         return (error);
  881 }
  882 
  883 /*
  884  * Just like if_promisc(), but for all-multicast-reception mode.
  885  */
  886 int
  887 if_allmulti(ifp, onswitch)
  888         struct ifnet *ifp;
  889         int onswitch;
  890 {
  891         int error = 0;
  892         int s = splimp();
  893 
  894         if (onswitch) {
  895                 if (ifp->if_amcount++ == 0) {
  896                         ifp->if_flags |= IFF_ALLMULTI;
  897                         error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0);
  898                 }
  899         } else {
  900                 if (ifp->if_amcount > 1) {
  901                         ifp->if_amcount--;
  902                 } else {
  903                         ifp->if_amcount = 0;
  904                         ifp->if_flags &= ~IFF_ALLMULTI;
  905                         error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0);
  906                 }
  907         }
  908         splx(s);
  909 
  910         if (error == 0)
  911                 rt_ifmsg(ifp);
  912         return error;
  913 }
  914 
  915 /*
  916  * Add a multicast listenership to the interface in question.
  917  * The link layer provides a routine which converts 
  918  */
  919 int
  920 if_addmulti(ifp, sa, retifma)
  921         struct ifnet *ifp;      /* interface to manipulate */
  922         struct sockaddr *sa;    /* address to add */
  923         struct ifmultiaddr **retifma;
  924 {
  925         struct sockaddr *llsa, *dupsa;
  926         int error, s;
  927         struct ifmultiaddr *ifma;
  928 
  929         /*
  930          * If the matching multicast address already exists
  931          * then don't add a new one, just add a reference
  932          */
  933         for (ifma = ifp->if_multiaddrs.lh_first; ifma; 
  934              ifma = ifma->ifma_link.le_next) {
  935                 if (equal(sa, ifma->ifma_addr)) {
  936                         ifma->ifma_refcount++;
  937                         if (retifma)
  938                                 *retifma = ifma;
  939                         return 0;
  940                 }
  941         }
  942 
  943         /*
  944          * Give the link layer a chance to accept/reject it, and also
  945          * find out which AF_LINK address this maps to, if it isn't one
  946          * already.
  947          */
  948         if (ifp->if_resolvemulti) {
  949                 error = ifp->if_resolvemulti(ifp, &llsa, sa);
  950                 if (error) return error;
  951         } else {
  952                 llsa = 0;
  953         }
  954 
  955         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
  956         MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
  957         bcopy(sa, dupsa, sa->sa_len);
  958 
  959         ifma->ifma_addr = dupsa;
  960         ifma->ifma_lladdr = llsa;
  961         ifma->ifma_ifp = ifp;
  962         ifma->ifma_refcount = 1;
  963         ifma->ifma_protospec = 0;
  964         rt_newmaddrmsg(RTM_NEWMADDR, ifma);
  965 
  966         /*
  967          * Some network interfaces can scan the address list at
  968          * interrupt time; lock them out.
  969          */
  970         s = splimp();
  971         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
  972         splx(s);
  973         *retifma = ifma;
  974 
  975         if (llsa != 0) {
  976                 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
  977                      ifma = ifma->ifma_link.le_next) {
  978                         if (equal(ifma->ifma_addr, llsa))
  979                                 break;
  980                 }
  981                 if (ifma) {
  982                         ifma->ifma_refcount++;
  983                 } else {
  984                         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
  985                                M_IFMADDR, M_WAITOK);
  986                         MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
  987                                M_IFMADDR, M_WAITOK);
  988                         bcopy(llsa, dupsa, llsa->sa_len);
  989                         ifma->ifma_addr = dupsa;
  990                         ifma->ifma_ifp = ifp;
  991                         ifma->ifma_refcount = 1;
  992                         s = splimp();
  993                         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
  994                         splx(s);
  995                 }
  996         }
  997         /*
  998          * We are certain we have added something, so call down to the
  999          * interface to let them know about it.
 1000          */
 1001         s = splimp();
 1002         ifp->if_ioctl(ifp, SIOCADDMULTI, 0);
 1003         splx(s);
 1004 
 1005         return 0;
 1006 }
 1007 
 1008 /*
 1009  * Remove a reference to a multicast address on this interface.  Yell
 1010  * if the request does not match an existing membership.
 1011  */
 1012 int
 1013 if_delmulti(ifp, sa)
 1014         struct ifnet *ifp;
 1015         struct sockaddr *sa;
 1016 {
 1017         struct ifmultiaddr *ifma;
 1018         int s;
 1019 
 1020         for (ifma = ifp->if_multiaddrs.lh_first; ifma; 
 1021              ifma = ifma->ifma_link.le_next)
 1022                 if (equal(sa, ifma->ifma_addr))
 1023                         break;
 1024         if (ifma == 0)
 1025                 return ENOENT;
 1026 
 1027         if (ifma->ifma_refcount > 1) {
 1028                 ifma->ifma_refcount--;
 1029                 return 0;
 1030         }
 1031 
 1032         rt_newmaddrmsg(RTM_DELMADDR, ifma);
 1033         sa = ifma->ifma_lladdr;
 1034         s = splimp();
 1035         LIST_REMOVE(ifma, ifma_link);
 1036         splx(s);
 1037         free(ifma->ifma_addr, M_IFMADDR);
 1038         free(ifma, M_IFMADDR);
 1039         if (sa == 0)
 1040                 return 0;
 1041 
 1042         /*
 1043          * Now look for the link-layer address which corresponds to
 1044          * this network address.  It had been squirreled away in
 1045          * ifma->ifma_lladdr for this purpose (so we don't have
 1046          * to call ifp->if_resolvemulti() again), and we saved that
 1047          * value in sa above.  If some nasty deleted the
 1048          * link-layer address out from underneath us, we can deal because
 1049          * the address we stored was is not the same as the one which was
 1050          * in the record for the link-layer address.  (So we don't complain
 1051          * in that case.)
 1052          */
 1053         for (ifma = ifp->if_multiaddrs.lh_first; ifma; 
 1054              ifma = ifma->ifma_link.le_next)
 1055                 if (equal(sa, ifma->ifma_addr))
 1056                         break;
 1057         if (ifma == 0)
 1058                 return 0;
 1059 
 1060         if (ifma->ifma_refcount > 1) {
 1061                 ifma->ifma_refcount--;
 1062                 return 0;
 1063         }
 1064 
 1065         s = splimp();
 1066         LIST_REMOVE(ifma, ifma_link);
 1067         ifp->if_ioctl(ifp, SIOCDELMULTI, 0);
 1068         splx(s);
 1069         free(ifma->ifma_addr, M_IFMADDR);
 1070         free(sa, M_IFMADDR);
 1071         free(ifma, M_IFMADDR);
 1072 
 1073         return 0;
 1074 }
 1075 
 1076 struct ifmultiaddr *
 1077 ifmaof_ifpforaddr(sa, ifp)
 1078         struct sockaddr *sa;
 1079         struct ifnet *ifp;
 1080 {
 1081         struct ifmultiaddr *ifma;
 1082         
 1083         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
 1084              ifma = ifma->ifma_link.le_next)
 1085                 if (equal(ifma->ifma_addr, sa))
 1086                         break;
 1087 
 1088         return ifma;
 1089 }
 1090 
 1091 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
 1092 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");

Cache object: e07216d19a46e24a92b94beebde6ce05


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.