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

Cache object: 84d6e14205c02e3bbcec8db3b0adfa70


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