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/bsd/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) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * Copyright (c) 1980, 1986, 1993
   27  *      The Regents of the University of California.  All rights reserved.
   28  *
   29  * Redistribution and use in source and binary forms, with or without
   30  * modification, are permitted provided that the following conditions
   31  * are met:
   32  * 1. Redistributions of source code must retain the above copyright
   33  *    notice, this list of conditions and the following disclaimer.
   34  * 2. Redistributions in binary form must reproduce the above copyright
   35  *    notice, this list of conditions and the following disclaimer in the
   36  *    documentation and/or other materials provided with the distribution.
   37  * 3. All advertising materials mentioning features or use of this software
   38  *    must display the following acknowledgement:
   39  *      This product includes software developed by the University of
   40  *      California, Berkeley and its contributors.
   41  * 4. Neither the name of the University nor the names of its contributors
   42  *    may be used to endorse or promote products derived from this software
   43  *    without specific prior written permission.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   55  * SUCH DAMAGE.
   56  *
   57  *      @(#)if.c        8.3 (Berkeley) 1/4/94
   58  * $FreeBSD: src/sys/net/if.c,v 1.85.2.9 2001/07/24 19:10:17 brooks Exp $
   59  */
   60 
   61 #include <sys/param.h>
   62 #include <sys/malloc.h>
   63 #include <sys/mbuf.h>
   64 #include <sys/systm.h>
   65 #include <sys/proc.h>
   66 #include <sys/socket.h>
   67 #include <sys/socketvar.h>
   68 #include <sys/protosw.h>
   69 #include <sys/kernel.h>
   70 #include <sys/sockio.h>
   71 #include <sys/syslog.h>
   72 #include <sys/sysctl.h>
   73 
   74 #include <net/if.h>
   75 #include <net/if_arp.h>
   76 #include <net/if_dl.h>
   77 #include <net/if_types.h>
   78 #include <net/if_var.h>
   79 #include <net/radix.h>
   80 #include <net/route.h>
   81 #ifdef __APPLE__
   82 #include <net/dlil.h>
   83 //#include <string.h>
   84 #include <sys/domain.h>
   85 #endif
   86 
   87 #if defined(INET) || defined(INET6)
   88 /*XXX*/
   89 #include <netinet/in.h>
   90 #include <netinet/in_var.h>
   91 #if INET6
   92 #include <netinet6/in6_var.h>
   93 #include <netinet6/in6_ifattach.h>
   94 #endif
   95 #endif
   96 
   97 /*
   98  * System initialization
   99  */
  100 
  101 static int ifconf __P((u_long, caddr_t));
  102 static void if_qflush __P((struct ifqueue *));
  103 static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
  104 
  105 MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
  106 MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
  107 
  108 int     ifqmaxlen = IFQ_MAXLEN;
  109 struct  ifnethead ifnet;        /* depend on static init XXX */
  110 struct ifmultihead ifma_lostlist = LIST_HEAD_INITIALIZER(ifma_lostlist);
  111 
  112 #if INET6
  113 /*
  114  * XXX: declare here to avoid to include many inet6 related files..
  115  * should be more generalized?
  116  */
  117 extern void     nd6_setmtu __P((struct ifnet *));
  118 #endif
  119 
  120 /*
  121  * Network interface utility routines.
  122  *
  123  * Routines with ifa_ifwith* names take sockaddr *'s as
  124  * parameters.
  125  */
  126 
  127 int if_index = 0;
  128 struct ifaddr **ifnet_addrs;
  129 struct ifnet **ifindex2ifnet = NULL;
  130 
  131 
  132 /*
  133  * Attach an interface to the
  134  * list of "active" interfaces.
  135  */
  136 void
  137 old_if_attach(ifp)
  138         struct ifnet *ifp;
  139 {
  140         unsigned socksize, ifasize;
  141         int namelen, masklen;
  142         char workbuf[64];
  143         register struct sockaddr_dl *sdl;
  144         register struct ifaddr *ifa;
  145         static int if_indexlim = 8;
  146         static int inited;
  147 
  148         if (ifp->if_snd.ifq_maxlen == 0)
  149             ifp->if_snd.ifq_maxlen = ifqmaxlen;
  150 
  151         if (!inited) {
  152                 TAILQ_INIT(&ifnet);
  153                 inited = 1;
  154         }
  155 
  156         TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
  157         /* if the interface is recycled, keep the index */
  158         if (!((ifp->if_eflags & IFEF_REUSE) && ifp->if_index))
  159           ifp->if_index = ++if_index;
  160         /*
  161          * XXX -
  162          * The old code would work if the interface passed a pre-existing
  163          * chain of ifaddrs to this code.  We don't trust our callers to
  164          * properly initialize the tailq, however, so we no longer allow
  165          * this unlikely case.
  166          */
  167         TAILQ_INIT(&ifp->if_addrhead);
  168         TAILQ_INIT(&ifp->if_prefixhead);
  169         LIST_INIT(&ifp->if_multiaddrs);
  170         getmicrotime(&ifp->if_lastchange);
  171         if (ifnet_addrs == 0 || if_index >= if_indexlim) {
  172                 unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
  173                 struct ifaddr **q = (struct ifaddr **)
  174                                         _MALLOC(n, M_IFADDR, M_WAITOK);
  175                 bzero((caddr_t)q, n);
  176                 if (ifnet_addrs) {
  177                         bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
  178                         FREE((caddr_t)ifnet_addrs, M_IFADDR);
  179                 }
  180                 ifnet_addrs = (struct ifaddr **)q;
  181 
  182                 /* grow ifindex2ifnet */
  183                 n = if_indexlim * sizeof(struct ifaddr *);
  184                 q = (struct ifaddr **)_MALLOC(n, M_IFADDR, M_WAITOK);
  185                 bzero(q, n);
  186                 if (ifindex2ifnet) {
  187                         bcopy((caddr_t)ifindex2ifnet, q, n/2);
  188                         _FREE((caddr_t)ifindex2ifnet, M_IFADDR);
  189                 }
  190                 ifindex2ifnet = (struct ifnet **)q;
  191         }
  192 
  193         ifindex2ifnet[if_index] = ifp;
  194 
  195         /*
  196          * create a Link Level name for this device
  197          */
  198         namelen = snprintf(workbuf, sizeof(workbuf),
  199             "%s%d", ifp->if_name, ifp->if_unit);
  200 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
  201         masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
  202         socksize = masklen + ifp->if_addrlen;
  203 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  204         if (socksize < sizeof(*sdl))
  205                 socksize = sizeof(*sdl);
  206         socksize = ROUNDUP(socksize);
  207         ifasize = sizeof(*ifa) + 2 * socksize;
  208         ifa = (struct ifaddr *) _MALLOC(ifasize, M_IFADDR, M_WAITOK);
  209         if (ifa) {
  210                 bzero((caddr_t)ifa, ifasize);
  211                 sdl = (struct sockaddr_dl *)(ifa + 1);
  212                 sdl->sdl_len = socksize;
  213                 sdl->sdl_family = AF_LINK;
  214                 bcopy(workbuf, sdl->sdl_data, namelen);
  215                 sdl->sdl_nlen = namelen;
  216                 sdl->sdl_index = ifp->if_index;
  217                 sdl->sdl_type = ifp->if_type;
  218                 ifnet_addrs[if_index - 1] = ifa;
  219                 ifa->ifa_ifp = ifp;
  220                 ifa->ifa_rtrequest = link_rtrequest;
  221                 ifa->ifa_addr = (struct sockaddr *)sdl;
  222                 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  223                 ifa->ifa_netmask = (struct sockaddr *)sdl;
  224                 sdl->sdl_len = masklen;
  225                 while (namelen != 0)
  226                         sdl->sdl_data[--namelen] = 0xff;
  227                 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
  228         }
  229 }
  230 
  231 __private_extern__ int
  232 ifa_foraddr(addr)
  233         unsigned int addr;
  234 {
  235         register struct ifnet *ifp;
  236         register struct ifaddr *ifa;
  237         register unsigned int addr2;
  238         
  239 
  240         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
  241             for (ifa = ifp->if_addrhead.tqh_first; ifa;
  242                  ifa = ifa->ifa_link.tqe_next) {
  243                 if (ifa->ifa_addr->sa_family != AF_INET)
  244                         continue;
  245                 addr2 = IA_SIN(ifa)->sin_addr.s_addr;
  246 
  247                 if (addr == addr2)
  248                         return (1);
  249         }
  250         return (0);
  251 }
  252 
  253 /*
  254  * Locate an interface based on a complete address.
  255  */
  256 /*ARGSUSED*/
  257 struct ifaddr *
  258 ifa_ifwithaddr(addr)
  259         register struct sockaddr *addr;
  260 {
  261         register struct ifnet *ifp;
  262         register struct ifaddr *ifa;
  263 
  264 #define equal(a1, a2) \
  265   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  266         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
  267             for (ifa = ifp->if_addrhead.tqh_first; ifa;
  268                  ifa = ifa->ifa_link.tqe_next) {
  269                 if (ifa->ifa_addr->sa_family != addr->sa_family)
  270                         continue;
  271                 if (equal(addr, ifa->ifa_addr))
  272                         return (ifa);
  273                 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
  274                     /* IP6 doesn't have broadcast */
  275                     ifa->ifa_broadaddr->sa_len != 0 &&
  276                     equal(ifa->ifa_broadaddr, addr))
  277                         return (ifa);
  278         }
  279         return ((struct ifaddr *)0);
  280 }
  281 /*
  282  * Locate the point to point interface with a given destination address.
  283  */
  284 /*ARGSUSED*/
  285 struct ifaddr *
  286 ifa_ifwithdstaddr(addr)
  287         register struct sockaddr *addr;
  288 {
  289         register struct ifnet *ifp;
  290         register struct ifaddr *ifa;
  291 
  292         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
  293             if (ifp->if_flags & IFF_POINTOPOINT)
  294                 for (ifa = ifp->if_addrhead.tqh_first; ifa;
  295                      ifa = ifa->ifa_link.tqe_next) {
  296                         if (ifa->ifa_addr->sa_family != addr->sa_family)
  297                                 continue;
  298                         if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
  299                                 return (ifa);
  300         }
  301         return ((struct ifaddr *)0);
  302 }
  303 
  304 /*
  305  * Find an interface on a specific network.  If many, choice
  306  * is most specific found.
  307  */
  308 struct ifaddr *
  309 ifa_ifwithnet(addr)
  310         struct sockaddr *addr;
  311 {
  312         register struct ifnet *ifp;
  313         register struct ifaddr *ifa;
  314         struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
  315         u_int af = addr->sa_family;
  316         char *addr_data = addr->sa_data, *cplim;
  317 
  318         /*
  319          * AF_LINK addresses can be looked up directly by their index number,
  320          * so do that if we can.
  321          */
  322         if (af == AF_LINK) {
  323             register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
  324             if (sdl->sdl_index && sdl->sdl_index <= if_index)
  325                 return (ifnet_addrs[sdl->sdl_index - 1]);
  326         }
  327 
  328         /*
  329          * Scan though each interface, looking for ones that have
  330          * addresses in this address family.
  331          */
  332         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
  333                 for (ifa = ifp->if_addrhead.tqh_first; ifa;
  334                      ifa = ifa->ifa_link.tqe_next) {
  335                         register char *cp, *cp2, *cp3;
  336 
  337                         if (ifa->ifa_addr->sa_family != af)
  338 next:                           continue;
  339 #ifndef __APPLE__
  340 /* This breaks tunneling application trying to install a route with
  341  * a specific subnet and the local address as the destination
  342  * It's breaks binary compatibility with previous version of MacOS X
  343  */
  344                         if (
  345  
  346 #if INET6 /* XXX: for maching gif tunnel dst as routing entry gateway */
  347                             addr->sa_family != AF_INET6 &&
  348 #endif
  349                             ifp->if_flags & IFF_POINTOPOINT) {
  350                                 /*
  351                                  * This is a bit broken as it doesn't
  352                                  * take into account that the remote end may
  353                                  * be a single node in the network we are
  354                                  * looking for.
  355                                  * The trouble is that we don't know the
  356                                  * netmask for the remote end.
  357                                  */
  358                                 if (ifa->ifa_dstaddr != 0
  359                                     && equal(addr, ifa->ifa_dstaddr))
  360                                         return (ifa);
  361                         } else
  362 #endif /* __APPLE__*/
  363                         {
  364                                 /*
  365                                  * if we have a special address handler,
  366                                  * then use it instead of the generic one.
  367                                  */
  368                                 if (ifa->ifa_claim_addr) {
  369                                         if ((*ifa->ifa_claim_addr)(ifa, addr)) {
  370                                                 return (ifa);
  371                                         } else {
  372                                                 continue;
  373                                         }
  374                                 }
  375 
  376                                 /*
  377                                  * Scan all the bits in the ifa's address.
  378                                  * If a bit dissagrees with what we are
  379                                  * looking for, mask it with the netmask
  380                                  * to see if it really matters.
  381                                  * (A byte at a time)
  382                                  */
  383                                 if (ifa->ifa_netmask == 0)
  384                                         continue;
  385                                 cp = addr_data;
  386                                 cp2 = ifa->ifa_addr->sa_data;
  387                                 cp3 = ifa->ifa_netmask->sa_data;
  388                                 cplim = ifa->ifa_netmask->sa_len
  389                                         + (char *)ifa->ifa_netmask;
  390                                 while (cp3 < cplim)
  391                                         if ((*cp++ ^ *cp2++) & *cp3++)
  392                                                 goto next; /* next address! */
  393                                 /*
  394                                  * If the netmask of what we just found
  395                                  * is more specific than what we had before
  396                                  * (if we had one) then remember the new one
  397                                  * before continuing to search
  398                                  * for an even better one.
  399                                  */
  400                                 if (ifa_maybe == 0 ||
  401                                     rn_refines((caddr_t)ifa->ifa_netmask,
  402                                     (caddr_t)ifa_maybe->ifa_netmask))
  403                                         ifa_maybe = ifa;
  404                         }
  405                 }
  406         }
  407         return (ifa_maybe);
  408 }
  409 
  410 /*
  411  * Find an interface address specific to an interface best matching
  412  * a given address.
  413  */
  414 struct ifaddr *
  415 ifaof_ifpforaddr(addr, ifp)
  416         struct sockaddr *addr;
  417         register struct ifnet *ifp;
  418 {
  419         register struct ifaddr *ifa;
  420         register char *cp, *cp2, *cp3;
  421         register char *cplim;
  422         struct ifaddr *ifa_maybe = 0;
  423         u_int af = addr->sa_family;
  424 
  425         if (af >= AF_MAX)
  426                 return (0);
  427         for (ifa = ifp->if_addrhead.tqh_first; ifa;
  428              ifa = ifa->ifa_link.tqe_next) {
  429                 if (ifa->ifa_addr->sa_family != af)
  430                         continue;
  431                 if (ifa_maybe == 0)
  432                         ifa_maybe = ifa;
  433                 if (ifa->ifa_netmask == 0) {
  434                         if (equal(addr, ifa->ifa_addr) ||
  435                             (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
  436                                 return (ifa);
  437                         continue;
  438                 }
  439                 if (ifp->if_flags & IFF_POINTOPOINT) {
  440                         if (equal(addr, ifa->ifa_dstaddr))
  441                                 return (ifa);
  442                 } else {
  443                         cp = addr->sa_data;
  444                         cp2 = ifa->ifa_addr->sa_data;
  445                         cp3 = ifa->ifa_netmask->sa_data;
  446                         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
  447                         for (; cp3 < cplim; cp3++)
  448                                 if ((*cp++ ^ *cp2++) & *cp3)
  449                                         break;
  450                         if (cp3 == cplim)
  451                                 return (ifa);
  452                 }
  453         }
  454         return (ifa_maybe);
  455 }
  456 
  457 #include <net/route.h>
  458 
  459 /*
  460  * Default action when installing a route with a Link Level gateway.
  461  * Lookup an appropriate real ifa to point to.
  462  * This should be moved to /sys/net/link.c eventually.
  463  */
  464 static void
  465 link_rtrequest(cmd, rt, sa)
  466         int cmd;
  467         register struct rtentry *rt;
  468         struct sockaddr *sa;
  469 {
  470         register struct ifaddr *ifa;
  471         struct sockaddr *dst;
  472         struct ifnet *ifp;
  473 
  474         if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
  475             ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
  476                 return;
  477         ifa = ifaof_ifpforaddr(dst, ifp);
  478         if (ifa) {
  479                 rtsetifa(rt, ifa);
  480                 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
  481                         ifa->ifa_rtrequest(cmd, rt, sa);
  482         }
  483 }
  484 
  485 /*
  486  * Mark an interface down and notify protocols of
  487  * the transition.
  488  * NOTE: must be called at splnet or eqivalent.
  489  */
  490 void
  491 if_unroute(ifp, flag, fam)
  492         register struct ifnet *ifp;
  493         int flag, fam;
  494 {
  495         register struct ifaddr *ifa;
  496 
  497         ifp->if_flags &= ~flag;
  498         getmicrotime(&ifp->if_lastchange);
  499         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  500                 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
  501                         pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
  502         if_qflush(&ifp->if_snd);
  503         rt_ifmsg(ifp);
  504 }
  505 
  506 /*
  507  * Mark an interface up and notify protocols of
  508  * the transition.
  509  * NOTE: must be called at splnet or eqivalent.
  510  */
  511 void
  512 if_route(ifp, flag, fam)
  513         register struct ifnet *ifp;
  514         int flag, fam;
  515 {
  516         register struct ifaddr *ifa;
  517 
  518         ifp->if_flags |= flag;
  519         getmicrotime(&ifp->if_lastchange);
  520         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  521                 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
  522                         pfctlinput(PRC_IFUP, ifa->ifa_addr);
  523         rt_ifmsg(ifp);
  524 
  525 }
  526 
  527 /*
  528  * Mark an interface down and notify protocols of
  529  * the transition.
  530  * NOTE: must be called at splnet or eqivalent.
  531  */
  532 void
  533 if_down(ifp)
  534         register struct ifnet *ifp;
  535 {
  536 
  537         if_unroute(ifp, IFF_UP, AF_UNSPEC);
  538 }
  539 
  540 /*
  541  * Mark an interface up and notify protocols of
  542  * the transition.
  543  * NOTE: must be called at splnet or eqivalent.
  544  */
  545 void
  546 if_up(ifp)
  547         register struct ifnet *ifp;
  548 {
  549 
  550         if_route(ifp, IFF_UP, AF_UNSPEC);
  551 }
  552 
  553 /*
  554  * Flush an interface queue.
  555  */
  556 static void
  557 if_qflush(ifq)
  558         register struct ifqueue *ifq;
  559 {
  560         register struct mbuf *m, *n;
  561 
  562         n = ifq->ifq_head;
  563         while ((m = n) != 0) {
  564                 n = m->m_act;
  565                 m_freem(m);
  566         }
  567         ifq->ifq_head = 0;
  568         ifq->ifq_tail = 0;
  569         ifq->ifq_len = 0;
  570 }
  571 
  572 /*
  573  * Map interface name to
  574  * interface structure pointer.
  575  */
  576 struct ifnet *
  577 ifunit(const char *name)
  578 {
  579         char namebuf[IFNAMSIZ + 1];
  580         const char *cp;
  581         struct ifnet *ifp;
  582         int unit;
  583         unsigned len, m;
  584         char c;
  585 
  586         len = strlen(name);
  587         if (len < 2 || len > IFNAMSIZ)
  588                 return NULL;
  589         cp = name + len - 1;
  590         c = *cp;
  591         if (c < '' || c > '9')
  592                 return NULL;            /* trailing garbage */
  593         unit = 0;
  594         m = 1;
  595         do {
  596                 if (cp == name)
  597                         return NULL;    /* no interface name */
  598                 unit += (c - '') * m;
  599                 if (unit > 1000000)
  600                         return NULL;    /* number is unreasonable */
  601                 m *= 10;
  602                 c = *--cp;
  603         } while (c >= '' && c <= '9');
  604         len = cp - name + 1;
  605         bcopy(name, namebuf, len);
  606         namebuf[len] = '\0';
  607         /*
  608          * Now search all the interfaces for this name/number
  609          */
  610         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
  611                 if (strcmp(ifp->if_name, namebuf))
  612                         continue;
  613                 if (unit == ifp->if_unit)
  614                         break;
  615         }
  616         return (ifp);
  617 }
  618 
  619 
  620 /*
  621  * Map interface name in a sockaddr_dl to
  622  * interface structure pointer.
  623  */
  624 struct ifnet *
  625 if_withname(sa)
  626         struct sockaddr *sa;
  627 {
  628         char ifname[IFNAMSIZ+1];
  629         struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
  630 
  631         if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
  632              (sdl->sdl_nlen > IFNAMSIZ) )
  633                 return NULL;
  634 
  635         /*
  636          * ifunit wants a null-terminated name.  It may not be null-terminated
  637          * in the sockaddr.  We don't want to change the caller's sockaddr,
  638          * and there might not be room to put the trailing null anyway, so we
  639          * make a local copy that we know we can null terminate safely.
  640          */
  641 
  642         bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
  643         ifname[sdl->sdl_nlen] = '\0';
  644         return ifunit(ifname);
  645 }
  646 
  647 
  648 /*
  649  * Interface ioctls.
  650  */
  651 int
  652 ifioctl(so, cmd, data, p)
  653         struct socket *so;
  654         u_long cmd;
  655         caddr_t data;
  656         struct proc *p;
  657 {
  658         register struct ifnet *ifp;
  659         register struct ifreq *ifr;
  660         struct ifstat *ifs;
  661         int error = 0;
  662         short oif_flags;
  663         struct kev_msg        ev_msg;
  664         struct net_event_data ev_data;
  665 
  666         switch (cmd) {
  667 
  668         case SIOCGIFCONF:
  669         case OSIOCGIFCONF:
  670                 return (ifconf(cmd, data));
  671         }
  672         ifr = (struct ifreq *)data;
  673         ifp = ifunit(ifr->ifr_name);
  674         if (ifp == 0)
  675                 return (ENXIO);
  676         switch (cmd) {
  677 
  678         case SIOCGIFFLAGS:
  679                 ifr->ifr_flags = ifp->if_flags;
  680                 break;
  681 
  682         case SIOCGIFMETRIC:
  683                 ifr->ifr_metric = ifp->if_metric;
  684                 break;
  685 
  686         case SIOCGIFMTU:
  687                 ifr->ifr_mtu = ifp->if_mtu;
  688                 break;
  689 
  690         case SIOCGIFPHYS:
  691                 ifr->ifr_phys = ifp->if_physical;
  692                 break;
  693 
  694         case SIOCSIFFLAGS:
  695                 error = suser(p->p_ucred, &p->p_acflag);
  696                 if (error)
  697                         return (error);
  698 #ifndef __APPLE__
  699                 if (ifp->if_flags & IFF_SMART) {
  700                         /* Smart drivers twiddle their own routes */
  701                 } else
  702 #endif
  703                 if (ifp->if_flags & IFF_UP &&
  704                     (ifr->ifr_flags & IFF_UP) == 0) {
  705                         int s = splimp();
  706                         if_down(ifp);
  707                         splx(s);
  708                 } else if (ifr->ifr_flags & IFF_UP &&
  709                     (ifp->if_flags & IFF_UP) == 0) {
  710                         int s = splimp();
  711                         if_up(ifp);
  712                         splx(s);
  713                 }
  714                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
  715                         (ifr->ifr_flags &~ IFF_CANTCHANGE);
  716 
  717                 error = dlil_ioctl(so->so_proto->pr_domain->dom_family, 
  718                                    ifp, cmd, (caddr_t) data);
  719 
  720                 if (error == 0) {
  721                          ev_msg.vendor_code    = KEV_VENDOR_APPLE;
  722                          ev_msg.kev_class      = KEV_NETWORK_CLASS;
  723                          ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
  724 
  725                          ev_msg.event_code = KEV_DL_SIFFLAGS;
  726                          strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
  727                          ev_data.if_family = ifp->if_family;
  728                          ev_data.if_unit   = (unsigned long) ifp->if_unit;
  729                          ev_msg.dv[0].data_length = sizeof(struct net_event_data);
  730                          ev_msg.dv[0].data_ptr    = &ev_data;
  731                          ev_msg.dv[1].data_length = 0;
  732                          kev_post_msg(&ev_msg);
  733                 }
  734                 getmicrotime(&ifp->if_lastchange);
  735                 break;
  736 
  737         case SIOCSIFMETRIC:
  738                 error = suser(p->p_ucred, &p->p_acflag);
  739                 if (error)
  740                         return (error);
  741                 ifp->if_metric = ifr->ifr_metric;
  742 
  743 
  744                 ev_msg.vendor_code    = KEV_VENDOR_APPLE;
  745                 ev_msg.kev_class      = KEV_NETWORK_CLASS;
  746                 ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
  747         
  748                 ev_msg.event_code = KEV_DL_SIFMETRICS;
  749                 strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
  750                 ev_data.if_family = ifp->if_family;
  751                 ev_data.if_unit   = (unsigned long) ifp->if_unit;
  752                 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
  753                 ev_msg.dv[0].data_ptr    = &ev_data;
  754 
  755                 ev_msg.dv[1].data_length = 0;
  756                 kev_post_msg(&ev_msg);
  757 
  758                 getmicrotime(&ifp->if_lastchange);
  759                 break;
  760 
  761         case SIOCSIFPHYS:
  762                 error = suser(p->p_ucred, &p->p_acflag);
  763                 if (error)
  764                         return error;
  765 
  766                 error = dlil_ioctl(so->so_proto->pr_domain->dom_family, 
  767                                         ifp, cmd, (caddr_t) data);
  768 
  769                 if (error == 0) {
  770                         ev_msg.vendor_code    = KEV_VENDOR_APPLE;
  771                         ev_msg.kev_class      = KEV_NETWORK_CLASS;
  772                         ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
  773 
  774                         ev_msg.event_code = KEV_DL_SIFPHYS;
  775                         strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
  776                         ev_data.if_family = ifp->if_family;
  777                         ev_data.if_unit   = (unsigned long) ifp->if_unit;
  778                         ev_msg.dv[0].data_length = sizeof(struct net_event_data);
  779                         ev_msg.dv[0].data_ptr    = &ev_data;
  780                         ev_msg.dv[1].data_length = 0;
  781                         kev_post_msg(&ev_msg);
  782 
  783                         getmicrotime(&ifp->if_lastchange);
  784                 }
  785                 return(error);
  786 
  787         case SIOCSIFMTU:
  788         {
  789                 u_long oldmtu = ifp->if_mtu;
  790 
  791                 error = suser(p->p_ucred, &p->p_acflag);
  792                 if (error)
  793                         return (error);
  794                 if (ifp->if_ioctl == NULL)
  795                         return (EOPNOTSUPP);
  796                 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
  797                         return (EINVAL);
  798 
  799                 error = dlil_ioctl(so->so_proto->pr_domain->dom_family, 
  800                                    ifp, cmd, (caddr_t) data);
  801 
  802                 if (error == 0) {
  803                      ev_msg.vendor_code    = KEV_VENDOR_APPLE;
  804                      ev_msg.kev_class      = KEV_NETWORK_CLASS;
  805                      ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
  806         
  807                      ev_msg.event_code = KEV_DL_SIFMTU;
  808                      strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
  809                      ev_data.if_family = ifp->if_family;
  810                      ev_data.if_unit   = (unsigned long) ifp->if_unit;
  811                      ev_msg.dv[0].data_length = sizeof(struct net_event_data);
  812                      ev_msg.dv[0].data_ptr    = &ev_data;
  813                      ev_msg.dv[1].data_length = 0;
  814                      kev_post_msg(&ev_msg);
  815 
  816                         getmicrotime(&ifp->if_lastchange);
  817                         rt_ifmsg(ifp);
  818                 }
  819                 /*
  820                  * If the link MTU changed, do network layer specific procedure.
  821                  */
  822                 if (ifp->if_mtu != oldmtu) {
  823 #if INET6
  824                         nd6_setmtu(ifp);
  825 #endif
  826                 }
  827                 return (error);
  828         }
  829 
  830         case SIOCADDMULTI:
  831         case SIOCDELMULTI:
  832                 error = suser(p->p_ucred, &p->p_acflag);
  833                 if (error)
  834                         return (error);
  835 
  836                 /* Don't allow group membership on non-multicast interfaces. */
  837                 if ((ifp->if_flags & IFF_MULTICAST) == 0)
  838                         return EOPNOTSUPP;
  839 
  840 #ifndef __APPLE__
  841                 /* Don't let users screw up protocols' entries. */
  842                 if (ifr->ifr_addr.sa_family != AF_LINK)
  843                         return EINVAL;
  844 #endif
  845 
  846                 if (cmd == SIOCADDMULTI) {
  847                         struct ifmultiaddr *ifma;
  848                         error = if_addmulti(ifp, &ifr->ifr_addr, &ifma);
  849                         ev_msg.event_code = KEV_DL_ADDMULTI;
  850                 } else {
  851                         error = if_delmulti(ifp, &ifr->ifr_addr);
  852                         ev_msg.event_code = KEV_DL_DELMULTI;
  853                 }
  854                 if (error == 0) {
  855                      ev_msg.vendor_code    = KEV_VENDOR_APPLE;
  856                      ev_msg.kev_class      = KEV_NETWORK_CLASS;
  857                      ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
  858                      strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
  859         
  860                      ev_data.if_family = ifp->if_family;
  861                      ev_data.if_unit   = (unsigned long) ifp->if_unit;
  862                      ev_msg.dv[0].data_length = sizeof(struct net_event_data);
  863                      ev_msg.dv[0].data_ptr    = &ev_data;
  864                      ev_msg.dv[1].data_length = 0;
  865                      kev_post_msg(&ev_msg);
  866 
  867                      getmicrotime(&ifp->if_lastchange);
  868                 }
  869                 return error;
  870 
  871         case SIOCSIFPHYADDR:
  872         case SIOCDIFPHYADDR:
  873 #ifdef INET6
  874         case SIOCSIFPHYADDR_IN6:
  875 #endif
  876         case SIOCSLIFPHYADDR:
  877         case SIOCSIFMEDIA:
  878         case SIOCSIFGENERIC:
  879         case SIOCSIFLLADDR:
  880                 error = suser(p->p_ucred, &p->p_acflag);
  881                 if (error)
  882                         return (error);
  883 
  884                 error = dlil_ioctl(so->so_proto->pr_domain->dom_family, 
  885                                    ifp, cmd, (caddr_t) data);
  886 
  887                 if (error == 0)
  888                         getmicrotime(&ifp->if_lastchange);
  889                 return error;
  890 
  891         case SIOCGIFSTATUS:
  892                 ifs = (struct ifstat *)data;
  893                 ifs->ascii[0] = '\0';
  894                 
  895         case SIOCGIFPSRCADDR:
  896         case SIOCGIFPDSTADDR:
  897         case SIOCGLIFPHYADDR:
  898         case SIOCGIFMEDIA:
  899         case SIOCGIFGENERIC:
  900 
  901                 return dlil_ioctl(so->so_proto->pr_domain->dom_family, 
  902                                    ifp, cmd, (caddr_t) data);
  903 
  904         default:
  905                 oif_flags = ifp->if_flags;
  906                 if (so->so_proto == 0)
  907                         return (EOPNOTSUPP);
  908 #if !COMPAT_43
  909                 return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
  910                                                                  data,
  911                                                                  ifp, p));
  912 #else
  913             {
  914                 int ocmd = cmd;
  915 
  916                 switch (cmd) {
  917 
  918                 case SIOCSIFDSTADDR:
  919                 case SIOCSIFADDR:
  920                 case SIOCSIFBRDADDR:
  921                 case SIOCSIFNETMASK:
  922 #if BYTE_ORDER != BIG_ENDIAN
  923                         if (ifr->ifr_addr.sa_family == 0 &&
  924                             ifr->ifr_addr.sa_len < 16) {
  925                                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
  926                                 ifr->ifr_addr.sa_len = 16;
  927                         }
  928 #else
  929                         if (ifr->ifr_addr.sa_len == 0)
  930                                 ifr->ifr_addr.sa_len = 16;
  931 #endif
  932                         break;
  933 
  934                 case OSIOCGIFADDR:
  935                         cmd = SIOCGIFADDR;
  936                         break;
  937 
  938                 case OSIOCGIFDSTADDR:
  939                         cmd = SIOCGIFDSTADDR;
  940                         break;
  941 
  942                 case OSIOCGIFBRDADDR:
  943                         cmd = SIOCGIFBRDADDR;
  944                         break;
  945 
  946                 case OSIOCGIFNETMASK:
  947                         cmd = SIOCGIFNETMASK;
  948                 }
  949                 error =  ((*so->so_proto->pr_usrreqs->pru_control)(so,
  950                                                                    cmd,
  951                                                                    data,
  952                                                                    ifp, p));
  953                 switch (ocmd) {
  954 
  955                 case OSIOCGIFADDR:
  956                 case OSIOCGIFDSTADDR:
  957                 case OSIOCGIFBRDADDR:
  958                 case OSIOCGIFNETMASK:
  959                         *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
  960 
  961                 }
  962             }
  963 #endif /* COMPAT_43 */
  964 
  965                 if (error == EOPNOTSUPP)
  966                         error = dlil_ioctl(so->so_proto->pr_domain->dom_family,
  967                                                                 ifp, cmd, (caddr_t) data);
  968 
  969                 return (error);
  970         }
  971         return (0);
  972 }
  973 
  974 /*
  975  * Set/clear promiscuous mode on interface ifp based on the truth value
  976  * of pswitch.  The calls are reference counted so that only the first
  977  * "on" request actually has an effect, as does the final "off" request.
  978  * Results are undefined if the "off" and "on" requests are not matched.
  979  */
  980 int
  981 ifpromisc(ifp, pswitch)
  982         struct ifnet *ifp;
  983         int pswitch;
  984 {
  985         struct ifreq ifr;
  986         int error;
  987         int oldflags;
  988 
  989         oldflags = ifp->if_flags;
  990         if (pswitch) {
  991                 /*
  992                  * If the device is not configured up, we cannot put it in
  993                  * promiscuous mode.
  994                  */
  995                 if ((ifp->if_flags & IFF_UP) == 0)
  996                         return (ENETDOWN);
  997                 if (ifp->if_pcount++ != 0)
  998                         return (0);
  999                 ifp->if_flags |= IFF_PROMISC;
 1000                 log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
 1001                     ifp->if_name, ifp->if_unit);
 1002         } else {
 1003                 if (--ifp->if_pcount > 0)
 1004                         return (0);
 1005                 ifp->if_flags &= ~IFF_PROMISC;
 1006                 log(LOG_INFO, "%s%d: promiscuous mode disabled\n",
 1007                     ifp->if_name, ifp->if_unit);
 1008         }
 1009         ifr.ifr_flags = ifp->if_flags;
 1010         error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
 1011         if (error == 0)
 1012                 rt_ifmsg(ifp);
 1013         else
 1014                 ifp->if_flags = oldflags;
 1015         return error;
 1016 }
 1017 
 1018 /*
 1019  * Return interface configuration
 1020  * of system.  List may be used
 1021  * in later ioctl's (above) to get
 1022  * other information.
 1023  */
 1024 /*ARGSUSED*/
 1025 static int
 1026 ifconf(cmd, data)
 1027         u_long cmd;
 1028         caddr_t data;
 1029 {
 1030         register struct ifconf *ifc = (struct ifconf *)data;
 1031         register struct ifnet *ifp = ifnet.tqh_first;
 1032         register struct ifaddr *ifa;
 1033         struct ifreq ifr, *ifrp;
 1034         int space = ifc->ifc_len, error = 0;
 1035 
 1036         ifrp = ifc->ifc_req;
 1037         for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) {
 1038                 char workbuf[64];
 1039                 int ifnlen, addrs;
 1040 
 1041                 ifnlen = snprintf(workbuf, sizeof(workbuf),
 1042                     "%s%d", ifp->if_name, ifp->if_unit);
 1043                 if(ifnlen + 1 > sizeof ifr.ifr_name) {
 1044                         error = ENAMETOOLONG;
 1045                         break;
 1046                 } else {
 1047                         strcpy(ifr.ifr_name, workbuf);
 1048                 }
 1049 
 1050                 addrs = 0;
 1051                 ifa = ifp->if_addrhead.tqh_first;
 1052                 for ( ; space > sizeof (ifr) && ifa;
 1053                     ifa = ifa->ifa_link.tqe_next) {
 1054                         register struct sockaddr *sa = ifa->ifa_addr;
 1055 #ifndef __APPLE__
 1056                         if (curproc->p_prison && prison_if(curproc, sa))
 1057                                 continue;
 1058 #endif
 1059                         addrs++;
 1060 #ifdef COMPAT_43
 1061                         if (cmd == OSIOCGIFCONF) {
 1062                                 struct osockaddr *osa =
 1063                                          (struct osockaddr *)&ifr.ifr_addr;
 1064                                 ifr.ifr_addr = *sa;
 1065                                 osa->sa_family = sa->sa_family;
 1066                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
 1067                                                 sizeof (ifr));
 1068                                 ifrp++;
 1069                         } else
 1070 #endif
 1071                         if (sa->sa_len <= sizeof(*sa)) {
 1072                                 ifr.ifr_addr = *sa;
 1073                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
 1074                                                 sizeof (ifr));
 1075                                 ifrp++;
 1076                         } else {
 1077                                 if (space < sizeof (ifr) + sa->sa_len -
 1078                                             sizeof(*sa))
 1079                                         break;
 1080                                 space -= sa->sa_len - sizeof(*sa);
 1081                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
 1082                                                 sizeof (ifr.ifr_name));
 1083                                 if (error == 0)
 1084                                     error = copyout((caddr_t)sa,
 1085                                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
 1086                                 ifrp = (struct ifreq *)
 1087                                         (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
 1088                         }
 1089                         if (error)
 1090                                 break;
 1091                         space -= sizeof (ifr);
 1092                 }
 1093                 if (error)
 1094                         break;
 1095                 if (!addrs) {
 1096                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
 1097                         error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
 1098                             sizeof (ifr));
 1099                         if (error)
 1100                                 break;
 1101                         space -= sizeof (ifr);
 1102                         ifrp++;
 1103                 }
 1104         }
 1105         ifc->ifc_len -= space;
 1106         return (error);
 1107 }
 1108 
 1109 /*
 1110  * Just like if_promisc(), but for all-multicast-reception mode.
 1111  */
 1112 int
 1113 if_allmulti(ifp, onswitch)
 1114         struct ifnet *ifp;
 1115         int onswitch;
 1116 {
 1117         int error = 0;
 1118         int s = splimp();
 1119 
 1120         if (onswitch) {
 1121                 if (ifp->if_amcount++ == 0) {
 1122                         ifp->if_flags |= IFF_ALLMULTI;
 1123                         error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
 1124                 }
 1125         } else {
 1126                 if (ifp->if_amcount > 1) {
 1127                         ifp->if_amcount--;
 1128                 } else {
 1129                         ifp->if_amcount = 0;
 1130                         ifp->if_flags &= ~IFF_ALLMULTI;
 1131                         error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
 1132                 }
 1133         }
 1134         splx(s);
 1135 
 1136         if (error == 0)
 1137                 rt_ifmsg(ifp);
 1138         return error;
 1139 }
 1140 
 1141 /*
 1142  * Add a multicast listenership to the interface in question.
 1143  * The link layer provides a routine which converts
 1144  */
 1145 int
 1146 if_addmulti(ifp, sa, retifma)
 1147         struct ifnet *ifp;      /* interface to manipulate */
 1148         struct sockaddr *sa;    /* address to add */
 1149         struct ifmultiaddr **retifma;
 1150 {
 1151         struct sockaddr *llsa = 0;
 1152         struct sockaddr *dupsa;
 1153         int error, s;
 1154         struct ifmultiaddr *ifma;
 1155         struct rslvmulti_req   rsreq;
 1156 
 1157         /*
 1158          * If the matching multicast address already exists
 1159          * then don't add a new one, just add a reference
 1160          */
 1161         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
 1162              ifma = ifma->ifma_link.le_next) {
 1163                 if (equal(sa, ifma->ifma_addr)) {
 1164                         ifma->ifma_refcount++;
 1165                         if (retifma)
 1166                                 *retifma = ifma;
 1167                         return 0;
 1168                 }
 1169         }
 1170 
 1171         /*
 1172          * Give the link layer a chance to accept/reject it, and also
 1173          * find out which AF_LINK address this maps to, if it isn't one
 1174          * already.
 1175          */
 1176         rsreq.sa = sa;
 1177         rsreq.llsa = &llsa;
 1178 
 1179         error = dlil_ioctl(sa->sa_family, ifp, SIOCRSLVMULTI, (caddr_t) &rsreq);
 1180         
 1181         /* to be similar to FreeBSD */
 1182         if (error == EOPNOTSUPP)
 1183                 error = 0;
 1184 
 1185         if (error) 
 1186              return error;
 1187 
 1188         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
 1189         MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
 1190         bcopy(sa, dupsa, sa->sa_len);
 1191 
 1192         ifma->ifma_addr = dupsa;
 1193         ifma->ifma_lladdr = llsa;
 1194         ifma->ifma_ifp = ifp;
 1195         ifma->ifma_refcount = 1;
 1196         ifma->ifma_protospec = 0;
 1197         rt_newmaddrmsg(RTM_NEWMADDR, ifma);
 1198 
 1199         /*
 1200          * Some network interfaces can scan the address list at
 1201          * interrupt time; lock them out.
 1202          */
 1203         s = splimp();
 1204         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
 1205         splx(s);
 1206         if (retifma)
 1207             *retifma = ifma;
 1208 
 1209         if (llsa != 0) {
 1210                 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
 1211                      ifma = ifma->ifma_link.le_next) {
 1212                         if (equal(ifma->ifma_addr, llsa))
 1213                                 break;
 1214                 }
 1215                 if (ifma) {
 1216                         ifma->ifma_refcount++;
 1217                 } else {
 1218                         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
 1219                                M_IFMADDR, M_WAITOK);
 1220                         MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
 1221                                M_IFMADDR, M_WAITOK);
 1222                         bcopy(llsa, dupsa, llsa->sa_len);
 1223                         ifma->ifma_addr = dupsa;
 1224                         ifma->ifma_lladdr = 0;
 1225                         ifma->ifma_ifp = ifp;
 1226                         ifma->ifma_refcount = 1;
 1227                         s = splimp();
 1228                         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
 1229                         splx(s);
 1230                 }
 1231         }
 1232         /*
 1233          * We are certain we have added something, so call down to the
 1234          * interface to let them know about it.
 1235          */
 1236         s = splimp();
 1237         dlil_ioctl(0, ifp, SIOCADDMULTI, (caddr_t) 0);
 1238         splx(s);
 1239 
 1240         return 0;
 1241 }
 1242 
 1243 int
 1244 if_delmultiaddr(struct ifmultiaddr *ifma)
 1245 {
 1246         struct sockaddr *sa;
 1247         struct ifnet *ifp;
 1248         
 1249         /* Verify ifma is valid */
 1250         {
 1251                 struct ifmultiaddr *match = NULL;
 1252                 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
 1253                         for (match = ifp->if_multiaddrs.lh_first; match; match = match->ifma_link.le_next) {
 1254                                 if (match->ifma_ifp != ifp) {
 1255                                         printf("if_delmultiaddr: ifma (%x) on ifp i(%s) is stale\n",
 1256                                                         match, if_name(ifp));
 1257                                         return (0) ; /* swallow error ? */
 1258                                 }
 1259                                 if (match == ifma)
 1260                                         break;
 1261                         }
 1262                         if (match == ifma)
 1263                                 break;
 1264                 }
 1265                 if (match != ifma) {
 1266                         for (match = ifma_lostlist.lh_first; match; match = match->ifma_link.le_next) {
 1267                                 if (match->ifma_ifp != NULL) {
 1268                                         printf("if_delmultiaddr: item on lost list (%x) contains non-null ifp=%s\n",
 1269                                                         match, if_name(match->ifma_ifp));
 1270                                         return (0) ; /* swallow error ? */
 1271                                 }
 1272                                 if (match == ifma)
 1273                                         break;
 1274                         }
 1275                 }
 1276                 
 1277                 if (match != ifma) {
 1278                         printf("if_delmultiaddr: ifma 0x%X is invalid\n", ifma);
 1279                         return 0;
 1280                 }
 1281         }
 1282         
 1283         if (ifma->ifma_refcount > 1) {
 1284                 ifma->ifma_refcount--;
 1285                 return 0;
 1286         }
 1287 
 1288         sa = ifma->ifma_lladdr;
 1289 
 1290         if (sa) /* send a routing msg for network addresses only */
 1291                 rt_newmaddrmsg(RTM_DELMADDR, ifma);
 1292 
 1293         ifp = ifma->ifma_ifp;
 1294         
 1295         LIST_REMOVE(ifma, ifma_link);
 1296         /*
 1297          * Make sure the interface driver is notified
 1298          * in the case of a link layer mcast group being left.
 1299          */
 1300         if (ifp && ifma->ifma_addr->sa_family == AF_LINK && sa == 0)
 1301                 dlil_ioctl(0, ifp, SIOCDELMULTI, 0);
 1302         FREE(ifma->ifma_addr, M_IFMADDR);
 1303         FREE(ifma, M_IFMADDR);
 1304         if (sa == 0)
 1305                 return 0;
 1306 
 1307         /*
 1308          * Now look for the link-layer address which corresponds to
 1309          * this network address.  It had been squirreled away in
 1310          * ifma->ifma_lladdr for this purpose (so we don't have
 1311          * to call SIOCRSLVMULTI again), and we saved that
 1312          * value in sa above.  If some nasty deleted the
 1313          * link-layer address out from underneath us, we can deal because
 1314          * the address we stored was is not the same as the one which was
 1315          * in the record for the link-layer address.  (So we don't complain
 1316          * in that case.)
 1317          */
 1318         if (ifp)
 1319                 ifma = ifp->if_multiaddrs.lh_first;
 1320         else
 1321                 ifma = ifma_lostlist.lh_first;
 1322         for (; ifma; ifma = ifma->ifma_link.le_next)
 1323                 if (equal(sa, ifma->ifma_addr))
 1324                         break;
 1325         
 1326         FREE(sa, M_IFMADDR);
 1327         if (ifma == 0) {
 1328                 return 0;
 1329         }
 1330 
 1331         return if_delmultiaddr(ifma);
 1332 }
 1333 
 1334 /*
 1335  * Remove a reference to a multicast address on this interface.  Yell
 1336  * if the request does not match an existing membership.
 1337  */
 1338 int
 1339 if_delmulti(ifp, sa)
 1340         struct ifnet *ifp;
 1341         struct sockaddr *sa;
 1342 {
 1343         struct ifmultiaddr *ifma;
 1344 
 1345         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
 1346              ifma = ifma->ifma_link.le_next)
 1347                 if (equal(sa, ifma->ifma_addr))
 1348                         break;
 1349         if (ifma == 0)
 1350                 return ENOENT;
 1351         
 1352         return if_delmultiaddr(ifma);
 1353 }
 1354 
 1355 
 1356 /*
 1357  * We don't use if_setlladdr, our interfaces are responsible for
 1358  * handling the SIOCSIFLLADDR ioctl.
 1359  */
 1360 #ifndef __APPLE__
 1361 int
 1362 if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
 1363 {
 1364         ...
 1365 }
 1366 #endif
 1367 
 1368 struct ifmultiaddr *
 1369 ifmaof_ifpforaddr(sa, ifp)
 1370         struct sockaddr *sa;
 1371         struct ifnet *ifp;
 1372 {
 1373         struct ifmultiaddr *ifma;
 1374         
 1375         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
 1376              ifma = ifma->ifma_link.le_next)
 1377                 if (equal(ifma->ifma_addr, sa))
 1378                         break;
 1379 
 1380         return ifma;
 1381 }
 1382 
 1383 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
 1384 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
 1385 
 1386 
 1387 /*
 1388  * Shutdown all network activity.  Used boot() when halting
 1389  * system.
 1390  */
 1391 int if_down_all(void)
 1392 {
 1393         struct ifnet *ifp;
 1394         int s;
 1395 
 1396         s = splnet();
 1397         TAILQ_FOREACH(ifp, &ifnet, if_link)
 1398                 if_down(ifp);
 1399 
 1400         splx(s);
 1401         return(0);              /* Sheesh */
 1402 }
 1403 
 1404 /*
 1405  * Delete Routes for a Network Interface
 1406  * 
 1407  * Called for each routing entry via the rnh->rnh_walktree() call above
 1408  * to delete all route entries referencing a detaching network interface.
 1409  *
 1410  * Arguments:
 1411  *      rn      pointer to node in the routing table
 1412  *      arg     argument passed to rnh->rnh_walktree() - detaching interface
 1413  *
 1414  * Returns:
 1415  *      0       successful
 1416  *      errno   failed - reason indicated
 1417  *
 1418  */
 1419 static int
 1420 if_rtdel(rn, arg)
 1421         struct radix_node       *rn;
 1422         void                    *arg;
 1423 {
 1424         struct rtentry  *rt = (struct rtentry *)rn;
 1425         struct ifnet    *ifp = arg;
 1426         int             err;
 1427 
 1428         if (rt != NULL && rt->rt_ifp == ifp) {
 1429                 
 1430                 /*
 1431                  * Protect (sorta) against walktree recursion problems
 1432                  * with cloned routes
 1433                  */
 1434                 if ((rt->rt_flags & RTF_UP) == 0)
 1435                         return (0);
 1436 
 1437                 err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
 1438                                 rt_mask(rt), rt->rt_flags,
 1439                                 (struct rtentry **) NULL);
 1440                 if (err) {
 1441                         log(LOG_WARNING, "if_rtdel: error %d\n", err);
 1442                 }
 1443         }
 1444 
 1445         return (0);
 1446 }
 1447 
 1448 /*
 1449  * Removes routing table reference to a given interfacei
 1450  * for a given protocol family
 1451  */
 1452 
 1453 void if_rtproto_del(struct ifnet *ifp, int protocol)
 1454 {
 1455         
 1456         struct radix_node_head  *rnh;
 1457 
 1458         if ((protocol <= AF_MAX) && ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL))
 1459                 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
 1460 }

Cache object: 4ecc95d3817458b2c3e8376e4b58322b


[ 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.