[ 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  -  FREEBSD8  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

    1 /*      $OpenBSD: if.c,v 1.183 2008/11/26 19:07:33 deraadt Exp $        */
    2 /*      $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $  */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  * 
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  * 
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Copyright (c) 1980, 1986, 1993
   35  *      The Regents of the University of California.  All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. Neither the name of the University nor the names of its contributors
   46  *    may be used to endorse or promote products derived from this software
   47  *    without specific prior written permission.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      @(#)if.c        8.3 (Berkeley) 1/4/94
   62  */
   63 
   64 #include "bluetooth.h"
   65 #include "bpfilter.h"
   66 #include "bridge.h"
   67 #include "carp.h"
   68 #include "pf.h"
   69 #include "trunk.h"
   70 
   71 #include <sys/param.h>
   72 #include <sys/systm.h>
   73 #include <sys/mbuf.h>
   74 #include <sys/proc.h>
   75 #include <sys/socket.h>
   76 #include <sys/socketvar.h>
   77 #include <sys/protosw.h>
   78 #include <sys/kernel.h>
   79 #include <sys/ioctl.h>
   80 #include <sys/domain.h>
   81 #include <sys/sysctl.h>
   82 
   83 #include <net/if.h>
   84 #include <net/if_dl.h>
   85 #include <net/if_media.h>
   86 #include <net/if_types.h>
   87 #include <net/route.h>
   88 #include <net/netisr.h>
   89 
   90 #ifdef INET
   91 #include <netinet/in.h>
   92 #include <netinet/in_var.h>
   93 #include <netinet/if_ether.h>
   94 #include <netinet/igmp.h>
   95 #ifdef MROUTING
   96 #include <netinet/ip_mroute.h>
   97 #endif
   98 #endif
   99 
  100 #ifdef INET6
  101 #ifndef INET
  102 #include <netinet/in.h>
  103 #endif
  104 #include <netinet6/in6_ifattach.h>
  105 #include <netinet6/nd6.h>
  106 #endif
  107 
  108 #if NBPFILTER > 0
  109 #include <net/bpf.h>
  110 #endif
  111 
  112 #if NTRUNK > 0
  113 #include <net/if_trunk.h>
  114 #endif
  115 
  116 #if NBRIDGE > 0
  117 #include <net/if_bridge.h>
  118 #endif
  119 
  120 #if NCARP > 0
  121 #include <netinet/ip_carp.h>
  122 #endif
  123 
  124 #if NPF > 0
  125 #include <net/pfvar.h>
  126 #endif
  127 
  128 void    if_attachsetup(struct ifnet *);
  129 void    if_attachdomain1(struct ifnet *);
  130 
  131 int     ifqmaxlen = IFQ_MAXLEN;
  132 
  133 void    if_detach_queues(struct ifnet *, struct ifqueue *);
  134 void    if_detached_start(struct ifnet *);
  135 int     if_detached_ioctl(struct ifnet *, u_long, caddr_t);
  136 int     if_detached_init(struct ifnet *);
  137 void    if_detached_watchdog(struct ifnet *);
  138 
  139 int     if_getgroup(caddr_t, struct ifnet *);
  140 int     if_getgroupmembers(caddr_t);
  141 int     if_getgroupattribs(caddr_t);
  142 int     if_setgroupattribs(caddr_t);
  143 
  144 int     if_clone_list(struct if_clonereq *);
  145 struct if_clone *if_clone_lookup(const char *, int *);
  146 
  147 void    if_congestion_clear(void *);
  148 int     if_group_egress_build(void);
  149 
  150 void    m_clinitifp(struct ifnet *);
  151 
  152 TAILQ_HEAD(, ifg_group) ifg_head;
  153 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
  154 int if_cloners_count;
  155 
  156 int m_clticks;
  157 struct timeout m_cltick_tmo;
  158 
  159 /*
  160  * Record when the last timeout has been run.  If the delta is
  161  * too high, m_cldrop() will notice and decrease the interface
  162  * high water marks.
  163  */
  164 static void
  165 m_cltick(void *arg)
  166 {
  167         extern int ticks;
  168 
  169         m_clticks = ticks;
  170         timeout_add(&m_cltick_tmo, 1);
  171 }
  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         static struct timeout if_slowtim;
  183 
  184         timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);
  185 
  186         if_slowtimo(&if_slowtim);
  187 
  188         timeout_set(&m_cltick_tmo, m_cltick, NULL);
  189         m_cltick(NULL);
  190 }
  191 
  192 static int if_index = 0;
  193 int if_indexlim = 0;
  194 struct ifaddr **ifnet_addrs = NULL;
  195 struct ifnet **ifindex2ifnet = NULL;
  196 struct ifnet_head ifnet;
  197 struct ifnet_head iftxlist = TAILQ_HEAD_INITIALIZER(iftxlist);
  198 struct ifnet *lo0ifp;
  199 
  200 /*
  201  * Attach an interface to the
  202  * list of "active" interfaces.
  203  */
  204 void
  205 if_attachsetup(struct ifnet *ifp)
  206 {
  207         struct ifaddr *ifa;
  208         int wrapped = 0;
  209 
  210         if (ifindex2ifnet == 0)
  211                 if_index = 1;
  212         else {
  213                 while (if_index < if_indexlim &&
  214                     ifindex2ifnet[if_index] != NULL) {
  215                         if_index++;
  216                         /*
  217                          * If we hit USHRT_MAX, we skip back to 1 since
  218                          * there are a number of places where the value
  219                          * of ifp->if_index or if_index itself is compared
  220                          * to or stored in an unsigned short.  By
  221                          * jumping back, we won't botch those assignments
  222                          * or comparisons.
  223                          */
  224                         if (if_index == USHRT_MAX) {
  225                                 if_index = 1;
  226                                 /*
  227                                  * However, if we have to jump back to 1
  228                                  * *twice* without finding an empty
  229                                  * slot in ifindex2ifnet[], then there
  230                                  * there are too many (>65535) interfaces.
  231                                  */
  232                                 if (wrapped++)
  233                                         panic("too many interfaces");
  234                         }
  235                 }
  236         }
  237         ifp->if_index = if_index;
  238 
  239         /*
  240          * We have some arrays that should be indexed by if_index.
  241          * since if_index will grow dynamically, they should grow too.
  242          *      struct ifaddr **ifnet_addrs
  243          *      struct ifnet **ifindex2ifnet
  244          */
  245         if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
  246                 size_t m, n, oldlim;
  247                 caddr_t q;
  248 
  249                 oldlim = if_indexlim;
  250                 if (if_indexlim == 0)
  251                         if_indexlim = 8;
  252                 while (if_index >= if_indexlim)
  253                         if_indexlim <<= 1;
  254 
  255                 /* grow ifnet_addrs */
  256                 m = oldlim * sizeof(ifa);
  257                 n = if_indexlim * sizeof(ifa);
  258                 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
  259                 if (ifnet_addrs) {
  260                         bcopy((caddr_t)ifnet_addrs, q, m);
  261                         free((caddr_t)ifnet_addrs, M_IFADDR);
  262                 }
  263                 ifnet_addrs = (struct ifaddr **)q;
  264 
  265                 /* grow ifindex2ifnet */
  266                 m = oldlim * sizeof(struct ifnet *);
  267                 n = if_indexlim * sizeof(struct ifnet *);
  268                 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK|M_ZERO);
  269                 if (ifindex2ifnet) {
  270                         bcopy((caddr_t)ifindex2ifnet, q, m);
  271                         free((caddr_t)ifindex2ifnet, M_IFADDR);
  272                 }
  273                 ifindex2ifnet = (struct ifnet **)q;
  274         }
  275 
  276         TAILQ_INIT(&ifp->if_groups);
  277 
  278         if_addgroup(ifp, IFG_ALL);
  279 
  280         ifindex2ifnet[if_index] = ifp;
  281 
  282         if (ifp->if_snd.ifq_maxlen == 0)
  283                 ifp->if_snd.ifq_maxlen = ifqmaxlen;
  284 #ifdef ALTQ
  285         ifp->if_snd.altq_type = 0;
  286         ifp->if_snd.altq_disc = NULL;
  287         ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
  288         ifp->if_snd.altq_tbr  = NULL;
  289         ifp->if_snd.altq_ifp  = ifp;
  290 #endif
  291 
  292         if (domains)
  293                 if_attachdomain1(ifp);
  294 #if NPF > 0
  295         pfi_attach_ifnet(ifp);
  296 #endif
  297 
  298         /* Announce the interface. */
  299         rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
  300 }
  301 
  302 /*
  303  * Allocate the link level name for the specified interface.  This
  304  * is an attachment helper.  It must be called after ifp->if_addrlen
  305  * is initialized, which may not be the case when if_attach() is
  306  * called.
  307  */
  308 void
  309 if_alloc_sadl(struct ifnet *ifp)
  310 {
  311         unsigned socksize, ifasize;
  312         int namelen, masklen;
  313         struct sockaddr_dl *sdl;
  314         struct ifaddr *ifa;
  315 
  316         /*
  317          * If the interface already has a link name, release it
  318          * now.  This is useful for interfaces that can change
  319          * link types, and thus switch link names often.
  320          */
  321         if (ifp->if_sadl != NULL)
  322                 if_free_sadl(ifp);
  323 
  324         namelen = strlen(ifp->if_xname);
  325 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
  326         masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
  327         socksize = masklen + ifp->if_addrlen;
  328 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
  329         if (socksize < sizeof(*sdl))
  330                 socksize = sizeof(*sdl);
  331         socksize = ROUNDUP(socksize);
  332         ifasize = sizeof(*ifa) + 2 * socksize;
  333         ifa = malloc(ifasize, M_IFADDR, M_WAITOK|M_ZERO);
  334         sdl = (struct sockaddr_dl *)(ifa + 1);
  335         sdl->sdl_len = socksize;
  336         sdl->sdl_family = AF_LINK;
  337         bcopy(ifp->if_xname, sdl->sdl_data, namelen);
  338         sdl->sdl_nlen = namelen;
  339         sdl->sdl_alen = ifp->if_addrlen;
  340         sdl->sdl_index = ifp->if_index;
  341         sdl->sdl_type = ifp->if_type;
  342         ifnet_addrs[ifp->if_index] = ifa;
  343         ifa->ifa_ifp = ifp;
  344         ifa->ifa_rtrequest = link_rtrequest;
  345         TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
  346         ifa->ifa_addr = (struct sockaddr *)sdl;
  347         ifp->if_sadl = sdl;
  348         sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
  349         ifa->ifa_netmask = (struct sockaddr *)sdl;
  350         sdl->sdl_len = masklen;
  351         while (namelen != 0)
  352                 sdl->sdl_data[--namelen] = 0xff;
  353 }
  354 
  355 /*
  356  * Free the link level name for the specified interface.  This is
  357  * a detach helper.  This is called from if_detach() or from
  358  * link layer type specific detach functions.
  359  */
  360 void
  361 if_free_sadl(struct ifnet *ifp)
  362 {
  363         struct ifaddr *ifa;
  364         int s;
  365 
  366         ifa = ifnet_addrs[ifp->if_index];
  367         if (ifa == NULL)
  368                 return;
  369 
  370         s = splnet();
  371         rtinit(ifa, RTM_DELETE, 0);
  372 #if 0
  373         TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
  374         ifnet_addrs[ifp->if_index] = NULL;
  375 #endif
  376         ifp->if_sadl = NULL;
  377 
  378         splx(s);
  379 }
  380 
  381 void
  382 if_attachdomain()
  383 {
  384         struct ifnet *ifp;
  385         int s;
  386 
  387         s = splnet();
  388         for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
  389                 if_attachdomain1(ifp);
  390         splx(s);
  391 }
  392 
  393 void
  394 if_attachdomain1(struct ifnet *ifp)
  395 {
  396         struct domain *dp;
  397         int s;
  398 
  399         s = splnet();
  400 
  401         /* address family dependent data region */
  402         bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
  403         for (dp = domains; dp; dp = dp->dom_next) {
  404                 if (dp->dom_ifattach)
  405                         ifp->if_afdata[dp->dom_family] =
  406                             (*dp->dom_ifattach)(ifp);
  407         }
  408 
  409         splx(s);
  410 }
  411 
  412 void
  413 if_attachhead(struct ifnet *ifp)
  414 {
  415         if (if_index == 0) {
  416                 TAILQ_INIT(&ifnet);
  417                 TAILQ_INIT(&ifg_head);
  418         }
  419         TAILQ_INIT(&ifp->if_addrlist);
  420         ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
  421             M_TEMP, M_NOWAIT);
  422         if (ifp->if_addrhooks == NULL)
  423                 panic("if_attachhead: malloc");
  424         TAILQ_INIT(ifp->if_addrhooks);
  425         ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
  426             M_TEMP, M_NOWAIT);
  427         if (ifp->if_linkstatehooks == NULL)
  428                 panic("if_attachhead: malloc");
  429         TAILQ_INIT(ifp->if_linkstatehooks);
  430         ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
  431             M_TEMP, M_NOWAIT);
  432         if (ifp->if_detachhooks == NULL)
  433                 panic("if_attachhead: malloc");
  434         TAILQ_INIT(ifp->if_detachhooks);
  435         TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
  436         if_attachsetup(ifp);
  437 }
  438 
  439 void
  440 if_attach(struct ifnet *ifp)
  441 {
  442 #if NCARP > 0
  443         struct ifnet *before = NULL;
  444 #endif
  445 
  446         if (if_index == 0) {
  447                 TAILQ_INIT(&ifnet);
  448                 TAILQ_INIT(&ifg_head);
  449         }
  450         TAILQ_INIT(&ifp->if_addrlist);
  451         ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
  452             M_TEMP, M_NOWAIT);
  453         if (ifp->if_addrhooks == NULL)
  454                 panic("if_attach: malloc");
  455         TAILQ_INIT(ifp->if_addrhooks);
  456         ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
  457             M_TEMP, M_NOWAIT);
  458         if (ifp->if_linkstatehooks == NULL)
  459                 panic("if_attach: malloc");
  460         TAILQ_INIT(ifp->if_linkstatehooks);
  461         ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
  462             M_TEMP, M_NOWAIT);
  463         if (ifp->if_detachhooks == NULL)
  464                 panic("if_attach: malloc");
  465         TAILQ_INIT(ifp->if_detachhooks);
  466 
  467 #if NCARP > 0
  468         if (ifp->if_type != IFT_CARP)
  469                 TAILQ_FOREACH(before, &ifnet, if_list)
  470                         if (before->if_type == IFT_CARP)
  471                                 break;
  472         if (before == NULL)
  473                 TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
  474         else
  475                 TAILQ_INSERT_BEFORE(before, ifp, if_list);
  476 #else
  477         TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
  478 #endif
  479 
  480         m_clinitifp(ifp);
  481 
  482         if_attachsetup(ifp);
  483 }
  484 
  485 void
  486 if_start(struct ifnet *ifp)
  487 {
  488         if (IF_QFULL(&ifp->if_snd) && !ISSET(ifp->if_flags, IFF_OACTIVE)) {
  489                 if (ISSET(ifp->if_xflags, IFXF_TXREADY)) {
  490                         TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
  491                         CLR(ifp->if_xflags, IFXF_TXREADY);
  492                 }
  493                 ifp->if_start(ifp);
  494                 return;
  495         }
  496 
  497         if (!ISSET(ifp->if_xflags, IFXF_TXREADY)) {
  498                 SET(ifp->if_xflags, IFXF_TXREADY);
  499                 TAILQ_INSERT_TAIL(&iftxlist, ifp, if_txlist);
  500                 schednetisr(NETISR_TX);
  501         }
  502 }
  503 
  504 void
  505 nettxintr(void)
  506 {
  507         struct ifnet *ifp;
  508         int s;
  509 
  510         s = splnet();
  511         while ((ifp = TAILQ_FIRST(&iftxlist)) != NULL) {
  512                 TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
  513                 CLR(ifp->if_xflags, IFXF_TXREADY);
  514                 ifp->if_start(ifp);
  515         }
  516         splx(s);
  517 }
  518 
  519 /*
  520  * Detach an interface from everything in the kernel.  Also deallocate
  521  * private resources.
  522  * XXX So far only the INET protocol family has been looked over
  523  * wrt resource usage that needs to be decoupled.
  524  */
  525 void
  526 if_detach(struct ifnet *ifp)
  527 {
  528         struct ifaddr *ifa;
  529         struct ifg_list *ifg;
  530         int s = splnet();
  531         struct domain *dp;
  532 
  533         ifp->if_flags &= ~IFF_OACTIVE;
  534         ifp->if_start = if_detached_start;
  535         ifp->if_ioctl = if_detached_ioctl;
  536         ifp->if_init = if_detached_init;
  537         ifp->if_watchdog = if_detached_watchdog;
  538 
  539         /* Call detach hooks, ie. to remove vlan interfaces */
  540         dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
  541 
  542 #if NTRUNK > 0
  543         if (ifp->if_type == IFT_IEEE8023ADLAG)
  544                 trunk_port_ifdetach(ifp);
  545 #endif
  546 
  547 #if NBRIDGE > 0
  548         /* Remove the interface from any bridge it is part of.  */
  549         if (ifp->if_bridge)
  550                 bridge_ifdetach(ifp);
  551 #endif
  552 
  553 #if NCARP > 0
  554         /* Remove the interface from any carp group it is a part of.  */
  555         if (ifp->if_carp && ifp->if_type != IFT_CARP)
  556                 carp_ifdetach(ifp);
  557 #endif
  558 
  559 #if NBPFILTER > 0
  560         bpfdetach(ifp);
  561 #endif
  562 #ifdef ALTQ
  563         if (ALTQ_IS_ENABLED(&ifp->if_snd))
  564                 altq_disable(&ifp->if_snd);
  565         if (ALTQ_IS_ATTACHED(&ifp->if_snd))
  566                 altq_detach(&ifp->if_snd);
  567 #endif
  568         rt_if_remove(ifp);
  569 #ifdef INET
  570         rti_delete(ifp);
  571 #if NETHER > 0
  572         myip_ifp = NULL;
  573 #endif
  574 #ifdef MROUTING
  575         vif_delete(ifp);
  576 #endif
  577 #endif
  578 #ifdef INET6
  579         in6_ifdetach(ifp);
  580 #endif
  581 
  582 #if NPF > 0
  583         pfi_detach_ifnet(ifp);
  584 #endif
  585 
  586         /*
  587          * remove packets came from ifp, from software interrupt queues.
  588          * net/netisr_dispatch.h is not usable, as some of them use
  589          * strange queue names.
  590          */
  591 #define IF_DETACH_QUEUES(x) \
  592 do { \
  593         extern struct ifqueue x; \
  594         if_detach_queues(ifp, & x); \
  595 } while (0)
  596 #ifdef INET
  597         IF_DETACH_QUEUES(arpintrq);
  598         IF_DETACH_QUEUES(ipintrq);
  599 #endif
  600 #ifdef INET6
  601         IF_DETACH_QUEUES(ip6intrq);
  602 #endif
  603 #ifdef NETATALK
  604         IF_DETACH_QUEUES(atintrq1);
  605         IF_DETACH_QUEUES(atintrq2);
  606 #endif
  607 #ifdef NATM
  608         IF_DETACH_QUEUES(natmintrq);
  609 #endif
  610 #undef IF_DETACH_QUEUES
  611 
  612         /*
  613          * XXX transient ifp refs?  inpcb.ip_moptions.imo_multicast_ifp?
  614          * Other network stacks than INET?
  615          */
  616 
  617         /* Remove the interface from the list of all interfaces.  */
  618         TAILQ_REMOVE(&ifnet, ifp, if_list);
  619         if (ISSET(ifp->if_xflags, IFXF_TXREADY))
  620                 TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
  621 
  622         /*
  623          * Deallocate private resources.
  624          */
  625         while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
  626                 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
  627 #ifdef INET
  628                 if (ifa->ifa_addr->sa_family == AF_INET)
  629                         TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa,
  630                             ia_list);
  631 #endif
  632                 /* XXX if_free_sadl needs this */
  633                 if (ifa == ifnet_addrs[ifp->if_index])
  634                         continue;
  635 
  636                 ifa->ifa_ifp = NULL;
  637                 IFAFREE(ifa);
  638         }
  639 
  640         for (ifg = TAILQ_FIRST(&ifp->if_groups); ifg;
  641             ifg = TAILQ_FIRST(&ifp->if_groups))
  642                 if_delgroup(ifp, ifg->ifgl_group->ifg_group);
  643 
  644         if_free_sadl(ifp);
  645 
  646         ifnet_addrs[ifp->if_index]->ifa_ifp = NULL;
  647         IFAFREE(ifnet_addrs[ifp->if_index]);
  648         ifnet_addrs[ifp->if_index] = NULL;
  649 
  650         free(ifp->if_addrhooks, M_TEMP);
  651         free(ifp->if_linkstatehooks, M_TEMP);
  652         free(ifp->if_detachhooks, M_TEMP);
  653 
  654         for (dp = domains; dp; dp = dp->dom_next) {
  655                 if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
  656                         (*dp->dom_ifdetach)(ifp,
  657                             ifp->if_afdata[dp->dom_family]);
  658         }
  659 
  660         /* Announce that the interface is gone. */
  661         rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
  662 
  663         ifindex2ifnet[ifp->if_index] = NULL;
  664         splx(s);
  665 }
  666 
  667 void
  668 if_detach_queues(struct ifnet *ifp, struct ifqueue *q)
  669 {
  670         struct mbuf *m, *prev, *next;
  671 
  672         prev = NULL;
  673         for (m = q->ifq_head; m; m = next) {
  674                 next = m->m_nextpkt;
  675 #ifdef DIAGNOSTIC
  676                 if ((m->m_flags & M_PKTHDR) == 0) {
  677                         prev = m;
  678                         continue;
  679                 }
  680 #endif
  681                 if (m->m_pkthdr.rcvif != ifp) {
  682                         prev = m;
  683                         continue;
  684                 }
  685 
  686                 if (prev)
  687                         prev->m_nextpkt = m->m_nextpkt;
  688                 else
  689                         q->ifq_head = m->m_nextpkt;
  690                 if (q->ifq_tail == m)
  691                         q->ifq_tail = prev;
  692                 q->ifq_len--;
  693 
  694                 m->m_nextpkt = NULL;
  695                 m_freem(m);
  696                 IF_DROP(q);
  697         }
  698 }
  699 
  700 /*
  701  * Create a clone network interface.
  702  */
  703 int
  704 if_clone_create(const char *name)
  705 {
  706         struct if_clone *ifc;
  707         struct ifnet *ifp;
  708         int unit, ret;
  709 
  710         ifc = if_clone_lookup(name, &unit);
  711         if (ifc == NULL)
  712                 return (EINVAL);
  713 
  714         if (ifunit(name) != NULL)
  715                 return (EEXIST);
  716 
  717         if ((ret = (*ifc->ifc_create)(ifc, unit)) == 0 &&
  718             (ifp = ifunit(name)) != NULL)
  719                 if_addgroup(ifp, ifc->ifc_name);
  720 
  721         return (ret);
  722 }
  723 
  724 /*
  725  * Destroy a clone network interface.
  726  */
  727 int
  728 if_clone_destroy(const char *name)
  729 {
  730         struct if_clone *ifc;
  731         struct ifnet *ifp;
  732         int s, ret;
  733 
  734         ifc = if_clone_lookup(name, NULL);
  735         if (ifc == NULL)
  736                 return (EINVAL);
  737 
  738         ifp = ifunit(name);
  739         if (ifp == NULL)
  740                 return (ENXIO);
  741 
  742         if (ifc->ifc_destroy == NULL)
  743                 return (EOPNOTSUPP);
  744 
  745         if (ifp->if_flags & IFF_UP) {
  746                 s = splnet();
  747                 if_down(ifp);
  748                 splx(s);
  749         }
  750 
  751         if_delgroup(ifp, ifc->ifc_name);
  752 
  753         if ((ret = (*ifc->ifc_destroy)(ifp)) != 0)
  754                 if_addgroup(ifp, ifc->ifc_name);
  755 
  756         return (ret);
  757 }
  758 
  759 /*
  760  * Look up a network interface cloner.
  761  */
  762 struct if_clone *
  763 if_clone_lookup(const char *name, int *unitp)
  764 {
  765         struct if_clone *ifc;
  766         const char *cp;
  767         int unit;
  768 
  769         /* separate interface name from unit */
  770         for (cp = name;
  771             cp - name < IFNAMSIZ && *cp && (*cp < '' || *cp > '9');
  772             cp++)
  773                 continue;
  774 
  775         if (cp == name || cp - name == IFNAMSIZ || !*cp)
  776                 return (NULL);  /* No name or unit number */
  777 
  778         if (cp - name < IFNAMSIZ-1 && *cp == '' && cp[1] != '\0')
  779                 return (NULL);  /* unit number 0 padded */
  780 
  781         LIST_FOREACH(ifc, &if_cloners, ifc_list) {
  782                 if (strlen(ifc->ifc_name) == cp - name &&
  783                     !strncmp(name, ifc->ifc_name, cp - name))
  784                         break;
  785         }
  786 
  787         if (ifc == NULL)
  788                 return (NULL);
  789 
  790         unit = 0;
  791         while (cp - name < IFNAMSIZ && *cp) {
  792                 if (*cp < '' || *cp > '9' ||
  793                     unit > (INT_MAX - (*cp - '')) / 10) {
  794                         /* Bogus unit number. */
  795                         return (NULL);
  796                 }
  797                 unit = (unit * 10) + (*cp++ - '');
  798         }
  799 
  800         if (unitp != NULL)
  801                 *unitp = unit;
  802         return (ifc);
  803 }
  804 
  805 /*
  806  * Register a network interface cloner.
  807  */
  808 void
  809 if_clone_attach(struct if_clone *ifc)
  810 {
  811         LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
  812         if_cloners_count++;
  813 }
  814 
  815 /*
  816  * Unregister a network interface cloner.
  817  */
  818 void
  819 if_clone_detach(struct if_clone *ifc)
  820 {
  821 
  822         LIST_REMOVE(ifc, ifc_list);
  823         if_cloners_count--;
  824 }
  825 
  826 /*
  827  * Provide list of interface cloners to userspace.
  828  */
  829 int
  830 if_clone_list(struct if_clonereq *ifcr)
  831 {
  832         char outbuf[IFNAMSIZ], *dst;
  833         struct if_clone *ifc;
  834         int count, error = 0;
  835 
  836         ifcr->ifcr_total = if_cloners_count;
  837         if ((dst = ifcr->ifcr_buffer) == NULL) {
  838                 /* Just asking how many there are. */
  839                 return (0);
  840         }
  841 
  842         if (ifcr->ifcr_count < 0)
  843                 return (EINVAL);
  844 
  845         count = (if_cloners_count < ifcr->ifcr_count) ?
  846             if_cloners_count : ifcr->ifcr_count;
  847 
  848         for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
  849             ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
  850                 bzero(outbuf, sizeof outbuf);
  851                 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
  852                 error = copyout(outbuf, dst, IFNAMSIZ);
  853                 if (error)
  854                         break;
  855         }
  856 
  857         return (error);
  858 }
  859 
  860 /*
  861  * set queue congestion marker and register timeout to clear it
  862  */
  863 void
  864 if_congestion(struct ifqueue *ifq)
  865 {
  866         /* Not currently needed, all callers check this */
  867         if (ifq->ifq_congestion)
  868                 return;
  869 
  870         ifq->ifq_congestion = malloc(sizeof(struct timeout), M_TEMP, M_NOWAIT);
  871         if (ifq->ifq_congestion == NULL)
  872                 return;
  873         timeout_set(ifq->ifq_congestion, if_congestion_clear, ifq);
  874         timeout_add(ifq->ifq_congestion, hz / 100);
  875 }
  876 
  877 /*
  878  * clear the congestion flag
  879  */
  880 void
  881 if_congestion_clear(void *arg)
  882 {
  883         struct ifqueue *ifq = arg;
  884         struct timeout *to = ifq->ifq_congestion;
  885 
  886         ifq->ifq_congestion = NULL;
  887         free(to, M_TEMP);
  888 }
  889 
  890 /*
  891  * Locate an interface based on a complete address.
  892  */
  893 /*ARGSUSED*/
  894 struct ifaddr *
  895 ifa_ifwithaddr(struct sockaddr *addr)
  896 {
  897         struct ifnet *ifp;
  898         struct ifaddr *ifa;
  899 
  900 #define equal(a1, a2)   \
  901         (bcmp((caddr_t)(a1), (caddr_t)(a2),     \
  902         ((struct sockaddr *)(a1))->sa_len) == 0)
  903         TAILQ_FOREACH(ifp, &ifnet, if_list) {
  904             TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  905                 if (ifa->ifa_addr->sa_family != addr->sa_family)
  906                         continue;
  907                 if (equal(addr, ifa->ifa_addr))
  908                         return (ifa);
  909                 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
  910                     /* IP6 doesn't have broadcast */
  911                     ifa->ifa_broadaddr->sa_len != 0 &&
  912                     equal(ifa->ifa_broadaddr, addr))
  913                         return (ifa);
  914             }
  915         }
  916         return (NULL);
  917 }
  918 /*
  919  * Locate the point to point interface with a given destination address.
  920  */
  921 /*ARGSUSED*/
  922 struct ifaddr *
  923 ifa_ifwithdstaddr(struct sockaddr *addr)
  924 {
  925         struct ifnet *ifp;
  926         struct ifaddr *ifa;
  927 
  928         TAILQ_FOREACH(ifp, &ifnet, if_list) {
  929             if (ifp->if_flags & IFF_POINTOPOINT)
  930                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  931                         if (ifa->ifa_addr->sa_family != addr->sa_family ||
  932                             ifa->ifa_dstaddr == NULL)
  933                                 continue;
  934                         if (equal(addr, ifa->ifa_dstaddr))
  935                                 return (ifa);
  936                 }
  937         }
  938         return (NULL);
  939 }
  940 
  941 /*
  942  * Find an interface on a specific network.  If many, choice
  943  * is most specific found.
  944  */
  945 struct ifaddr *
  946 ifa_ifwithnet(struct sockaddr *addr)
  947 {
  948         struct ifnet *ifp;
  949         struct ifaddr *ifa;
  950         struct ifaddr *ifa_maybe = 0;
  951         u_int af = addr->sa_family;
  952         char *addr_data = addr->sa_data, *cplim;
  953 
  954         if (af == AF_LINK) {
  955                 struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
  956                 if (sdl->sdl_index && sdl->sdl_index < if_indexlim &&
  957                     ifindex2ifnet[sdl->sdl_index])
  958                         return (ifnet_addrs[sdl->sdl_index]);
  959         }
  960         TAILQ_FOREACH(ifp, &ifnet, if_list) {
  961                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  962                         char *cp, *cp2, *cp3;
  963 
  964                         if (ifa->ifa_addr->sa_family != af ||
  965                             ifa->ifa_netmask == 0)
  966                                 next: continue;
  967                         cp = addr_data;
  968                         cp2 = ifa->ifa_addr->sa_data;
  969                         cp3 = ifa->ifa_netmask->sa_data;
  970                         cplim = (char *)ifa->ifa_netmask +
  971                                 ifa->ifa_netmask->sa_len;
  972                         while (cp3 < cplim)
  973                                 if ((*cp++ ^ *cp2++) & *cp3++)
  974                                     /* want to continue for() loop */
  975                                         goto next;
  976                         if (ifa_maybe == 0 ||
  977                             rn_refines((caddr_t)ifa->ifa_netmask,
  978                             (caddr_t)ifa_maybe->ifa_netmask))
  979                                 ifa_maybe = ifa;
  980                 }
  981         }
  982         return (ifa_maybe);
  983 }
  984 
  985 /*
  986  * Find an interface using a specific address family
  987  */
  988 struct ifaddr *
  989 ifa_ifwithaf(int af)
  990 {
  991         struct ifnet *ifp;
  992         struct ifaddr *ifa;
  993 
  994         TAILQ_FOREACH(ifp, &ifnet, if_list) {
  995                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  996                         if (ifa->ifa_addr->sa_family == af)
  997                                 return (ifa);
  998                 }
  999         }
 1000         return (NULL);
 1001 }
 1002 
 1003 /*
 1004  * Find an interface address specific to an interface best matching
 1005  * a given address.
 1006  */
 1007 struct ifaddr *
 1008 ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
 1009 {
 1010         struct ifaddr *ifa;
 1011         char *cp, *cp2, *cp3;
 1012         char *cplim;
 1013         struct ifaddr *ifa_maybe = NULL;
 1014         u_int af = addr->sa_family;
 1015 
 1016         if (af >= AF_MAX)
 1017                 return (NULL);
 1018         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
 1019                 if (ifa->ifa_addr->sa_family != af)
 1020                         continue;
 1021                 if (ifa_maybe == NULL)
 1022                         ifa_maybe = ifa;
 1023                 if (ifa->ifa_netmask == 0 || ifp->if_flags & IFF_POINTOPOINT) {
 1024                         if (equal(addr, ifa->ifa_addr) ||
 1025                             (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
 1026                                 return (ifa);
 1027                         continue;
 1028                 }
 1029                 cp = addr->sa_data;
 1030                 cp2 = ifa->ifa_addr->sa_data;
 1031                 cp3 = ifa->ifa_netmask->sa_data;
 1032                 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
 1033                 for (; cp3 < cplim; cp3++)
 1034                         if ((*cp++ ^ *cp2++) & *cp3)
 1035                                 break;
 1036                 if (cp3 == cplim)
 1037                         return (ifa);
 1038         }
 1039         return (ifa_maybe);
 1040 }
 1041 
 1042 /*
 1043  * Default action when installing a route with a Link Level gateway.
 1044  * Lookup an appropriate real ifa to point to.
 1045  * This should be moved to /sys/net/link.c eventually.
 1046  */
 1047 void
 1048 link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
 1049 {
 1050         struct ifaddr *ifa;
 1051         struct sockaddr *dst;
 1052         struct ifnet *ifp;
 1053 
 1054         if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
 1055             ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
 1056                 return;
 1057         if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
 1058                 ifa->ifa_refcnt++;
 1059                 IFAFREE(rt->rt_ifa);
 1060                 rt->rt_ifa = ifa;
 1061                 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
 1062                         ifa->ifa_rtrequest(cmd, rt, info);
 1063         }
 1064 }
 1065 
 1066 /*
 1067  * Mark an interface down and notify protocols of
 1068  * the transition.
 1069  * NOTE: must be called at splsoftnet or equivalent.
 1070  */
 1071 void
 1072 if_down(struct ifnet *ifp)
 1073 {
 1074         struct ifaddr *ifa;
 1075 
 1076         splassert(IPL_SOFTNET);
 1077 
 1078         ifp->if_flags &= ~IFF_UP;
 1079         microtime(&ifp->if_lastchange);
 1080         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
 1081                 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
 1082         }
 1083         IFQ_PURGE(&ifp->if_snd);
 1084 #if NCARP > 0
 1085         if (ifp->if_carp)
 1086                 carp_carpdev_state(ifp);
 1087 #endif
 1088 #if NBRIDGE > 0
 1089         if (ifp->if_bridge)
 1090                 bstp_ifstate(ifp);
 1091 #endif
 1092         rt_ifmsg(ifp);
 1093 #ifndef SMALL_KERNEL
 1094         rt_if_track(ifp);
 1095 #endif
 1096 }
 1097 
 1098 /*
 1099  * Mark an interface up and notify protocols of
 1100  * the transition.
 1101  * NOTE: must be called at splsoftnet or equivalent.
 1102  */
 1103 void
 1104 if_up(struct ifnet *ifp)
 1105 {
 1106 #ifdef notyet
 1107         struct ifaddr *ifa;
 1108 #endif
 1109 
 1110         splassert(IPL_SOFTNET);
 1111 
 1112         ifp->if_flags |= IFF_UP;
 1113         microtime(&ifp->if_lastchange);
 1114 #ifdef notyet
 1115         /* this has no effect on IP, and will kill all ISO connections XXX */
 1116         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
 1117                 pfctlinput(PRC_IFUP, ifa->ifa_addr);
 1118         }
 1119 #endif
 1120 #if NCARP > 0
 1121         if (ifp->if_carp)
 1122                 carp_carpdev_state(ifp);
 1123 #endif
 1124 #if NBRIDGE > 0
 1125         if (ifp->if_bridge)
 1126                 bstp_ifstate(ifp);
 1127 #endif
 1128         rt_ifmsg(ifp);
 1129 #ifdef INET6
 1130         in6_if_up(ifp);
 1131 #endif
 1132 
 1133 #ifndef SMALL_KERNEL
 1134         rt_if_track(ifp);
 1135 #endif
 1136 
 1137         m_clinitifp(ifp);
 1138 }
 1139 
 1140 /*
 1141  * Process a link state change.
 1142  * NOTE: must be called at splsoftnet or equivalent.
 1143  */
 1144 void
 1145 if_link_state_change(struct ifnet *ifp)
 1146 {
 1147         rt_ifmsg(ifp);
 1148 #ifndef SMALL_KERNEL
 1149         rt_if_track(ifp);
 1150 #endif
 1151         dohooks(ifp->if_linkstatehooks, 0);
 1152 }
 1153 
 1154 /*
 1155  * Flush an interface queue.
 1156  */
 1157 void
 1158 if_qflush(struct ifqueue *ifq)
 1159 {
 1160         struct mbuf *m, *n;
 1161 
 1162         n = ifq->ifq_head;
 1163         while ((m = n) != NULL) {
 1164                 n = m->m_act;
 1165                 m_freem(m);
 1166         }
 1167         ifq->ifq_head = 0;
 1168         ifq->ifq_tail = 0;
 1169         ifq->ifq_len = 0;
 1170 }
 1171 
 1172 /*
 1173  * Handle interface watchdog timer routines.  Called
 1174  * from softclock, we decrement timers (if set) and
 1175  * call the appropriate interface routine on expiration.
 1176  */
 1177 void
 1178 if_slowtimo(void *arg)
 1179 {
 1180         struct timeout *to = (struct timeout *)arg;
 1181         struct ifnet *ifp;
 1182         int s = splnet();
 1183 
 1184         TAILQ_FOREACH(ifp, &ifnet, if_list) {
 1185                 if (ifp->if_timer == 0 || --ifp->if_timer)
 1186                         continue;
 1187                 if (ifp->if_watchdog)
 1188                         (*ifp->if_watchdog)(ifp);
 1189         }
 1190         splx(s);
 1191         timeout_add(to, hz / IFNET_SLOWHZ);
 1192 }
 1193 
 1194 /*
 1195  * Map interface name to
 1196  * interface structure pointer.
 1197  */
 1198 struct ifnet *
 1199 ifunit(const char *name)
 1200 {
 1201         struct ifnet *ifp;
 1202 
 1203         TAILQ_FOREACH(ifp, &ifnet, if_list) {
 1204                 if (strcmp(ifp->if_xname, name) == 0)
 1205                         return (ifp);
 1206         }
 1207         return (NULL);
 1208 }
 1209 
 1210 /*
 1211  * Interface ioctls.
 1212  */
 1213 int
 1214 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
 1215 {
 1216         struct ifnet *ifp;
 1217         struct ifreq *ifr;
 1218         struct ifaddr *ifa;
 1219         struct sockaddr_dl *sdl;
 1220         struct ifgroupreq *ifgr;
 1221         char ifdescrbuf[IFDESCRSIZE];
 1222         char ifrtlabelbuf[RTLABEL_LEN];
 1223         int error = 0;
 1224         size_t bytesdone;
 1225         short oif_flags;
 1226         const char *label;
 1227 
 1228         switch (cmd) {
 1229 
 1230         case SIOCGIFCONF:
 1231         case OSIOCGIFCONF:
 1232                 return (ifconf(cmd, data));
 1233         }
 1234         ifr = (struct ifreq *)data;
 1235 
 1236         switch (cmd) {
 1237         case SIOCIFCREATE:
 1238         case SIOCIFDESTROY:
 1239                 if ((error = suser(p, 0)) != 0)
 1240                         return (error);
 1241                 return ((cmd == SIOCIFCREATE) ?
 1242                     if_clone_create(ifr->ifr_name) :
 1243                     if_clone_destroy(ifr->ifr_name));
 1244         case SIOCIFGCLONERS:
 1245                 return (if_clone_list((struct if_clonereq *)data));
 1246         case SIOCGIFGMEMB:
 1247                 return (if_getgroupmembers(data));
 1248         case SIOCGIFGATTR:
 1249                 return (if_getgroupattribs(data));
 1250         case SIOCSIFGATTR:
 1251                 if ((error = suser(p, 0)) != 0)
 1252                         return (error);
 1253                 return (if_setgroupattribs(data));
 1254         }
 1255 
 1256         ifp = ifunit(ifr->ifr_name);
 1257         if (ifp == 0)
 1258                 return (ENXIO);
 1259         oif_flags = ifp->if_flags;
 1260         switch (cmd) {
 1261 
 1262         case SIOCGIFFLAGS:
 1263                 ifr->ifr_flags = ifp->if_flags;
 1264                 break;
 1265 
 1266         case SIOCGIFMETRIC:
 1267                 ifr->ifr_metric = ifp->if_metric;
 1268                 break;
 1269 
 1270         case SIOCGIFMTU:
 1271                 ifr->ifr_mtu = ifp->if_mtu;
 1272                 break;
 1273 
 1274         case SIOCGIFDATA:
 1275                 error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data,
 1276                     sizeof(ifp->if_data));
 1277                 break;
 1278 
 1279         case SIOCSIFFLAGS:
 1280                 if ((error = suser(p, 0)) != 0)
 1281                         return (error);
 1282                 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
 1283                         int s = splnet();
 1284                         if_down(ifp);
 1285                         splx(s);
 1286                 }
 1287                 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
 1288                         int s = splnet();
 1289                         if_up(ifp);
 1290                         splx(s);
 1291                 }
 1292                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
 1293                         (ifr->ifr_flags &~ IFF_CANTCHANGE);
 1294                 if (ifp->if_ioctl)
 1295                         (void) (*ifp->if_ioctl)(ifp, cmd, data);
 1296                 break;
 1297 
 1298         case SIOCSIFMETRIC:
 1299                 if ((error = suser(p, 0)) != 0)
 1300                         return (error);
 1301                 ifp->if_metric = ifr->ifr_metric;
 1302                 break;
 1303 
 1304         case SIOCSIFMTU:
 1305         {
 1306 #ifdef INET6
 1307                 int oldmtu = ifp->if_mtu;
 1308 #endif
 1309 
 1310                 if ((error = suser(p, 0)) != 0)
 1311                         return (error);
 1312                 if (ifp->if_ioctl == NULL)
 1313                         return (EOPNOTSUPP);
 1314                 error = (*ifp->if_ioctl)(ifp, cmd, data);
 1315 
 1316                 /*
 1317                  * If the link MTU changed, do network layer specific procedure.
 1318                  */
 1319 #ifdef INET6
 1320                 if (ifp->if_mtu != oldmtu)
 1321                         nd6_setmtu(ifp);
 1322 #endif
 1323                 break;
 1324         }
 1325 
 1326         case SIOCSIFPHYADDR:
 1327         case SIOCDIFPHYADDR:
 1328 #ifdef INET6
 1329         case SIOCSIFPHYADDR_IN6:
 1330 #endif
 1331         case SIOCSLIFPHYADDR:
 1332         case SIOCADDMULTI:
 1333         case SIOCDELMULTI:
 1334         case SIOCSIFMEDIA:
 1335                 if ((error = suser(p, 0)) != 0)
 1336                         return (error);
 1337                 /* FALLTHROUGH */
 1338         case SIOCGIFPSRCADDR:
 1339         case SIOCGIFPDSTADDR:
 1340         case SIOCGLIFPHYADDR:
 1341         case SIOCGIFMEDIA:
 1342                 if (ifp->if_ioctl == 0)
 1343                         return (EOPNOTSUPP);
 1344                 error = (*ifp->if_ioctl)(ifp, cmd, data);
 1345                 break;
 1346 
 1347         case SIOCGIFDESCR:
 1348                 strlcpy(ifdescrbuf, ifp->if_description, IFDESCRSIZE);
 1349                 error = copyoutstr(ifdescrbuf, ifr->ifr_data, IFDESCRSIZE,
 1350                     &bytesdone);
 1351                 break;
 1352 
 1353         case SIOCSIFDESCR:
 1354                 if ((error = suser(p, 0)) != 0)
 1355                         return (error);
 1356                 error = copyinstr(ifr->ifr_data, ifdescrbuf,
 1357                     IFDESCRSIZE, &bytesdone);
 1358                 if (error == 0) {
 1359                         (void)memset(ifp->if_description, 0, IFDESCRSIZE);
 1360                         strlcpy(ifp->if_description, ifdescrbuf, IFDESCRSIZE);
 1361                 }
 1362                 break;
 1363 
 1364         case SIOCGIFRTLABEL:
 1365                 if (ifp->if_rtlabelid &&
 1366                     (label = rtlabel_id2name(ifp->if_rtlabelid)) != NULL) {
 1367                         strlcpy(ifrtlabelbuf, label, RTLABEL_LEN);
 1368                         error = copyoutstr(ifrtlabelbuf, ifr->ifr_data,
 1369                             RTLABEL_LEN, &bytesdone);
 1370                 } else
 1371                         error = ENOENT;
 1372                 break;
 1373 
 1374         case SIOCSIFRTLABEL:
 1375                 if ((error = suser(p, 0)) != 0)
 1376                         return (error);
 1377                 error = copyinstr(ifr->ifr_data, ifrtlabelbuf,
 1378                     RTLABEL_LEN, &bytesdone);
 1379                 if (error == 0) {
 1380                         rtlabel_unref(ifp->if_rtlabelid);
 1381                         ifp->if_rtlabelid = rtlabel_name2id(ifrtlabelbuf);
 1382                 }
 1383                 break;
 1384 
 1385         case SIOCAIFGROUP:
 1386                 if ((error = suser(p, 0)))
 1387                         return (error);
 1388                 (*ifp->if_ioctl)(ifp, cmd, data); /* XXX error check */
 1389                 ifgr = (struct ifgroupreq *)data;
 1390                 if ((error = if_addgroup(ifp, ifgr->ifgr_group)))
 1391                         return (error);
 1392                 break;
 1393 
 1394         case SIOCGIFGROUP:
 1395                 if ((error = if_getgroup(data, ifp)))
 1396                         return (error);
 1397                 break;
 1398 
 1399         case SIOCDIFGROUP:
 1400                 if ((error = suser(p, 0)))
 1401                         return (error);
 1402                 (*ifp->if_ioctl)(ifp, cmd, data); /* XXX error check */
 1403                 ifgr = (struct ifgroupreq *)data;
 1404                 if ((error = if_delgroup(ifp, ifgr->ifgr_group)))
 1405                         return (error);
 1406                 break;
 1407 
 1408         case SIOCSIFLLADDR:
 1409                 if ((error = suser(p, 0)))
 1410                         return (error);
 1411                 ifa = ifnet_addrs[ifp->if_index];
 1412                 if (ifa == NULL)
 1413                         return (EINVAL);
 1414                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 1415                 if (sdl == NULL)
 1416                         return (EINVAL);
 1417                 if (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN)
 1418                         return (EINVAL);
 1419                 if (ETHER_IS_MULTICAST(ifr->ifr_addr.sa_data))
 1420                         return (EINVAL);
 1421                 switch (ifp->if_type) {
 1422                 case IFT_ETHER:
 1423                 case IFT_CARP:
 1424                 case IFT_FDDI:
 1425                 case IFT_XETHER:
 1426                 case IFT_ISO88025:
 1427                 case IFT_L2VLAN:
 1428                         bcopy((caddr_t)ifr->ifr_addr.sa_data,
 1429                             (caddr_t)((struct arpcom *)ifp)->ac_enaddr,
 1430                             ETHER_ADDR_LEN);
 1431                         bcopy((caddr_t)ifr->ifr_addr.sa_data,
 1432                             LLADDR(sdl), ETHER_ADDR_LEN);
 1433                         break;
 1434                 default:
 1435                         return (ENODEV);
 1436                 }
 1437                 if (ifp->if_flags & IFF_UP) {
 1438                         struct ifreq ifrq;
 1439                         int s = splnet();
 1440                         ifp->if_flags &= ~IFF_UP;
 1441                         ifrq.ifr_flags = ifp->if_flags;
 1442                         (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
 1443                         ifp->if_flags |= IFF_UP;
 1444                         ifrq.ifr_flags = ifp->if_flags;
 1445                         (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
 1446                         splx(s);
 1447                         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
 1448                                 if (ifa->ifa_addr != NULL &&
 1449                                     ifa->ifa_addr->sa_family == AF_INET)
 1450                                         arp_ifinit((struct arpcom *)ifp, ifa);
 1451                         }
 1452                 }
 1453                 break;
 1454 
 1455         default:
 1456                 if (so->so_proto == 0)
 1457                         return (EOPNOTSUPP);
 1458 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
 1459                 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
 1460                         (struct mbuf *) cmd, (struct mbuf *) data,
 1461                         (struct mbuf *) ifp, p));
 1462 #else
 1463             {
 1464                 u_long ocmd = cmd;
 1465 
 1466                 switch (cmd) {
 1467 
 1468                 case SIOCSIFADDR:
 1469                 case SIOCSIFDSTADDR:
 1470                 case SIOCSIFBRDADDR:
 1471                 case SIOCSIFNETMASK:
 1472 #if BYTE_ORDER != BIG_ENDIAN
 1473                         if (ifr->ifr_addr.sa_family == 0 &&
 1474                             ifr->ifr_addr.sa_len < 16) {
 1475                                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
 1476                                 ifr->ifr_addr.sa_len = 16;
 1477                         }
 1478 #else
 1479                         if (ifr->ifr_addr.sa_len == 0)
 1480                                 ifr->ifr_addr.sa_len = 16;
 1481 #endif
 1482                         break;
 1483 
 1484                 case OSIOCGIFADDR:
 1485                         cmd = SIOCGIFADDR;
 1486                         break;
 1487 
 1488                 case OSIOCGIFDSTADDR:
 1489                         cmd = SIOCGIFDSTADDR;
 1490                         break;
 1491 
 1492                 case OSIOCGIFBRDADDR:
 1493                         cmd = SIOCGIFBRDADDR;
 1494                         break;
 1495 
 1496                 case OSIOCGIFNETMASK:
 1497                         cmd = SIOCGIFNETMASK;
 1498                 }
 1499                 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
 1500                     (struct mbuf *) cmd, (struct mbuf *) data,
 1501                     (struct mbuf *) ifp, p));
 1502                 switch (ocmd) {
 1503 
 1504                 case OSIOCGIFADDR:
 1505                 case OSIOCGIFDSTADDR:
 1506                 case OSIOCGIFBRDADDR:
 1507                 case OSIOCGIFNETMASK:
 1508                         *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
 1509                 }
 1510 
 1511             }
 1512 #endif
 1513                 break;
 1514         }
 1515 
 1516         if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
 1517                 microtime(&ifp->if_lastchange);
 1518 #ifdef INET6
 1519                 if ((ifp->if_flags & IFF_UP) != 0) {
 1520                         int s = splnet();
 1521                         in6_if_up(ifp);
 1522                         splx(s);
 1523                 }
 1524 #endif
 1525         }
 1526         return (error);
 1527 }
 1528 
 1529 /*
 1530  * Return interface configuration
 1531  * of system.  List may be used
 1532  * in later ioctl's (above) to get
 1533  * other information.
 1534  */
 1535 /*ARGSUSED*/
 1536 int
 1537 ifconf(u_long cmd, caddr_t data)
 1538 {
 1539         struct ifconf *ifc = (struct ifconf *)data;
 1540         struct ifnet *ifp;
 1541         struct ifaddr *ifa;
 1542         struct ifreq ifr, *ifrp;
 1543         int space = ifc->ifc_len, error = 0;
 1544 
 1545         /* If ifc->ifc_len is 0, fill it in with the needed size and return. */
 1546         if (space == 0) {
 1547                 TAILQ_FOREACH(ifp, &ifnet, if_list) {
 1548                         struct sockaddr *sa;
 1549 
 1550                         if (TAILQ_EMPTY(&ifp->if_addrlist))
 1551                                 space += sizeof (ifr);
 1552                         else
 1553                                 TAILQ_FOREACH(ifa,
 1554                                     &ifp->if_addrlist, ifa_list) {
 1555                                         sa = ifa->ifa_addr;
 1556 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
 1557                                         if (cmd != OSIOCGIFCONF)
 1558 #endif
 1559                                         if (sa->sa_len > sizeof(*sa))
 1560                                                 space += sa->sa_len -
 1561                                                     sizeof(*sa);
 1562                                         space += sizeof(ifr);
 1563                                 }
 1564                 }
 1565                 ifc->ifc_len = space;
 1566                 return (0);
 1567         }
 1568 
 1569         ifrp = ifc->ifc_req;
 1570         for (ifp = TAILQ_FIRST(&ifnet); space >= sizeof(ifr) &&
 1571             ifp != TAILQ_END(&ifnet); ifp = TAILQ_NEXT(ifp, if_list)) {
 1572                 bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
 1573                 if (TAILQ_EMPTY(&ifp->if_addrlist)) {
 1574                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
 1575                         error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
 1576                             sizeof(ifr));
 1577                         if (error)
 1578                                 break;
 1579                         space -= sizeof (ifr), ifrp++;
 1580                 } else
 1581                         for (ifa = TAILQ_FIRST(&ifp->if_addrlist);
 1582                             space >= sizeof (ifr) &&
 1583                             ifa != TAILQ_END(&ifp->if_addrlist);
 1584                             ifa = TAILQ_NEXT(ifa, ifa_list)) {
 1585                                 struct sockaddr *sa = ifa->ifa_addr;
 1586 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
 1587                                 if (cmd == OSIOCGIFCONF) {
 1588                                         struct osockaddr *osa =
 1589                                             (struct osockaddr *)&ifr.ifr_addr;
 1590                                         ifr.ifr_addr = *sa;
 1591                                         osa->sa_family = sa->sa_family;
 1592                                         error = copyout((caddr_t)&ifr,
 1593                                             (caddr_t)ifrp, sizeof (ifr));
 1594                                         ifrp++;
 1595                                 } else
 1596 #endif
 1597                                 if (sa->sa_len <= sizeof(*sa)) {
 1598                                         ifr.ifr_addr = *sa;
 1599                                         error = copyout((caddr_t)&ifr,
 1600                                             (caddr_t)ifrp, sizeof (ifr));
 1601                                         ifrp++;
 1602                                 } else {
 1603                                         space -= sa->sa_len - sizeof(*sa);
 1604                                         if (space < sizeof (ifr))
 1605                                                 break;
 1606                                         error = copyout((caddr_t)&ifr,
 1607                                             (caddr_t)ifrp,
 1608                                             sizeof(ifr.ifr_name));
 1609                                         if (error == 0)
 1610                                                 error = copyout((caddr_t)sa,
 1611                                                     (caddr_t)&ifrp->ifr_addr,
 1612                                                     sa->sa_len);
 1613                                         ifrp = (struct ifreq *)(sa->sa_len +
 1614                                             (caddr_t)&ifrp->ifr_addr);
 1615                                 }
 1616                                 if (error)
 1617                                         break;
 1618                                 space -= sizeof (ifr);
 1619                         }
 1620         }
 1621         ifc->ifc_len -= space;
 1622         return (error);
 1623 }
 1624 
 1625 /*
 1626  * Dummy functions replaced in ifnet during detach (if protocols decide to
 1627  * fiddle with the if during detach.
 1628  */
 1629 void
 1630 if_detached_start(struct ifnet *ifp)
 1631 {
 1632         struct mbuf *m;
 1633 
 1634         while (1) {
 1635                 IF_DEQUEUE(&ifp->if_snd, m);
 1636 
 1637                 if (m == NULL)
 1638                         return;
 1639                 m_freem(m);
 1640         }
 1641 }
 1642 
 1643 int
 1644 if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
 1645 {
 1646         return ENODEV;
 1647 }
 1648 
 1649 int
 1650 if_detached_init(struct ifnet *ifp)
 1651 {
 1652         return (ENXIO);
 1653 }
 1654 
 1655 void
 1656 if_detached_watchdog(struct ifnet *ifp)
 1657 {
 1658         /* nothing */
 1659 }
 1660 
 1661 /*
 1662  * Create interface group without members
 1663  */
 1664 struct ifg_group *
 1665 if_creategroup(const char *groupname)
 1666 {
 1667         struct ifg_group        *ifg;
 1668 
 1669         if ((ifg = malloc(sizeof(*ifg), M_TEMP, M_NOWAIT)) == NULL)
 1670                 return (NULL);
 1671 
 1672         strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
 1673         ifg->ifg_refcnt = 0;
 1674         ifg->ifg_carp_demoted = 0;
 1675         TAILQ_INIT(&ifg->ifg_members);
 1676 #if NPF > 0
 1677         pfi_attach_ifgroup(ifg);
 1678 #endif
 1679         TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
 1680 
 1681         return (ifg);
 1682 }
 1683 
 1684 /*
 1685  * Add a group to an interface
 1686  */
 1687 int
 1688 if_addgroup(struct ifnet *ifp, const char *groupname)
 1689 {
 1690         struct ifg_list         *ifgl;
 1691         struct ifg_group        *ifg = NULL;
 1692         struct ifg_member       *ifgm;
 1693 
 1694         if (groupname[0] && groupname[strlen(groupname) - 1] >= '' &&
 1695             groupname[strlen(groupname) - 1] <= '9')
 1696                 return (EINVAL);
 1697 
 1698         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
 1699                 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
 1700                         return (EEXIST);
 1701 
 1702         if ((ifgl = malloc(sizeof(*ifgl), M_TEMP, M_NOWAIT)) == NULL)
 1703                 return (ENOMEM);
 1704 
 1705         if ((ifgm = malloc(sizeof(*ifgm), M_TEMP, M_NOWAIT)) == NULL) {
 1706                 free(ifgl, M_TEMP);
 1707                 return (ENOMEM);
 1708         }
 1709 
 1710         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
 1711                 if (!strcmp(ifg->ifg_group, groupname))
 1712                         break;
 1713 
 1714         if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) {
 1715                 free(ifgl, M_TEMP);
 1716                 free(ifgm, M_TEMP);
 1717                 return (ENOMEM);
 1718         }
 1719 
 1720         ifg->ifg_refcnt++;
 1721         ifgl->ifgl_group = ifg;
 1722         ifgm->ifgm_ifp = ifp;
 1723 
 1724         TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
 1725         TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
 1726 
 1727 #if NPF > 0
 1728         pfi_group_change(groupname);
 1729 #endif
 1730 
 1731         return (0);
 1732 }
 1733 
 1734 /*
 1735  * Remove a group from an interface
 1736  */
 1737 int
 1738 if_delgroup(struct ifnet *ifp, const char *groupname)
 1739 {
 1740         struct ifg_list         *ifgl;
 1741         struct ifg_member       *ifgm;
 1742 
 1743         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
 1744                 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
 1745                         break;
 1746         if (ifgl == NULL)
 1747                 return (ENOENT);
 1748 
 1749         TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
 1750 
 1751         TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
 1752                 if (ifgm->ifgm_ifp == ifp)
 1753                         break;
 1754 
 1755         if (ifgm != NULL) {
 1756                 TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
 1757                 free(ifgm, M_TEMP);
 1758         }
 1759 
 1760         if (--ifgl->ifgl_group->ifg_refcnt == 0) {
 1761                 TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
 1762 #if NPF > 0
 1763                 pfi_detach_ifgroup(ifgl->ifgl_group);
 1764 #endif
 1765                 free(ifgl->ifgl_group, M_TEMP);
 1766         }
 1767 
 1768         free(ifgl, M_TEMP);
 1769 
 1770 #if NPF > 0
 1771         pfi_group_change(groupname);
 1772 #endif
 1773 
 1774         return (0);
 1775 }
 1776 
 1777 /*
 1778  * Stores all groups from an interface in memory pointed
 1779  * to by data
 1780  */
 1781 int
 1782 if_getgroup(caddr_t data, struct ifnet *ifp)
 1783 {
 1784         int                      len, error;
 1785         struct ifg_list         *ifgl;
 1786         struct ifg_req           ifgrq, *ifgp;
 1787         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
 1788 
 1789         if (ifgr->ifgr_len == 0) {
 1790                 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
 1791                         ifgr->ifgr_len += sizeof(struct ifg_req);
 1792                 return (0);
 1793         }
 1794 
 1795         len = ifgr->ifgr_len;
 1796         ifgp = ifgr->ifgr_groups;
 1797         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
 1798                 if (len < sizeof(ifgrq))
 1799                         return (EINVAL);
 1800                 bzero(&ifgrq, sizeof ifgrq);
 1801                 strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
 1802                     sizeof(ifgrq.ifgrq_group));
 1803                 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
 1804                     sizeof(struct ifg_req))))
 1805                         return (error);
 1806                 len -= sizeof(ifgrq);
 1807                 ifgp++;
 1808         }
 1809 
 1810         return (0);
 1811 }
 1812 
 1813 /*
 1814  * Stores all members of a group in memory pointed to by data
 1815  */
 1816 int
 1817 if_getgroupmembers(caddr_t data)
 1818 {
 1819         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
 1820         struct ifg_group        *ifg;
 1821         struct ifg_member       *ifgm;
 1822         struct ifg_req           ifgrq, *ifgp;
 1823         int                      len, error;
 1824 
 1825         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
 1826                 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
 1827                         break;
 1828         if (ifg == NULL)
 1829                 return (ENOENT);
 1830 
 1831         if (ifgr->ifgr_len == 0) {
 1832                 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
 1833                         ifgr->ifgr_len += sizeof(ifgrq);
 1834                 return (0);
 1835         }
 1836 
 1837         len = ifgr->ifgr_len;
 1838         ifgp = ifgr->ifgr_groups;
 1839         TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
 1840                 if (len < sizeof(ifgrq))
 1841                         return (EINVAL);
 1842                 bzero(&ifgrq, sizeof ifgrq);
 1843                 strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
 1844                     sizeof(ifgrq.ifgrq_member));
 1845                 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
 1846                     sizeof(struct ifg_req))))
 1847                         return (error);
 1848                 len -= sizeof(ifgrq);
 1849                 ifgp++;
 1850         }
 1851 
 1852         return (0);
 1853 }
 1854 
 1855 int
 1856 if_getgroupattribs(caddr_t data)
 1857 {
 1858         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
 1859         struct ifg_group        *ifg;
 1860 
 1861         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
 1862                 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
 1863                         break;
 1864         if (ifg == NULL)
 1865                 return (ENOENT);
 1866 
 1867         ifgr->ifgr_attrib.ifg_carp_demoted = ifg->ifg_carp_demoted;
 1868 
 1869         return (0);
 1870 }
 1871 
 1872 int
 1873 if_setgroupattribs(caddr_t data)
 1874 {
 1875         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
 1876         struct ifg_group        *ifg;
 1877         struct ifg_member       *ifgm;
 1878         int                      demote;
 1879 
 1880         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
 1881                 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
 1882                         break;
 1883         if (ifg == NULL)
 1884                 return (ENOENT);
 1885 
 1886         demote = ifgr->ifgr_attrib.ifg_carp_demoted;
 1887         if (demote + ifg->ifg_carp_demoted > 0xff ||
 1888             demote + ifg->ifg_carp_demoted < 0)
 1889                 return (ERANGE);
 1890 
 1891         ifg->ifg_carp_demoted += demote;
 1892 
 1893         TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
 1894                 if (ifgm->ifgm_ifp->if_ioctl)
 1895                         ifgm->ifgm_ifp->if_ioctl(ifgm->ifgm_ifp,
 1896                             SIOCSIFGATTR, data);
 1897         return (0);
 1898 }
 1899 
 1900 void
 1901 if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
 1902 {
 1903         switch (dst->sa_family) {
 1904         case AF_INET:
 1905                 if (satosin(dst)->sin_addr.s_addr == INADDR_ANY &&
 1906                     mask && (mask->sa_len == 0 ||
 1907                     satosin(mask)->sin_addr.s_addr == INADDR_ANY))
 1908                         if_group_egress_build();
 1909                 break;
 1910 #ifdef INET6
 1911         case AF_INET6:
 1912                 if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
 1913                     &in6addr_any) && mask &&
 1914                     IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
 1915                     &in6addr_any))
 1916                         if_group_egress_build();
 1917                 break;
 1918 #endif
 1919         }
 1920 }
 1921 
 1922 int
 1923 if_group_egress_build(void)
 1924 {
 1925         struct ifg_group        *ifg;
 1926         struct ifg_member       *ifgm, *next;
 1927         struct sockaddr_in       sa_in;
 1928 #ifdef INET6
 1929         struct sockaddr_in6      sa_in6;
 1930 #endif
 1931         struct radix_node       *rn;
 1932         struct rtentry          *rt;
 1933 
 1934         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
 1935                 if (!strcmp(ifg->ifg_group, IFG_EGRESS))
 1936                         break;
 1937 
 1938         if (ifg != NULL)
 1939                 for (ifgm = TAILQ_FIRST(&ifg->ifg_members); ifgm; ifgm = next) {
 1940                         next = TAILQ_NEXT(ifgm, ifgm_next);
 1941                         if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS);
 1942                 }
 1943 
 1944         bzero(&sa_in, sizeof(sa_in));
 1945         sa_in.sin_len = sizeof(sa_in);
 1946         sa_in.sin_family = AF_INET;
 1947         if ((rn = rt_lookup(sintosa(&sa_in), sintosa(&sa_in), 0)) != NULL) {
 1948                 do {
 1949                         rt = (struct rtentry *)rn;
 1950                         if (rt->rt_ifp)
 1951                                 if_addgroup(rt->rt_ifp, IFG_EGRESS);
 1952 #ifndef SMALL_KERNEL
 1953                         rn = rn_mpath_next(rn, 0);
 1954 #else
 1955                         rn = NULL;
 1956 #endif
 1957                 } while (rn != NULL);
 1958         }
 1959 
 1960 #ifdef INET6
 1961         bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
 1962         if ((rn = rt_lookup(sin6tosa(&sa_in6), sin6tosa(&sa_in6), 0)) != NULL) {
 1963                 do {
 1964                         rt = (struct rtentry *)rn;
 1965                         if (rt->rt_ifp)
 1966                                 if_addgroup(rt->rt_ifp, IFG_EGRESS);
 1967 #ifndef SMALL_KERNEL
 1968                         rn = rn_mpath_next(rn, 0);
 1969 #else
 1970                         rn = NULL;
 1971 #endif
 1972                 } while (rn != NULL);
 1973         }
 1974 #endif
 1975 
 1976         return (0);
 1977 }
 1978 
 1979 /*
 1980  * Set/clear promiscuous mode on interface ifp based on the truth value
 1981  * of pswitch.  The calls are reference counted so that only the first
 1982  * "on" request actually has an effect, as does the final "off" request.
 1983  * Results are undefined if the "off" and "on" requests are not matched.
 1984  */
 1985 int
 1986 ifpromisc(struct ifnet *ifp, int pswitch)
 1987 {
 1988         struct ifreq ifr;
 1989 
 1990         if (pswitch) {
 1991                 /*
 1992                  * If the device is not configured up, we cannot put it in
 1993                  * promiscuous mode.
 1994                  */
 1995                 if ((ifp->if_flags & IFF_UP) == 0)
 1996                         return (ENETDOWN);
 1997                 if (ifp->if_pcount++ != 0)
 1998                         return (0);
 1999                 ifp->if_flags |= IFF_PROMISC;
 2000         } else {
 2001                 if (--ifp->if_pcount > 0)
 2002                         return (0);
 2003                 ifp->if_flags &= ~IFF_PROMISC;
 2004                 /*
 2005                  * If the device is not configured up, we should not need to
 2006                  * turn off promiscuous mode (device should have turned it
 2007                  * off when interface went down; and will look at IFF_PROMISC
 2008                  * again next time interface comes up).
 2009                  */
 2010                 if ((ifp->if_flags & IFF_UP) == 0)
 2011                         return (0);
 2012         }
 2013         ifr.ifr_flags = ifp->if_flags;
 2014         return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
 2015 }
 2016 
 2017 int
 2018 sysctl_ifq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
 2019     void *newp, size_t newlen, struct ifqueue *ifq)
 2020 {
 2021         /* All sysctl names at this level are terminal. */
 2022         if (namelen != 1)
 2023                 return (ENOTDIR);
 2024 
 2025         switch (name[0]) {
 2026         case IFQCTL_LEN:
 2027                 return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_len));
 2028         case IFQCTL_MAXLEN:
 2029                 return (sysctl_int(oldp, oldlenp, newp, newlen,
 2030                     &ifq->ifq_maxlen));
 2031         case IFQCTL_DROPS:
 2032                 return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_drops));
 2033         default:
 2034                 return (EOPNOTSUPP);
 2035         }
 2036         /* NOTREACHED */
 2037 }
 2038 
 2039 void
 2040 m_clinitifp(struct ifnet *ifp)
 2041 {
 2042         extern u_int mclsizes[];
 2043         int i;
 2044 
 2045         /* Initialize high water marks for use of cluster pools */
 2046         for (i = 0; i < MCLPOOLS; i++) {
 2047                 ifp->if_mclstat.mclpool[i].mcl_hwm = MAX(4,
 2048                     ifp->if_mclstat.mclpool[i].mcl_lwm);
 2049                 ifp->if_mclstat.mclpool[i].mcl_size = mclsizes[i];
 2050         }
 2051 }
 2052 
 2053 void
 2054 m_clsetlwm(struct ifnet *ifp, u_int pktlen, u_int lwm)
 2055 {
 2056         extern u_int mclsizes[];
 2057         int i;
 2058 
 2059         for (i = 0; i < MCLPOOLS; i++) {
 2060                 if (pktlen <= mclsizes[i])
 2061                         break;
 2062         }
 2063         if (i >= MCLPOOLS)
 2064                 return;
 2065 
 2066         ifp->if_mclstat.mclpool[i].mcl_lwm = lwm;
 2067 }
 2068 
 2069 int
 2070 m_cldrop(struct ifnet *ifp, int pi)
 2071 {
 2072         static int livelock, liveticks;
 2073         struct mclstat *mcls;
 2074         extern int ticks;
 2075         int i;
 2076 
 2077         if (livelock == 0 && ticks - m_clticks > 2) {
 2078                 struct ifnet *aifp;
 2079 
 2080                 /*
 2081                  * Timeout did not run, so we are in some kind of livelock.
 2082                  * Decrease the cluster allocation high water marks on all
 2083                  * interfaces and prevent them from growth for the very near
 2084                  * future.
 2085                  */
 2086                 livelock = 1;
 2087                 liveticks = ticks;
 2088                 TAILQ_FOREACH(aifp, &ifnet, if_list) {
 2089                         mcls = &aifp->if_mclstat;
 2090                         for (i = 0; i < nitems(mcls->mclpool); i++)
 2091                                 mcls->mclpool[i].mcl_hwm =
 2092                                     max(mcls->mclpool[i].mcl_hwm / 2,
 2093                                     mcls->mclpool[i].mcl_lwm);
 2094                 }
 2095         } else if (livelock && ticks - liveticks > 5)
 2096                 livelock = 0;   /* Let the high water marks grow again */
 2097 
 2098         mcls = &ifp->if_mclstat;
 2099         if (mcls->mclpool[pi].mcl_alive <= 2 &&
 2100             mcls->mclpool[pi].mcl_hwm < 32768 &&
 2101             ISSET(ifp->if_flags, IFF_RUNNING) && livelock == 0) {
 2102                 /* About to run out, so increase the watermark */
 2103                 mcls->mclpool[pi].mcl_hwm++;
 2104         } else if (mcls->mclpool[pi].mcl_alive >= mcls->mclpool[pi].mcl_hwm)
 2105                 return (1);             /* No more packets given */
 2106 
 2107         return (0);
 2108 }
 2109 
 2110 void
 2111 m_clcount(struct ifnet *ifp, int pi)
 2112 {
 2113         ifp->if_mclstat.mclpool[pi].mcl_alive++;
 2114 }
 2115 
 2116 void
 2117 m_cluncount(struct mbuf *m, int all)
 2118 {
 2119         struct mbuf_ext *me;
 2120 
 2121         do {
 2122                 me = &m->m_ext;
 2123                 if (((m->m_flags & (M_EXT|M_CLUSTER)) != (M_EXT|M_CLUSTER)) ||
 2124                     (me->ext_ifp == NULL))
 2125                         continue;
 2126 
 2127                 me->ext_ifp->if_mclstat.mclpool[me->ext_backend].mcl_alive--;
 2128                 me->ext_ifp = NULL;
 2129         } while (all && (m = m->m_next));
 2130 }

Cache object: 87cefc890a38912d68c23b5e0bd921f3


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