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 /*      $NetBSD: if.c,v 1.178 2006/11/20 04:09:25 dyoung Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by William Studenmund and Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
   41  * All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. Neither the name of the project nor the names of its contributors
   52  *    may be used to endorse or promote products derived from this software
   53  *    without specific prior written permission.
   54  *
   55  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   56  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   58  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   59  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   60  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   61  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   63  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   64  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   65  * SUCH DAMAGE.
   66  */
   67 
   68 /*
   69  * Copyright (c) 1980, 1986, 1993
   70  *      The Regents of the University of California.  All rights reserved.
   71  *
   72  * Redistribution and use in source and binary forms, with or without
   73  * modification, are permitted provided that the following conditions
   74  * are met:
   75  * 1. Redistributions of source code must retain the above copyright
   76  *    notice, this list of conditions and the following disclaimer.
   77  * 2. Redistributions in binary form must reproduce the above copyright
   78  *    notice, this list of conditions and the following disclaimer in the
   79  *    documentation and/or other materials provided with the distribution.
   80  * 3. Neither the name of the University nor the names of its contributors
   81  *    may be used to endorse or promote products derived from this software
   82  *    without specific prior written permission.
   83  *
   84  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   85  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   86  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   87  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   88  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   89  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   90  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   91  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   92  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   93  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   94  * SUCH DAMAGE.
   95  *
   96  *      @(#)if.c        8.5 (Berkeley) 1/9/95
   97  */
   98 
   99 #include <sys/cdefs.h>
  100 __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.178 2006/11/20 04:09:25 dyoung Exp $");
  101 
  102 #include "opt_inet.h"
  103 
  104 #include "opt_compat_linux.h"
  105 #include "opt_compat_svr4.h"
  106 #include "opt_compat_ultrix.h"
  107 #include "opt_compat_43.h"
  108 #include "opt_atalk.h"
  109 #include "opt_natm.h"
  110 #include "opt_pfil_hooks.h"
  111 
  112 #include <sys/param.h>
  113 #include <sys/mbuf.h>
  114 #include <sys/systm.h>
  115 #include <sys/callout.h>
  116 #include <sys/proc.h>
  117 #include <sys/socket.h>
  118 #include <sys/socketvar.h>
  119 #include <sys/domain.h>
  120 #include <sys/protosw.h>
  121 #include <sys/kernel.h>
  122 #include <sys/ioctl.h>
  123 #include <sys/sysctl.h>
  124 #include <sys/syslog.h>
  125 #include <sys/kauth.h>
  126 
  127 #include <net/if.h>
  128 #include <net/if_dl.h>
  129 #include <net/if_ether.h>
  130 #include <net/if_media.h>
  131 #include <net80211/ieee80211.h>
  132 #include <net80211/ieee80211_ioctl.h>
  133 #include <net/if_types.h>
  134 #include <net/radix.h>
  135 #include <net/route.h>
  136 #include <net/netisr.h>
  137 #ifdef NETATALK
  138 #include <netatalk/at_extern.h>
  139 #include <netatalk/at.h>
  140 #endif
  141 #include <net/pfil.h>
  142 
  143 #ifdef INET6
  144 #include <netinet/in.h>
  145 #include <netinet6/in6_var.h>
  146 #include <netinet6/nd6.h>
  147 #endif
  148 
  149 #include "carp.h"
  150 #if NCARP > 0
  151 #include <netinet/ip_carp.h>
  152 #endif
  153 
  154 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) || defined(COMPAT_ULTRIX) || defined(LKM)
  155 #define COMPAT_OSOCK
  156 #include <compat/sys/socket.h>
  157 #endif
  158 
  159 MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
  160 MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
  161 
  162 int     ifqmaxlen = IFQ_MAXLEN;
  163 struct  callout if_slowtimo_ch;
  164 
  165 int netisr;                     /* scheduling bits for network */
  166 
  167 static int      if_rt_walktree(struct radix_node *, void *);
  168 
  169 static struct if_clone *if_clone_lookup(const char *, int *);
  170 static int      if_clone_list(struct if_clonereq *);
  171 
  172 static LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
  173 static int if_cloners_count;
  174 
  175 #ifdef PFIL_HOOKS
  176 struct pfil_head if_pfil;       /* packet filtering hook for interfaces */
  177 #endif
  178 
  179 static void if_detach_queues(struct ifnet *, struct ifqueue *);
  180 
  181 /*
  182  * Network interface utility routines.
  183  *
  184  * Routines with ifa_ifwith* names take sockaddr *'s as
  185  * parameters.
  186  */
  187 void
  188 ifinit(void)
  189 {
  190 
  191         callout_init(&if_slowtimo_ch);
  192         if_slowtimo(NULL);
  193 #ifdef PFIL_HOOKS
  194         if_pfil.ph_type = PFIL_TYPE_IFNET;
  195         if_pfil.ph_ifnet = NULL;
  196         if (pfil_head_register(&if_pfil) != 0)
  197                 printf("WARNING: unable to register pfil hook\n");
  198 #endif
  199 }
  200 
  201 /*
  202  * Null routines used while an interface is going away.  These routines
  203  * just return an error.
  204  */
  205 
  206 int
  207 if_nulloutput(struct ifnet *ifp, struct mbuf *m,
  208     struct sockaddr *so, struct rtentry *rt)
  209 {
  210 
  211         return (ENXIO);
  212 }
  213 
  214 void
  215 if_nullinput(struct ifnet *ifp, struct mbuf *m)
  216 {
  217 
  218         /* Nothing. */
  219 }
  220 
  221 void
  222 if_nullstart(struct ifnet *ifp)
  223 {
  224 
  225         /* Nothing. */
  226 }
  227 
  228 int
  229 if_nullioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  230 {
  231 
  232         return (ENXIO);
  233 }
  234 
  235 int
  236 if_nullinit(struct ifnet *ifp)
  237 {
  238 
  239         return (ENXIO);
  240 }
  241 
  242 void
  243 if_nullstop(struct ifnet *ifp, int disable)
  244 {
  245 
  246         /* Nothing. */
  247 }
  248 
  249 void
  250 if_nullwatchdog(struct ifnet *ifp)
  251 {
  252 
  253         /* Nothing. */
  254 }
  255 
  256 void
  257 if_nulldrain(struct ifnet *ifp)
  258 {
  259 
  260         /* Nothing. */
  261 }
  262 
  263 static u_int if_index = 1;
  264 struct ifnet_head ifnet;
  265 size_t if_indexlim = 0;
  266 struct ifaddr **ifnet_addrs = NULL;
  267 struct ifnet **ifindex2ifnet = NULL;
  268 struct ifnet *lo0ifp;
  269 
  270 /*
  271  * Allocate the link level name for the specified interface.  This
  272  * is an attachment helper.  It must be called after ifp->if_addrlen
  273  * is initialized, which may not be the case when if_attach() is
  274  * called.
  275  */
  276 void
  277 if_alloc_sadl(struct ifnet *ifp)
  278 {
  279         unsigned socksize, ifasize;
  280         int namelen, masklen;
  281         struct sockaddr_dl *sdl;
  282         struct ifaddr *ifa;
  283 
  284         /*
  285          * If the interface already has a link name, release it
  286          * now.  This is useful for interfaces that can change
  287          * link types, and thus switch link names often.
  288          */
  289         if (ifp->if_sadl != NULL)
  290                 if_free_sadl(ifp);
  291 
  292         namelen = strlen(ifp->if_xname);
  293         masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
  294         socksize = masklen + ifp->if_addrlen;
  295 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  296         if (socksize < sizeof(*sdl))
  297                 socksize = sizeof(*sdl);
  298         socksize = ROUNDUP(socksize);
  299         ifasize = sizeof(*ifa) + 2 * socksize;
  300         ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
  301         memset((caddr_t)ifa, 0, ifasize);
  302         sdl = (struct sockaddr_dl *)(ifa + 1);
  303         sdl->sdl_len = socksize;
  304         sdl->sdl_family = AF_LINK;
  305         bcopy(ifp->if_xname, sdl->sdl_data, namelen);
  306         sdl->sdl_nlen = namelen;
  307         sdl->sdl_alen = ifp->if_addrlen;
  308         sdl->sdl_index = ifp->if_index;
  309         sdl->sdl_type = ifp->if_type;
  310         ifnet_addrs[ifp->if_index] = ifa;
  311         IFAREF(ifa);
  312         ifa->ifa_ifp = ifp;
  313         ifa->ifa_rtrequest = link_rtrequest;
  314         TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
  315         IFAREF(ifa);
  316         ifa->ifa_addr = (struct sockaddr *)sdl;
  317         ifp->if_sadl = sdl;
  318         sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  319         ifa->ifa_netmask = (struct sockaddr *)sdl;
  320         sdl->sdl_len = masklen;
  321         while (namelen != 0)
  322                 sdl->sdl_data[--namelen] = 0xff;
  323 }
  324 
  325 /*
  326  * Free the link level name for the specified interface.  This is
  327  * a detach helper.  This is called from if_detach() or from
  328  * link layer type specific detach functions.
  329  */
  330 void
  331 if_free_sadl(struct ifnet *ifp)
  332 {
  333         struct ifaddr *ifa;
  334         int s;
  335 
  336         ifa = ifnet_addrs[ifp->if_index];
  337         if (ifa == NULL) {
  338                 KASSERT(ifp->if_sadl == NULL);
  339                 return;
  340         }
  341 
  342         KASSERT(ifp->if_sadl != NULL);
  343 
  344         s = splnet();
  345         rtinit(ifa, RTM_DELETE, 0);
  346         TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
  347         IFAFREE(ifa);
  348 
  349         ifp->if_sadl = NULL;
  350 
  351         ifnet_addrs[ifp->if_index] = NULL;
  352         IFAFREE(ifa);
  353         splx(s);
  354 }
  355 
  356 /*
  357  * Attach an interface to the
  358  * list of "active" interfaces.
  359  */
  360 void
  361 if_attach(struct ifnet *ifp)
  362 {
  363         int indexlim = 0;
  364 
  365         if (if_indexlim == 0) {
  366                 TAILQ_INIT(&ifnet);
  367                 if_indexlim = 8;
  368         }
  369         TAILQ_INIT(&ifp->if_addrlist);
  370         TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
  371         ifp->if_index = if_index;
  372         if (ifindex2ifnet == 0)
  373                 if_index++;
  374         else
  375                 while (ifp->if_index < if_indexlim &&
  376                     ifindex2ifnet[ifp->if_index] != NULL) {
  377                         ++if_index;
  378                         if (if_index == 0)
  379                                 if_index = 1;
  380                         /*
  381                          * If we hit USHRT_MAX, we skip back to 0 since
  382                          * there are a number of places where the value
  383                          * of if_index or if_index itself is compared
  384                          * to or stored in an unsigned short.  By
  385                          * jumping back, we won't botch those assignments
  386                          * or comparisons.
  387                          */
  388                         else if (if_index == USHRT_MAX) {
  389                                 /*
  390                                  * However, if we have to jump back to
  391                                  * zero *twice* without finding an empty
  392                                  * slot in ifindex2ifnet[], then there
  393                                  * there are too many (>65535) interfaces.
  394                                  */
  395                                 if (indexlim++)
  396                                         panic("too many interfaces");
  397                                 else
  398                                         if_index = 1;
  399                         }
  400                         ifp->if_index = if_index;
  401                 }
  402 
  403         /*
  404          * We have some arrays that should be indexed by if_index.
  405          * since if_index will grow dynamically, they should grow too.
  406          *      struct ifadd **ifnet_addrs
  407          *      struct ifnet **ifindex2ifnet
  408          */
  409         if (ifnet_addrs == 0 || ifindex2ifnet == 0 ||
  410             ifp->if_index >= if_indexlim) {
  411                 size_t m, n, oldlim;
  412                 caddr_t q;
  413 
  414                 oldlim = if_indexlim;
  415                 while (ifp->if_index >= if_indexlim)
  416                         if_indexlim <<= 1;
  417 
  418                 /* grow ifnet_addrs */
  419                 m = oldlim * sizeof(struct ifaddr *);
  420                 n = if_indexlim * sizeof(struct ifaddr *);
  421                 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
  422                 memset(q, 0, n);
  423                 if (ifnet_addrs) {
  424                         bcopy((caddr_t)ifnet_addrs, q, m);
  425                         free((caddr_t)ifnet_addrs, M_IFADDR);
  426                 }
  427                 ifnet_addrs = (struct ifaddr **)q;
  428 
  429                 /* grow ifindex2ifnet */
  430                 m = oldlim * sizeof(struct ifnet *);
  431                 n = if_indexlim * sizeof(struct ifnet *);
  432                 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
  433                 memset(q, 0, n);
  434                 if (ifindex2ifnet) {
  435                         bcopy((caddr_t)ifindex2ifnet, q, m);
  436                         free((caddr_t)ifindex2ifnet, M_IFADDR);
  437                 }
  438                 ifindex2ifnet = (struct ifnet **)q;
  439         }
  440 
  441         ifindex2ifnet[ifp->if_index] = ifp;
  442 
  443         /*
  444          * Link level name is allocated later by a separate call to
  445          * if_alloc_sadl().
  446          */
  447 
  448         if (ifp->if_snd.ifq_maxlen == 0)
  449                 ifp->if_snd.ifq_maxlen = ifqmaxlen;
  450         ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
  451 
  452         ifp->if_link_state = LINK_STATE_UNKNOWN;
  453 
  454         ifp->if_capenable = 0;
  455         ifp->if_csum_flags_tx = 0;
  456         ifp->if_csum_flags_rx = 0;
  457 
  458 #ifdef ALTQ
  459         ifp->if_snd.altq_type = 0;
  460         ifp->if_snd.altq_disc = NULL;
  461         ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
  462         ifp->if_snd.altq_tbr  = NULL;
  463         ifp->if_snd.altq_ifp  = ifp;
  464 #endif
  465 
  466 #ifdef PFIL_HOOKS
  467         ifp->if_pfil.ph_type = PFIL_TYPE_IFNET;
  468         ifp->if_pfil.ph_ifnet = ifp;
  469         if (pfil_head_register(&ifp->if_pfil) != 0)
  470                 printf("%s: WARNING: unable to register pfil hook\n",
  471                     ifp->if_xname);
  472         (void)pfil_run_hooks(&if_pfil,
  473             (struct mbuf **)PFIL_IFNET_ATTACH, ifp, PFIL_IFNET);
  474 #endif
  475 
  476         if (!STAILQ_EMPTY(&domains))
  477                 if_attachdomain1(ifp);
  478 
  479         /* Announce the interface. */
  480         rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
  481 }
  482 
  483 void
  484 if_attachdomain(void)
  485 {
  486         struct ifnet *ifp;
  487         int s;
  488 
  489         s = splnet();
  490         TAILQ_FOREACH(ifp, &ifnet, if_list)
  491                 if_attachdomain1(ifp);
  492         splx(s);
  493 }
  494 
  495 void
  496 if_attachdomain1(struct ifnet *ifp)
  497 {
  498         struct domain *dp;
  499         int s;
  500 
  501         s = splnet();
  502 
  503         /* address family dependent data region */
  504         memset(ifp->if_afdata, 0, sizeof(ifp->if_afdata));
  505         DOMAIN_FOREACH(dp) {
  506                 if (dp->dom_ifattach)
  507                         ifp->if_afdata[dp->dom_family] =
  508                             (*dp->dom_ifattach)(ifp);
  509         }
  510 
  511         splx(s);
  512 }
  513 
  514 /*
  515  * Deactivate an interface.  This points all of the procedure
  516  * handles at error stubs.  May be called from interrupt context.
  517  */
  518 void
  519 if_deactivate(struct ifnet *ifp)
  520 {
  521         int s;
  522 
  523         s = splnet();
  524 
  525         ifp->if_output   = if_nulloutput;
  526         ifp->if_input    = if_nullinput;
  527         ifp->if_start    = if_nullstart;
  528         ifp->if_ioctl    = if_nullioctl;
  529         ifp->if_init     = if_nullinit;
  530         ifp->if_stop     = if_nullstop;
  531         ifp->if_watchdog = if_nullwatchdog;
  532         ifp->if_drain    = if_nulldrain;
  533 
  534         /* No more packets may be enqueued. */
  535         ifp->if_snd.ifq_maxlen = 0;
  536 
  537         splx(s);
  538 }
  539 
  540 /*
  541  * Detach an interface from the list of "active" interfaces,
  542  * freeing any resources as we go along.
  543  *
  544  * NOTE: This routine must be called with a valid thread context,
  545  * as it may block.
  546  */
  547 void
  548 if_detach(struct ifnet *ifp)
  549 {
  550         struct socket so;
  551         struct ifaddr *ifa;
  552 #ifdef IFAREF_DEBUG
  553         struct ifaddr *last_ifa = NULL;
  554 #endif
  555         struct domain *dp;
  556         const struct protosw *pr;
  557         struct radix_node_head *rnh;
  558         int s, i, family, purged;
  559 
  560         /*
  561          * XXX It's kind of lame that we have to have the
  562          * XXX socket structure...
  563          */
  564         memset(&so, 0, sizeof(so));
  565 
  566         s = splnet();
  567 
  568         /*
  569          * Do an if_down() to give protocols a chance to do something.
  570          */
  571         if_down(ifp);
  572 
  573 #ifdef ALTQ
  574         if (ALTQ_IS_ENABLED(&ifp->if_snd))
  575                 altq_disable(&ifp->if_snd);
  576         if (ALTQ_IS_ATTACHED(&ifp->if_snd))
  577                 altq_detach(&ifp->if_snd);
  578 #endif
  579 
  580 
  581 #if NCARP > 0
  582         /* Remove the interface from any carp group it is a part of.  */
  583         if (ifp->if_carp && ifp->if_type != IFT_CARP)
  584                 carp_ifdetach(ifp);
  585 #endif
  586 
  587 #ifdef PFIL_HOOKS
  588         (void)pfil_run_hooks(&if_pfil,
  589             (struct mbuf **)PFIL_IFNET_DETACH, ifp, PFIL_IFNET);
  590         (void)pfil_head_unregister(&ifp->if_pfil);
  591 #endif
  592 
  593         /*
  594          * Rip all the addresses off the interface.  This should make
  595          * all of the routes go away.
  596          *
  597          * pr_usrreq calls can remove an arbitrary number of ifaddrs
  598          * from the list, including our "cursor", ifa.  For safety,
  599          * and to honor the TAILQ abstraction, I just restart the
  600          * loop after each removal.  Note that the loop will exit
  601          * when all of the remaining ifaddrs belong to the AF_LINK
  602          * family.  I am counting on the historical fact that at
  603          * least one pr_usrreq in each address domain removes at
  604          * least one ifaddr.
  605          */
  606 again:
  607         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  608                 family = ifa->ifa_addr->sa_family;
  609 #ifdef IFAREF_DEBUG
  610                 printf("if_detach: ifaddr %p, family %d, refcnt %d\n",
  611                     ifa, family, ifa->ifa_refcnt);
  612                 if (last_ifa != NULL && ifa == last_ifa)
  613                         panic("if_detach: loop detected");
  614                 last_ifa = ifa;
  615 #endif
  616                 if (family == AF_LINK)
  617                         continue;
  618                 dp = pffinddomain(family);
  619 #ifdef DIAGNOSTIC
  620                 if (dp == NULL)
  621                         panic("if_detach: no domain for AF %d",
  622                             family);
  623 #endif
  624                 /*
  625                  * XXX These PURGEIF calls are redundant with the
  626                  * purge-all-families calls below, but are left in for
  627                  * now both to make a smaller change, and to avoid
  628                  * unplanned interactions with clearing of
  629                  * ifp->if_addrlist.
  630                  */
  631                 purged = 0;
  632                 for (pr = dp->dom_protosw;
  633                      pr < dp->dom_protoswNPROTOSW; pr++) {
  634                         so.so_proto = pr;
  635                         if (pr->pr_usrreq != NULL) {
  636                                 (void) (*pr->pr_usrreq)(&so,
  637                                     PRU_PURGEIF, NULL, NULL,
  638                                     (struct mbuf *) ifp, curlwp);
  639                                 purged = 1;
  640                         }
  641                 }
  642                 if (purged == 0) {
  643                         /*
  644                          * XXX What's really the best thing to do
  645                          * XXX here?  --thorpej@NetBSD.org
  646                          */
  647                         printf("if_detach: WARNING: AF %d not purged\n",
  648                             family);
  649                         TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
  650                 }
  651                 goto again;
  652         }
  653 
  654         if_free_sadl(ifp);
  655 
  656         /* Walk the routing table looking for straglers. */
  657         for (i = 0; i <= AF_MAX; i++) {
  658                 if ((rnh = rt_tables[i]) != NULL)
  659                         (void) (*rnh->rnh_walktree)(rnh, if_rt_walktree, ifp);
  660         }
  661 
  662         DOMAIN_FOREACH(dp) {
  663                 if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
  664                         (*dp->dom_ifdetach)(ifp,
  665                             ifp->if_afdata[dp->dom_family]);
  666 
  667                 /*
  668                  * One would expect multicast memberships (INET and
  669                  * INET6) on UDP sockets to be purged by the PURGEIF
  670                  * calls above, but if all addresses were removed from
  671                  * the interface prior to destruction, the calls will
  672                  * not be made (e.g. ppp, for which pppd(8) generally
  673                  * removes addresses before destroying the interface).
  674                  * Because there is no invariant that multicast
  675                  * memberships only exist for interfaces with IPv4
  676                  * addresses, we must call PURGEIF regardless of
  677                  * addresses.  (Protocols which might store ifnet
  678                  * pointers are marked with PR_PURGEIF.)
  679                  */
  680                 for (pr = dp->dom_protosw;
  681                      pr < dp->dom_protoswNPROTOSW; pr++) {
  682                         so.so_proto = pr;
  683                         if (pr->pr_usrreq != NULL &&
  684                             pr->pr_flags & PR_PURGEIF)
  685                                 (void) (*pr->pr_usrreq)(&so,
  686                                     PRU_PURGEIF, NULL, NULL,
  687                                     (struct mbuf *) ifp, curlwp);
  688                 }
  689         }
  690 
  691         /* Announce that the interface is gone. */
  692         rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
  693 
  694         ifindex2ifnet[ifp->if_index] = NULL;
  695 
  696         TAILQ_REMOVE(&ifnet, ifp, if_list);
  697 
  698         /*
  699          * remove packets that came from ifp, from software interrupt queues.
  700          */
  701         DOMAIN_FOREACH(dp) {
  702                 for (i = 0; i < __arraycount(dp->dom_ifqueues); i++) {
  703                         if (dp->dom_ifqueues[i] == NULL)
  704                                 break;
  705                         if_detach_queues(ifp, dp->dom_ifqueues[i]);
  706                 }
  707         }
  708 
  709         splx(s);
  710 }
  711 
  712 static void
  713 if_detach_queues(struct ifnet *ifp, struct ifqueue *q)
  714 {
  715         struct mbuf *m, *prev, *next;
  716 
  717         prev = NULL;
  718         for (m = q->ifq_head; m; m = next) {
  719                 next = m->m_nextpkt;
  720 #ifdef DIAGNOSTIC
  721                 if ((m->m_flags & M_PKTHDR) == 0) {
  722                         prev = m;
  723                         continue;
  724                 }
  725 #endif
  726                 if (m->m_pkthdr.rcvif != ifp) {
  727                         prev = m;
  728                         continue;
  729                 }
  730 
  731                 if (prev)
  732                         prev->m_nextpkt = m->m_nextpkt;
  733                 else
  734                         q->ifq_head = m->m_nextpkt;
  735                 if (q->ifq_tail == m)
  736                         q->ifq_tail = prev;
  737                 q->ifq_len--;
  738 
  739                 m->m_nextpkt = NULL;
  740                 m_freem(m);
  741                 IF_DROP(q);
  742         }
  743 }
  744 
  745 /*
  746  * Callback for a radix tree walk to delete all references to an
  747  * ifnet.
  748  */
  749 static int
  750 if_rt_walktree(struct radix_node *rn, void *v)
  751 {
  752         struct ifnet *ifp = (struct ifnet *)v;
  753         struct rtentry *rt = (struct rtentry *)rn;
  754         int error;
  755 
  756         if (rt->rt_ifp == ifp) {
  757                 /* Delete the entry. */
  758                 error = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
  759                     rt_mask(rt), rt->rt_flags, NULL);
  760                 if (error)
  761                         printf("%s: warning: unable to delete rtentry @ %p, "
  762                             "error = %d\n", ifp->if_xname, rt, error);
  763         }
  764         return (0);
  765 }
  766 
  767 /*
  768  * Create a clone network interface.
  769  */
  770 int
  771 if_clone_create(const char *name)
  772 {
  773         struct if_clone *ifc;
  774         int unit;
  775 
  776         ifc = if_clone_lookup(name, &unit);
  777         if (ifc == NULL)
  778                 return (EINVAL);
  779 
  780         if (ifunit(name) != NULL)
  781                 return (EEXIST);
  782 
  783         return ((*ifc->ifc_create)(ifc, unit));
  784 }
  785 
  786 /*
  787  * Destroy a clone network interface.
  788  */
  789 int
  790 if_clone_destroy(const char *name)
  791 {
  792         struct if_clone *ifc;
  793         struct ifnet *ifp;
  794 
  795         ifc = if_clone_lookup(name, NULL);
  796         if (ifc == NULL)
  797                 return (EINVAL);
  798 
  799         ifp = ifunit(name);
  800         if (ifp == NULL)
  801                 return (ENXIO);
  802 
  803         if (ifc->ifc_destroy == NULL)
  804                 return (EOPNOTSUPP);
  805 
  806         return ((*ifc->ifc_destroy)(ifp));
  807 }
  808 
  809 /*
  810  * Look up a network interface cloner.
  811  */
  812 static struct if_clone *
  813 if_clone_lookup(const char *name, int *unitp)
  814 {
  815         struct if_clone *ifc;
  816         const char *cp;
  817         int unit;
  818 
  819         /* separate interface name from unit */
  820         for (cp = name;
  821             cp - name < IFNAMSIZ && *cp && (*cp < '' || *cp > '9');
  822             cp++)
  823                 continue;
  824 
  825         if (cp == name || cp - name == IFNAMSIZ || !*cp)
  826                 return (NULL);  /* No name or unit number */
  827 
  828         LIST_FOREACH(ifc, &if_cloners, ifc_list) {
  829                 if (strlen(ifc->ifc_name) == cp - name &&
  830                     !strncmp(name, ifc->ifc_name, cp - name))
  831                         break;
  832         }
  833 
  834         if (ifc == NULL)
  835                 return (NULL);
  836 
  837         unit = 0;
  838         while (cp - name < IFNAMSIZ && *cp) {
  839                 if (*cp < '' || *cp > '9' || unit > INT_MAX / 10) {
  840                         /* Bogus unit number. */
  841                         return (NULL);
  842                 }
  843                 unit = (unit * 10) + (*cp++ - '');
  844         }
  845 
  846         if (unitp != NULL)
  847                 *unitp = unit;
  848         return (ifc);
  849 }
  850 
  851 /*
  852  * Register a network interface cloner.
  853  */
  854 void
  855 if_clone_attach(struct if_clone *ifc)
  856 {
  857 
  858         LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
  859         if_cloners_count++;
  860 }
  861 
  862 /*
  863  * Unregister a network interface cloner.
  864  */
  865 void
  866 if_clone_detach(struct if_clone *ifc)
  867 {
  868 
  869         LIST_REMOVE(ifc, ifc_list);
  870         if_cloners_count--;
  871 }
  872 
  873 /*
  874  * Provide list of interface cloners to userspace.
  875  */
  876 static int
  877 if_clone_list(struct if_clonereq *ifcr)
  878 {
  879         char outbuf[IFNAMSIZ], *dst;
  880         struct if_clone *ifc;
  881         int count, error = 0;
  882 
  883         ifcr->ifcr_total = if_cloners_count;
  884         if ((dst = ifcr->ifcr_buffer) == NULL) {
  885                 /* Just asking how many there are. */
  886                 return (0);
  887         }
  888 
  889         if (ifcr->ifcr_count < 0)
  890                 return (EINVAL);
  891 
  892         count = (if_cloners_count < ifcr->ifcr_count) ?
  893             if_cloners_count : ifcr->ifcr_count;
  894 
  895         for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
  896              ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
  897                 (void)strncpy(outbuf, ifc->ifc_name, sizeof(outbuf));
  898                 if (outbuf[sizeof(outbuf) - 1] != '\0')
  899                         return ENAMETOOLONG;
  900                 error = copyout(outbuf, dst, sizeof(outbuf));
  901                 if (error)
  902                         break;
  903         }
  904 
  905         return (error);
  906 }
  907 
  908 /*
  909  * Locate an interface based on a complete address.
  910  */
  911 /*ARGSUSED*/
  912 struct ifaddr *
  913 ifa_ifwithaddr(const struct sockaddr *addr)
  914 {
  915         struct ifnet *ifp;
  916         struct ifaddr *ifa;
  917 
  918 #define equal(a1, a2) \
  919   (bcmp((a1), (a2), ((const struct sockaddr *)(a1))->sa_len) == 0)
  920 
  921         TAILQ_FOREACH(ifp, &ifnet, if_list) {
  922                 if (ifp->if_output == if_nulloutput)
  923                         continue;
  924                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  925                         if (ifa->ifa_addr->sa_family != addr->sa_family)
  926                                 continue;
  927                         if (equal(addr, ifa->ifa_addr))
  928                                 return (ifa);
  929                         if ((ifp->if_flags & IFF_BROADCAST) &&
  930                             ifa->ifa_broadaddr &&
  931                             /* IP6 doesn't have broadcast */
  932                             ifa->ifa_broadaddr->sa_len != 0 &&
  933                             equal(ifa->ifa_broadaddr, addr))
  934                                 return (ifa);
  935                 }
  936         }
  937         return (NULL);
  938 }
  939 
  940 /*
  941  * Locate the point to point interface with a given destination address.
  942  */
  943 /*ARGSUSED*/
  944 struct ifaddr *
  945 ifa_ifwithdstaddr(const struct sockaddr *addr)
  946 {
  947         struct ifnet *ifp;
  948         struct ifaddr *ifa;
  949 
  950         TAILQ_FOREACH(ifp, &ifnet, if_list) {
  951                 if (ifp->if_output == if_nulloutput)
  952                         continue;
  953                 if (ifp->if_flags & IFF_POINTOPOINT) {
  954                         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  955                                 if (ifa->ifa_addr->sa_family !=
  956                                       addr->sa_family ||
  957                                     ifa->ifa_dstaddr == NULL)
  958                                         continue;
  959                                 if (equal(addr, ifa->ifa_dstaddr))
  960                                         return (ifa);
  961                         }
  962                 }
  963         }
  964         return (NULL);
  965 }
  966 
  967 /*
  968  * Find an interface on a specific network.  If many, choice
  969  * is most specific found.
  970  */
  971 struct ifaddr *
  972 ifa_ifwithnet(const struct sockaddr *addr)
  973 {
  974         struct ifnet *ifp;
  975         struct ifaddr *ifa;
  976         const struct sockaddr_dl *sdl;
  977         struct ifaddr *ifa_maybe = 0;
  978         u_int af = addr->sa_family;
  979         const char *addr_data = addr->sa_data, *cplim;
  980 
  981         if (af == AF_LINK) {
  982                 sdl = (const struct sockaddr_dl *)addr;
  983                 if (sdl->sdl_index && sdl->sdl_index < if_indexlim &&
  984                     ifindex2ifnet[sdl->sdl_index] &&
  985                     ifindex2ifnet[sdl->sdl_index]->if_output != if_nulloutput)
  986                         return (ifnet_addrs[sdl->sdl_index]);
  987         }
  988 #ifdef NETATALK
  989         if (af == AF_APPLETALK) {
  990                 const struct sockaddr_at *sat, *sat2;
  991                 sat = (const struct sockaddr_at *)addr;
  992                 TAILQ_FOREACH(ifp, &ifnet, if_list) {
  993                         if (ifp->if_output == if_nulloutput)
  994                                 continue;
  995                         ifa = at_ifawithnet((const struct sockaddr_at *)addr, ifp);
  996                         if (ifa == NULL)
  997                                 continue;
  998                         sat2 = (struct sockaddr_at *)ifa->ifa_addr;
  999                         if (sat2->sat_addr.s_net == sat->sat_addr.s_net)
 1000                                 return (ifa); /* exact match */
 1001                         if (ifa_maybe == NULL) {
 1002                                 /* else keep the if with the right range */
 1003                                 ifa_maybe = ifa;
 1004                         }
 1005                 }
 1006                 return (ifa_maybe);
 1007         }
 1008 #endif
 1009         TAILQ_FOREACH(ifp, &ifnet, if_list) {
 1010                 if (ifp->if_output == if_nulloutput)
 1011                         continue;
 1012                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
 1013                         const char *cp, *cp2, *cp3;
 1014 
 1015                         if (ifa->ifa_addr->sa_family != af ||
 1016                             ifa->ifa_netmask == 0)
 1017  next:                          continue;
 1018                         cp = addr_data;
 1019                         cp2 = ifa->ifa_addr->sa_data;
 1020                         cp3 = ifa->ifa_netmask->sa_data;
 1021                         cplim = (const char *)ifa->ifa_netmask +
 1022                             ifa->ifa_netmask->sa_len;
 1023                         while (cp3 < cplim) {
 1024                                 if ((*cp++ ^ *cp2++) & *cp3++) {
 1025                                         /* want to continue for() loop */
 1026                                         goto next;
 1027                                 }
 1028                         }
 1029                         if (ifa_maybe == 0 ||
 1030                             rn_refines((caddr_t)ifa->ifa_netmask,
 1031                             (caddr_t)ifa_maybe->ifa_netmask))
 1032                                 ifa_maybe = ifa;
 1033                 }
 1034         }
 1035         return (ifa_maybe);
 1036 }
 1037 
 1038 /*
 1039  * Find the interface of the addresss.
 1040  */
 1041 struct ifaddr *
 1042 ifa_ifwithladdr(const struct sockaddr *addr)
 1043 {
 1044         struct ifaddr *ia;
 1045 
 1046         if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr)) ||
 1047             (ia = ifa_ifwithnet(addr)))
 1048                 return (ia);
 1049         return (NULL);
 1050 }
 1051 
 1052 /*
 1053  * Find an interface using a specific address family
 1054  */
 1055 struct ifaddr *
 1056 ifa_ifwithaf(int af)
 1057 {
 1058         struct ifnet *ifp;
 1059         struct ifaddr *ifa;
 1060 
 1061         TAILQ_FOREACH(ifp, &ifnet, if_list) {
 1062                 if (ifp->if_output == if_nulloutput)
 1063                         continue;
 1064                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
 1065                         if (ifa->ifa_addr->sa_family == af)
 1066                                 return ifa;
 1067                 }
 1068         }
 1069         return NULL;
 1070 }
 1071 
 1072 /*
 1073  * Find an interface address specific to an interface best matching
 1074  * a given address.
 1075  */
 1076 struct ifaddr *
 1077 ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
 1078 {
 1079         struct ifaddr *ifa;
 1080         const char *cp, *cp2, *cp3;
 1081         const char *cplim;
 1082         struct ifaddr *ifa_maybe = 0;
 1083         u_int af = addr->sa_family;
 1084 
 1085         if (ifp->if_output == if_nulloutput)
 1086                 return (NULL);
 1087 
 1088         if (af >= AF_MAX)
 1089                 return (NULL);
 1090 
 1091         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
 1092                 if (ifa->ifa_addr->sa_family != af)
 1093                         continue;
 1094                 ifa_maybe = ifa;
 1095                 if (ifa->ifa_netmask == 0) {
 1096                         if (equal(addr, ifa->ifa_addr) ||
 1097                             (ifa->ifa_dstaddr &&
 1098                              equal(addr, ifa->ifa_dstaddr)))
 1099                                 return (ifa);
 1100                         continue;
 1101                 }
 1102                 cp = addr->sa_data;
 1103                 cp2 = ifa->ifa_addr->sa_data;
 1104                 cp3 = ifa->ifa_netmask->sa_data;
 1105                 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
 1106                 for (; cp3 < cplim; cp3++) {
 1107                         if ((*cp++ ^ *cp2++) & *cp3)
 1108                                 break;
 1109                 }
 1110                 if (cp3 == cplim)
 1111                         return (ifa);
 1112         }
 1113         return (ifa_maybe);
 1114 }
 1115 
 1116 /*
 1117  * Default action when installing a route with a Link Level gateway.
 1118  * Lookup an appropriate real ifa to point to.
 1119  * This should be moved to /sys/net/link.c eventually.
 1120  */
 1121 void
 1122 link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
 1123 {
 1124         struct ifaddr *ifa;
 1125         struct sockaddr *dst;
 1126         struct ifnet *ifp;
 1127 
 1128         if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
 1129             ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
 1130                 return;
 1131         if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
 1132                 rt_replace_ifa(rt, ifa);
 1133                 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
 1134                         ifa->ifa_rtrequest(cmd, rt, info);
 1135         }
 1136 }
 1137 
 1138 /*
 1139  * Handle a change in the interface link state.
 1140  */
 1141 void
 1142 if_link_state_change(struct ifnet *ifp, int link_state)
 1143 {
 1144         /* Notify that the link state has changed. */
 1145         if (ifp->if_link_state != link_state) {
 1146                 ifp->if_link_state = link_state;
 1147                 rt_ifmsg(ifp);
 1148 #if NCARP > 0
 1149                 if (ifp->if_carp)
 1150                         carp_carpdev_state(ifp);
 1151 #endif
 1152         }
 1153 }
 1154 
 1155 /*
 1156  * Mark an interface down and notify protocols of
 1157  * the transition.
 1158  * NOTE: must be called at splsoftnet or equivalent.
 1159  */
 1160 void
 1161 if_down(struct ifnet *ifp)
 1162 {
 1163         struct ifaddr *ifa;
 1164 
 1165         ifp->if_flags &= ~IFF_UP;
 1166         microtime(&ifp->if_lastchange);
 1167         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
 1168                 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
 1169         IFQ_PURGE(&ifp->if_snd);
 1170 #if NCARP > 0
 1171         if (ifp->if_carp)
 1172                 carp_carpdev_state(ifp);
 1173 #endif
 1174         rt_ifmsg(ifp);
 1175 }
 1176 
 1177 /*
 1178  * Mark an interface up and notify protocols of
 1179  * the transition.
 1180  * NOTE: must be called at splsoftnet or equivalent.
 1181  */
 1182 void
 1183 if_up(struct ifnet *ifp)
 1184 {
 1185 #ifdef notyet
 1186         struct ifaddr *ifa;
 1187 #endif
 1188 
 1189         ifp->if_flags |= IFF_UP;
 1190         microtime(&ifp->if_lastchange);
 1191 #ifdef notyet
 1192         /* this has no effect on IP, and will kill all ISO connections XXX */
 1193         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
 1194                 pfctlinput(PRC_IFUP, ifa->ifa_addr);
 1195 #endif
 1196 #if NCARP > 0
 1197         if (ifp->if_carp)
 1198                 carp_carpdev_state(ifp);
 1199 #endif
 1200         rt_ifmsg(ifp);
 1201 #ifdef INET6
 1202         in6_if_up(ifp);
 1203 #endif
 1204 }
 1205 
 1206 /*
 1207  * Handle interface watchdog timer routines.  Called
 1208  * from softclock, we decrement timers (if set) and
 1209  * call the appropriate interface routine on expiration.
 1210  */
 1211 void
 1212 if_slowtimo(void *arg)
 1213 {
 1214         struct ifnet *ifp;
 1215         int s = splnet();
 1216 
 1217         TAILQ_FOREACH(ifp, &ifnet, if_list) {
 1218                 if (ifp->if_timer == 0 || --ifp->if_timer)
 1219                         continue;
 1220                 if (ifp->if_watchdog)
 1221                         (*ifp->if_watchdog)(ifp);
 1222         }
 1223         splx(s);
 1224         callout_reset(&if_slowtimo_ch, hz / IFNET_SLOWHZ,
 1225             if_slowtimo, NULL);
 1226 }
 1227 
 1228 /*
 1229  * Set/clear promiscuous mode on interface ifp based on the truth value
 1230  * of pswitch.  The calls are reference counted so that only the first
 1231  * "on" request actually has an effect, as does the final "off" request.
 1232  * Results are undefined if the "off" and "on" requests are not matched.
 1233  */
 1234 int
 1235 ifpromisc(struct ifnet *ifp, int pswitch)
 1236 {
 1237         int pcount, ret;
 1238         short flags;
 1239         struct ifreq ifr;
 1240 
 1241         pcount = ifp->if_pcount;
 1242         flags = ifp->if_flags;
 1243         if (pswitch) {
 1244                 /*
 1245                  * Allow the device to be "placed" into promiscuous
 1246                  * mode even if it is not configured up.  It will
 1247                  * consult IFF_PROMISC when it is is brought up.
 1248                  */
 1249                 if (ifp->if_pcount++ != 0)
 1250                         return (0);
 1251                 ifp->if_flags |= IFF_PROMISC;
 1252                 if ((ifp->if_flags & IFF_UP) == 0)
 1253                         return (0);
 1254         } else {
 1255                 if (--ifp->if_pcount > 0)
 1256                         return (0);
 1257                 ifp->if_flags &= ~IFF_PROMISC;
 1258                 /*
 1259                  * If the device is not configured up, we should not need to
 1260                  * turn off promiscuous mode (device should have turned it
 1261                  * off when interface went down; and will look at IFF_PROMISC
 1262                  * again next time interface comes up).
 1263                  */
 1264                 if ((ifp->if_flags & IFF_UP) == 0)
 1265                         return (0);
 1266         }
 1267         memset(&ifr, 0, sizeof(ifr));
 1268         ifr.ifr_flags = ifp->if_flags;
 1269         ret = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t) &ifr);
 1270         /* Restore interface state if not successful. */
 1271         if (ret != 0) {
 1272                 ifp->if_pcount = pcount;
 1273                 ifp->if_flags = flags;
 1274         }
 1275         return (ret);
 1276 }
 1277 
 1278 /*
 1279  * Map interface name to
 1280  * interface structure pointer.
 1281  */
 1282 struct ifnet *
 1283 ifunit(const char *name)
 1284 {
 1285         struct ifnet *ifp;
 1286         const char *cp = name;
 1287         u_int unit = 0;
 1288         u_int i;
 1289 
 1290         /*
 1291          * If the entire name is a number, treat it as an ifindex.
 1292          */
 1293         for (i = 0; i < IFNAMSIZ && *cp >= '' && *cp <= '9'; i++, cp++) {
 1294                 unit = unit * 10 + (*cp - '');
 1295         }
 1296 
 1297         /*
 1298          * If the number took all of the name, then it's a valid ifindex.
 1299          */
 1300         if (i == IFNAMSIZ || (cp != name && *cp == '\0')) {
 1301                 if (unit >= if_indexlim)
 1302                         return (NULL);
 1303                 ifp = ifindex2ifnet[unit];
 1304                 if (ifp == NULL || ifp->if_output == if_nulloutput)
 1305                         return (NULL);
 1306                 return (ifp);
 1307         }
 1308 
 1309         TAILQ_FOREACH(ifp, &ifnet, if_list) {
 1310                 if (ifp->if_output == if_nulloutput)
 1311                         continue;
 1312                 if (strcmp(ifp->if_xname, name) == 0)
 1313                         return (ifp);
 1314         }
 1315         return (NULL);
 1316 }
 1317 
 1318 /*
 1319  * Interface ioctls.
 1320  */
 1321 int
 1322 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct lwp *l)
 1323 {
 1324         struct ifnet *ifp;
 1325         struct ifreq *ifr;
 1326         struct ifcapreq *ifcr;
 1327         struct ifdatareq *ifdr;
 1328         int s, error = 0;
 1329         short oif_flags;
 1330 
 1331         switch (cmd) {
 1332 
 1333         case SIOCGIFCONF:
 1334         case OSIOCGIFCONF:
 1335                 return (ifconf(cmd, data));
 1336         }
 1337         ifr = (struct ifreq *)data;
 1338         ifcr = (struct ifcapreq *)data;
 1339         ifdr = (struct ifdatareq *)data;
 1340 
 1341         ifp = ifunit(ifr->ifr_name);
 1342 
 1343         switch (cmd) {
 1344         case SIOCIFCREATE:
 1345         case SIOCIFDESTROY:
 1346                 if (l) {
 1347                         error = kauth_authorize_network(l->l_cred,
 1348                             KAUTH_NETWORK_INTERFACE,
 1349                             KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
 1350                             (void *)cmd, NULL);
 1351                         if (error)
 1352                                 return error;
 1353                 }
 1354                 return ((cmd == SIOCIFCREATE) ?
 1355                         if_clone_create(ifr->ifr_name) :
 1356                         if_clone_destroy(ifr->ifr_name));
 1357 
 1358         case SIOCIFGCLONERS:
 1359                 return (if_clone_list((struct if_clonereq *)data));
 1360         }
 1361 
 1362         if (ifp == 0)
 1363                 return (ENXIO);
 1364 
 1365         switch (cmd) {
 1366         case SIOCSIFFLAGS:
 1367         case SIOCSIFCAP:
 1368         case SIOCSIFMETRIC:
 1369         case SIOCZIFDATA:
 1370         case SIOCSIFMTU:
 1371         case SIOCSIFPHYADDR:
 1372         case SIOCDIFPHYADDR:
 1373 #ifdef INET6
 1374         case SIOCSIFPHYADDR_IN6:
 1375 #endif
 1376         case SIOCSLIFPHYADDR:
 1377         case SIOCADDMULTI:
 1378         case SIOCDELMULTI:
 1379         case SIOCSIFMEDIA:
 1380         case SIOCSDRVSPEC:
 1381         case SIOCS80211NWID:
 1382         case SIOCS80211NWKEY:
 1383         case SIOCS80211POWER:
 1384         case SIOCS80211BSSID:
 1385         case SIOCS80211CHANNEL:
 1386                 if (l) {
 1387                         error = kauth_authorize_network(l->l_cred,
 1388                             KAUTH_NETWORK_INTERFACE,
 1389                             KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
 1390                             (void *)cmd, NULL);
 1391                         if (error)
 1392                                 return error;
 1393                 }
 1394         }
 1395 
 1396         oif_flags = ifp->if_flags;
 1397         switch (cmd) {
 1398 
 1399         case SIOCGIFFLAGS:
 1400                 ifr->ifr_flags = ifp->if_flags;
 1401                 break;
 1402 
 1403         case SIOCGIFMETRIC:
 1404                 ifr->ifr_metric = ifp->if_metric;
 1405                 break;
 1406 
 1407         case SIOCGIFMTU:
 1408                 ifr->ifr_mtu = ifp->if_mtu;
 1409                 break;
 1410 
 1411         case SIOCGIFDLT:
 1412                 ifr->ifr_dlt = ifp->if_dlt;
 1413                 break;
 1414 
 1415         case SIOCSIFFLAGS:
 1416                 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
 1417                         s = splnet();
 1418                         if_down(ifp);
 1419                         splx(s);
 1420                 }
 1421                 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
 1422                         s = splnet();
 1423                         if_up(ifp);
 1424                         splx(s);
 1425                 }
 1426                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
 1427                         (ifr->ifr_flags &~ IFF_CANTCHANGE);
 1428                 if (ifp->if_ioctl)
 1429                         (void) (*ifp->if_ioctl)(ifp, cmd, data);
 1430                 break;
 1431 
 1432         case SIOCGIFCAP:
 1433                 ifcr->ifcr_capabilities = ifp->if_capabilities;
 1434                 ifcr->ifcr_capenable = ifp->if_capenable;
 1435                 break;
 1436 
 1437         case SIOCSIFCAP:
 1438                 if ((ifcr->ifcr_capenable & ~ifp->if_capabilities) != 0)
 1439                         return (EINVAL);
 1440                 if (ifp->if_ioctl == NULL)
 1441                         return (EOPNOTSUPP);
 1442 
 1443                 /* Must prevent race with packet reception here. */
 1444                 s = splnet();
 1445                 if (ifcr->ifcr_capenable != ifp->if_capenable) {
 1446                         struct ifreq ifrq;
 1447 
 1448                         ifrq.ifr_flags = ifp->if_flags;
 1449                         ifp->if_capenable = ifcr->ifcr_capenable;
 1450 
 1451                         /* Pre-compute the checksum flags mask. */
 1452                         ifp->if_csum_flags_tx = 0;
 1453                         ifp->if_csum_flags_rx = 0;
 1454                         if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) {
 1455                                 ifp->if_csum_flags_tx |= M_CSUM_IPv4;
 1456                         }
 1457                         if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) {
 1458                                 ifp->if_csum_flags_rx |= M_CSUM_IPv4;
 1459                         }
 1460 
 1461                         if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) {
 1462                                 ifp->if_csum_flags_tx |= M_CSUM_TCPv4;
 1463                         }
 1464                         if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) {
 1465                                 ifp->if_csum_flags_rx |= M_CSUM_TCPv4;
 1466                         }
 1467 
 1468                         if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) {
 1469                                 ifp->if_csum_flags_tx |= M_CSUM_UDPv4;
 1470                         }
 1471                         if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) {
 1472                                 ifp->if_csum_flags_rx |= M_CSUM_UDPv4;
 1473                         }
 1474 
 1475                         if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx) {
 1476                                 ifp->if_csum_flags_tx |= M_CSUM_TCPv6;
 1477                         }
 1478                         if (ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) {
 1479                                 ifp->if_csum_flags_rx |= M_CSUM_TCPv6;
 1480                         }
 1481 
 1482                         if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx) {
 1483                                 ifp->if_csum_flags_tx |= M_CSUM_UDPv6;
 1484                         }
 1485                         if (ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) {
 1486                                 ifp->if_csum_flags_rx |= M_CSUM_UDPv6;
 1487                         }
 1488 
 1489                         /*
 1490                          * Only kick the interface if it's up.  If it's
 1491                          * not up now, it will notice the cap enables
 1492                          * when it is brought up later.
 1493                          */
 1494                         if (ifp->if_flags & IFF_UP)
 1495                                 (void) (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS,
 1496                                     (caddr_t) &ifrq);
 1497                 }
 1498                 splx(s);
 1499                 break;
 1500 
 1501         case SIOCSIFMETRIC:
 1502                 ifp->if_metric = ifr->ifr_metric;
 1503                 break;
 1504 
 1505         case SIOCGIFDATA:
 1506                 ifdr->ifdr_data = ifp->if_data;
 1507                 break;
 1508 
 1509         case SIOCZIFDATA:
 1510                 ifdr->ifdr_data = ifp->if_data;
 1511                 /*
 1512                  * Assumes that the volatile counters that can be
 1513                  * zero'ed are at the end of if_data.
 1514                  */
 1515                 memset(&ifp->if_data.ifi_ipackets, 0, sizeof(ifp->if_data) -
 1516                     offsetof(struct if_data, ifi_ipackets));
 1517                 break;
 1518 
 1519         case SIOCSIFMTU:
 1520         {
 1521                 u_long oldmtu = ifp->if_mtu;
 1522 
 1523                 if (ifp->if_ioctl == NULL)
 1524                         return (EOPNOTSUPP);
 1525                 error = (*ifp->if_ioctl)(ifp, cmd, data);
 1526 
 1527                 /*
 1528                  * If the link MTU changed, do network layer specific procedure.
 1529                  */
 1530                 if (ifp->if_mtu != oldmtu) {
 1531 #ifdef INET6
 1532                         nd6_setmtu(ifp);
 1533 #endif
 1534                 }
 1535                 break;
 1536         }
 1537         case SIOCSIFPHYADDR:
 1538         case SIOCDIFPHYADDR:
 1539 #ifdef INET6
 1540         case SIOCSIFPHYADDR_IN6:
 1541 #endif
 1542         case SIOCSLIFPHYADDR:
 1543         case SIOCADDMULTI:
 1544         case SIOCDELMULTI:
 1545         case SIOCSIFMEDIA:
 1546         case SIOCGIFPSRCADDR:
 1547         case SIOCGIFPDSTADDR:
 1548         case SIOCGLIFPHYADDR:
 1549         case SIOCGIFMEDIA:
 1550                 if (ifp->if_ioctl == 0)
 1551                         return (EOPNOTSUPP);
 1552                 error = (*ifp->if_ioctl)(ifp, cmd, data);
 1553                 break;
 1554 
 1555         case SIOCSDRVSPEC:
 1556         case SIOCS80211NWID:
 1557         case SIOCS80211NWKEY:
 1558         case SIOCS80211POWER:
 1559         case SIOCS80211BSSID:
 1560         case SIOCS80211CHANNEL:
 1561         default:
 1562                 if (so->so_proto == 0)
 1563                         return (EOPNOTSUPP);
 1564 #ifdef COMPAT_OSOCK
 1565                 error = compat_ifioctl(so, cmd, data, l);
 1566 #else
 1567                 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
 1568                     (struct mbuf *)cmd, (struct mbuf *)data,
 1569                     (struct mbuf *)ifp, l));
 1570 #endif
 1571                 break;
 1572         }
 1573 
 1574         if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
 1575 #ifdef INET6
 1576                 if ((ifp->if_flags & IFF_UP) != 0) {
 1577                         s = splnet();
 1578                         in6_if_up(ifp);
 1579                         splx(s);
 1580                 }
 1581 #endif
 1582         }
 1583 
 1584         return (error);
 1585 }
 1586 
 1587 /*
 1588  * Return interface configuration
 1589  * of system.  List may be used
 1590  * in later ioctl's (above) to get
 1591  * other information.
 1592  */
 1593 /*ARGSUSED*/
 1594 int
 1595 ifconf(u_long cmd, caddr_t data)
 1596 {
 1597         struct ifconf *ifc = (struct ifconf *)data;
 1598         struct ifnet *ifp;
 1599         struct ifaddr *ifa;
 1600         struct ifreq ifr, *ifrp;
 1601         int space = ifc->ifc_len, error = 0;
 1602         const int sz = (int)sizeof(ifr);
 1603         int sign;
 1604 
 1605         if ((ifrp = ifc->ifc_req) == NULL) {
 1606                 space = 0;
 1607                 sign = -1;
 1608         } else {
 1609                 sign = 1;
 1610         }
 1611         IFNET_FOREACH(ifp) {
 1612                 (void)strncpy(ifr.ifr_name, ifp->if_xname,
 1613                     sizeof(ifr.ifr_name));
 1614                 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0')
 1615                         return ENAMETOOLONG;
 1616                 if ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) == NULL) {
 1617                         memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
 1618                         if (ifrp != NULL && space >= sz) {
 1619                                 error = copyout(&ifr, ifrp, sz);
 1620                                 if (error)
 1621                                         break;
 1622                                 ifrp++;
 1623                         }
 1624                         space -= sizeof(ifr) * sign;
 1625                         continue;
 1626                 }
 1627 
 1628                 for (; ifa != 0; ifa = TAILQ_NEXT(ifa, ifa_list)) {
 1629                         struct sockaddr *sa = ifa->ifa_addr;
 1630 #ifdef COMPAT_OSOCK
 1631                         if (cmd == OSIOCGIFCONF) {
 1632                                 struct osockaddr *osa =
 1633                                          (struct osockaddr *)&ifr.ifr_addr;
 1634                                 /*
 1635                                  * If it does not fit, we don't bother with it
 1636                                  */
 1637                                 if (sa->sa_len > sizeof(*osa))
 1638                                         continue;
 1639                                 ifr.ifr_addr = *sa;
 1640                                 osa->sa_family = sa->sa_family;
 1641                                 if (ifrp != NULL && space >= sz) {
 1642                                         error = copyout(&ifr, ifrp, sz);
 1643                                         ifrp++;
 1644                                 }
 1645                         } else
 1646 #endif
 1647                         if (sa->sa_len <= sizeof(*sa)) {
 1648                                 ifr.ifr_addr = *sa;
 1649                                 if (ifrp != NULL && space >= sz) {
 1650                                         error = copyout(&ifr, ifrp, sz);
 1651                                         ifrp++;
 1652                                 }
 1653                         } else {
 1654                                 space -= (sa->sa_len - sizeof(*sa)) * sign;
 1655                                 if (ifrp != NULL && space >= sz) {
 1656                                         error = copyout(&ifr, ifrp,
 1657                                             sizeof(ifr.ifr_name));
 1658                                         if (error == 0) {
 1659                                                 error = copyout(sa,
 1660                                                     &ifrp->ifr_addr,
 1661                                                     sa->sa_len);
 1662                                         }
 1663                                         ifrp = (struct ifreq *)
 1664                                                 (sa->sa_len +
 1665                                                  (caddr_t)&ifrp->ifr_addr);
 1666                                 }
 1667                         }
 1668                         if (error)
 1669                                 break;
 1670                         space -= sz * sign;
 1671                 }
 1672         }
 1673         if (ifrp != NULL)
 1674                 ifc->ifc_len -= space;
 1675         else
 1676                 ifc->ifc_len = space;
 1677         return (error);
 1678 }
 1679 
 1680 /*
 1681  * Queue message on interface, and start output if interface
 1682  * not yet active.
 1683  */
 1684 int
 1685 ifq_enqueue(struct ifnet *ifp, struct mbuf *m
 1686     ALTQ_COMMA ALTQ_DECL(struct altq_pktattr *pktattr))
 1687 {
 1688         int len = m->m_pkthdr.len;
 1689         int mflags = m->m_flags;
 1690         int s = splnet();
 1691         int error;
 1692 
 1693         IFQ_ENQUEUE(&ifp->if_snd, m, pktattr, error);
 1694         if (error) {
 1695                 splx(s);
 1696                 return error;
 1697         }
 1698         ifp->if_obytes += len;
 1699         if (mflags & M_MCAST)
 1700                 ifp->if_omcasts++;
 1701         if ((ifp->if_flags & IFF_OACTIVE) == 0)
 1702                 (*ifp->if_start)(ifp);
 1703         splx(s);
 1704         return error;
 1705 }
 1706 
 1707 /*
 1708  * Queue message on interface, possibly using a second fast queue
 1709  */
 1710 int
 1711 ifq_enqueue2(struct ifnet *ifp, struct ifqueue *ifq, struct mbuf *m
 1712     ALTQ_COMMA ALTQ_DECL(struct altq_pktattr *pktattr))
 1713 {
 1714         int error = 0;
 1715 
 1716         if (ifq != NULL
 1717 #ifdef ALTQ
 1718             && ALTQ_IS_ENABLED(&ifp->if_snd) == 0
 1719 #endif
 1720             ) {
 1721                 if (IF_QFULL(ifq)) {
 1722                         IF_DROP(&ifp->if_snd);
 1723                         m_freem(m);
 1724                         if (error == 0)
 1725                                 error = ENOBUFS;
 1726                 }
 1727                 else
 1728                         IF_ENQUEUE(ifq, m);
 1729         } else
 1730                 IFQ_ENQUEUE(&ifp->if_snd, m, pktattr, error);
 1731         if (error != 0) {
 1732                 ++ifp->if_oerrors;
 1733                 return error;
 1734         }
 1735 
 1736         return 0;
 1737 }
 1738 
 1739 
 1740 #if defined(INET) || defined(INET6)
 1741 static void
 1742 sysctl_net_ifq_setup(struct sysctllog **clog,
 1743                      int pf, const char *pfname,
 1744                      int ipn, const char *ipname,
 1745                      int qid, struct ifqueue *ifq)
 1746 {
 1747 
 1748         sysctl_createv(clog, 0, NULL, NULL,
 1749                        CTLFLAG_PERMANENT,
 1750                        CTLTYPE_NODE, "net", NULL,
 1751                        NULL, 0, NULL, 0,
 1752                        CTL_NET, CTL_EOL);
 1753         sysctl_createv(clog, 0, NULL, NULL,
 1754                        CTLFLAG_PERMANENT,
 1755                        CTLTYPE_NODE, pfname, NULL,
 1756                        NULL, 0, NULL, 0,
 1757                        CTL_NET, pf, CTL_EOL);
 1758         sysctl_createv(clog, 0, NULL, NULL,
 1759                        CTLFLAG_PERMANENT,
 1760                        CTLTYPE_NODE, ipname, NULL,
 1761                        NULL, 0, NULL, 0,
 1762                        CTL_NET, pf, ipn, CTL_EOL);
 1763         sysctl_createv(clog, 0, NULL, NULL,
 1764                        CTLFLAG_PERMANENT,
 1765                        CTLTYPE_NODE, "ifq",
 1766                        SYSCTL_DESCR("Protocol input queue controls"),
 1767                        NULL, 0, NULL, 0,
 1768                        CTL_NET, pf, ipn, qid, CTL_EOL);
 1769 
 1770         sysctl_createv(clog, 0, NULL, NULL,
 1771                        CTLFLAG_PERMANENT,
 1772                        CTLTYPE_INT, "len",
 1773                        SYSCTL_DESCR("Current input queue length"),
 1774                        NULL, 0, &ifq->ifq_len, 0,
 1775                        CTL_NET, pf, ipn, qid, IFQCTL_LEN, CTL_EOL);
 1776         sysctl_createv(clog, 0, NULL, NULL,
 1777                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1778                        CTLTYPE_INT, "maxlen",
 1779                        SYSCTL_DESCR("Maximum allowed input queue length"),
 1780                        NULL, 0, &ifq->ifq_maxlen, 0,
 1781                        CTL_NET, pf, ipn, qid, IFQCTL_MAXLEN, CTL_EOL);
 1782 #ifdef notyet
 1783         sysctl_createv(clog, 0, NULL, NULL,
 1784                        CTLFLAG_PERMANENT,
 1785                        CTLTYPE_INT, "peak",
 1786                        SYSCTL_DESCR("Highest input queue length"),
 1787                        NULL, 0, &ifq->ifq_peak, 0,
 1788                        CTL_NET, pf, ipn, qid, IFQCTL_PEAK, CTL_EOL);
 1789 #endif
 1790         sysctl_createv(clog, 0, NULL, NULL,
 1791                        CTLFLAG_PERMANENT,
 1792                        CTLTYPE_INT, "drops",
 1793                        SYSCTL_DESCR("Packets dropped due to full input queue"),
 1794                        NULL, 0, &ifq->ifq_drops, 0,
 1795                        CTL_NET, pf, ipn, qid, IFQCTL_DROPS, CTL_EOL);
 1796 }
 1797 
 1798 #ifdef INET
 1799 SYSCTL_SETUP(sysctl_net_inet_ip_ifq_setup,
 1800              "sysctl net.inet.ip.ifq subtree setup")
 1801 {
 1802         extern struct ifqueue ipintrq;
 1803 
 1804         sysctl_net_ifq_setup(clog, PF_INET, "inet", IPPROTO_IP, "ip",
 1805                              IPCTL_IFQ, &ipintrq);
 1806 }
 1807 #endif /* INET */
 1808 
 1809 #ifdef INET6
 1810 SYSCTL_SETUP(sysctl_net_inet6_ip6_ifq_setup,
 1811              "sysctl net.inet6.ip6.ifq subtree setup")
 1812 {
 1813         extern struct ifqueue ip6intrq;
 1814 
 1815         sysctl_net_ifq_setup(clog, PF_INET6, "inet6", IPPROTO_IPV6, "ip6",
 1816                              IPV6CTL_IFQ, &ip6intrq);
 1817 }
 1818 #endif /* INET6 */
 1819 #endif /* INET || INET6 */

Cache object: 1e46ad43efd3e22ff60cef51ad2d8bae


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