LCOV - code coverage report
Current view: top level - net - if.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1429 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 93 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if.c,v 1.564 2018/09/11 10:23:40 krw 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 "bpfilter.h"
      65             : #include "bridge.h"
      66             : #include "carp.h"
      67             : #include "ether.h"
      68             : #include "pf.h"
      69             : #include "pfsync.h"
      70             : #include "ppp.h"
      71             : #include "pppoe.h"
      72             : #include "switch.h"
      73             : #include "trunk.h"
      74             : 
      75             : #include <sys/param.h>
      76             : #include <sys/systm.h>
      77             : #include <sys/mbuf.h>
      78             : #include <sys/socket.h>
      79             : #include <sys/socketvar.h>
      80             : #include <sys/timeout.h>
      81             : #include <sys/protosw.h>
      82             : #include <sys/kernel.h>
      83             : #include <sys/ioctl.h>
      84             : #include <sys/domain.h>
      85             : #include <sys/task.h>
      86             : #include <sys/atomic.h>
      87             : #include <sys/proc.h>
      88             : 
      89             : #include <dev/rndvar.h>
      90             : 
      91             : #include <net/if.h>
      92             : #include <net/if_dl.h>
      93             : #include <net/if_types.h>
      94             : #include <net/route.h>
      95             : #include <net/netisr.h>
      96             : 
      97             : #include <netinet/in.h>
      98             : #include <netinet/if_ether.h>
      99             : #include <netinet/igmp.h>
     100             : #ifdef MROUTING
     101             : #include <netinet/ip_mroute.h>
     102             : #endif
     103             : 
     104             : #ifdef INET6
     105             : #include <netinet6/in6_var.h>
     106             : #include <netinet6/in6_ifattach.h>
     107             : #include <netinet6/nd6.h>
     108             : #include <netinet/ip6.h>
     109             : #include <netinet6/ip6_var.h>
     110             : #endif
     111             : 
     112             : #ifdef MPLS
     113             : #include <netmpls/mpls.h>
     114             : #endif
     115             : 
     116             : #if NBPFILTER > 0
     117             : #include <net/bpf.h>
     118             : #endif
     119             : 
     120             : #if NBRIDGE > 0
     121             : #include <net/if_bridge.h>
     122             : #endif
     123             : 
     124             : #if NCARP > 0
     125             : #include <netinet/ip_carp.h>
     126             : #endif
     127             : 
     128             : #if NPF > 0
     129             : #include <net/pfvar.h>
     130             : #endif
     131             : 
     132             : #include <sys/device.h>
     133             : 
     134             : void    if_attachsetup(struct ifnet *);
     135             : void    if_attachdomain(struct ifnet *);
     136             : void    if_attach_common(struct ifnet *);
     137             : int     if_createrdomain(int, struct ifnet *);
     138             : int     if_setrdomain(struct ifnet *, int);
     139             : void    if_slowtimo(void *);
     140             : 
     141             : void    if_detached_qstart(struct ifqueue *);
     142             : int     if_detached_ioctl(struct ifnet *, u_long, caddr_t);
     143             : 
     144             : int     ifioctl_get(u_long, caddr_t);
     145             : int     ifconf(caddr_t);
     146             : 
     147             : int     if_getgroup(caddr_t, struct ifnet *);
     148             : int     if_getgroupmembers(caddr_t);
     149             : int     if_getgroupattribs(caddr_t);
     150             : int     if_setgroupattribs(caddr_t);
     151             : int     if_getgrouplist(caddr_t);
     152             : 
     153             : void    if_linkstate(struct ifnet *);
     154             : void    if_linkstate_task(void *);
     155             : 
     156             : int     if_clone_list(struct if_clonereq *);
     157             : struct if_clone *if_clone_lookup(const char *, int *);
     158             : 
     159             : int     if_group_egress_build(void);
     160             : 
     161             : void    if_watchdog_task(void *);
     162             : 
     163             : void    if_netisr(void *);
     164             : 
     165             : #ifdef DDB
     166             : void    ifa_print_all(void);
     167             : #endif
     168             : 
     169             : void    if_qstart_compat(struct ifqueue *);
     170             : 
     171             : /*
     172             :  * interface index map
     173             :  *
     174             :  * the kernel maintains a mapping of interface indexes to struct ifnet
     175             :  * pointers.
     176             :  *
     177             :  * the map is an array of struct ifnet pointers prefixed by an if_map
     178             :  * structure. the if_map structure stores the length of its array.
     179             :  *
     180             :  * as interfaces are attached to the system, the map is grown on demand
     181             :  * up to USHRT_MAX entries.
     182             :  *
     183             :  * interface index 0 is reserved and represents no interface. this
     184             :  * supports the use of the interface index as the scope for IPv6 link
     185             :  * local addresses, where scope 0 means no scope has been specified.
     186             :  * it also supports the use of interface index as the unique identifier
     187             :  * for network interfaces in SNMP applications as per RFC2863. therefore
     188             :  * if_get(0) returns NULL.
     189             :  */
     190             : 
     191             : void if_ifp_dtor(void *, void *);
     192             : void if_map_dtor(void *, void *);
     193             : struct ifnet *if_ref(struct ifnet *);
     194             : 
     195             : /*
     196             :  * struct if_map
     197             :  *
     198             :  * bounded array of ifnet srp pointers used to fetch references of live
     199             :  * interfaces with if_get().
     200             :  */
     201             : 
     202             : struct if_map {
     203             :         unsigned long            limit;
     204             :         /* followed by limit ifnet srp pointers */
     205             : };
     206             : 
     207             : /*
     208             :  * struct if_idxmap
     209             :  *
     210             :  * infrastructure to manage updates and accesses to the current if_map.
     211             :  */
     212             : 
     213             : struct if_idxmap {
     214             :         unsigned int             serial;
     215             :         unsigned int             count;
     216             :         struct srp               map;
     217             : };
     218             : 
     219             : void    if_idxmap_init(unsigned int);
     220             : void    if_idxmap_insert(struct ifnet *);
     221             : void    if_idxmap_remove(struct ifnet *);
     222             : 
     223             : TAILQ_HEAD(, ifg_group) ifg_head = TAILQ_HEAD_INITIALIZER(ifg_head);
     224             : 
     225             : LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
     226             : int if_cloners_count;
     227             : 
     228             : struct timeout net_tick_to;
     229             : void    net_tick(void *);
     230             : int     net_livelocked(void);
     231             : int     ifq_congestion;
     232             : 
     233             : int              netisr;
     234             : 
     235             : #define NET_TASKQ       1
     236             : struct taskq    *nettqmp[NET_TASKQ];
     237             : 
     238             : struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL);
     239             : 
     240             : /*
     241             :  * Serialize socket operations to ensure no new sleeping points
     242             :  * are introduced in IP output paths.
     243             :  */
     244             : struct rwlock netlock = RWLOCK_INITIALIZER("netlock");
     245             : 
     246             : /*
     247             :  * Network interface utility routines.
     248             :  */
     249             : void
     250           0 : ifinit(void)
     251             : {
     252             :         unsigned int    i;
     253             : 
     254             :         /*
     255             :          * most machines boot with 4 or 5 interfaces, so size the initial map
     256             :          * to accomodate this
     257             :          */
     258           0 :         if_idxmap_init(8);
     259             : 
     260           0 :         timeout_set(&net_tick_to, net_tick, &net_tick_to);
     261             : 
     262           0 :         for (i = 0; i < NET_TASKQ; i++) {
     263           0 :                 nettqmp[i] = taskq_create("softnet", 1, IPL_NET, TASKQ_MPSAFE);
     264           0 :                 if (nettqmp[i] == NULL)
     265           0 :                         panic("unable to create network taskq %d", i);
     266             :         }
     267             : 
     268           0 :         net_tick(&net_tick_to);
     269           0 : }
     270             : 
     271             : static struct if_idxmap if_idxmap = {
     272             :         0,
     273             :         0,
     274             :         SRP_INITIALIZER()
     275             : };
     276             : 
     277             : struct srp_gc if_ifp_gc = SRP_GC_INITIALIZER(if_ifp_dtor, NULL);
     278             : struct srp_gc if_map_gc = SRP_GC_INITIALIZER(if_map_dtor, NULL);
     279             : 
     280             : struct ifnet_head ifnet = TAILQ_HEAD_INITIALIZER(ifnet);
     281             : 
     282             : void
     283           0 : if_idxmap_init(unsigned int limit)
     284             : {
     285             :         struct if_map *if_map;
     286             :         struct srp *map;
     287             :         unsigned int i;
     288             : 
     289           0 :         if_idxmap.serial = 1; /* skip ifidx 0 so it can return NULL */
     290             : 
     291           0 :         if_map = malloc(sizeof(*if_map) + limit * sizeof(*map),
     292             :             M_IFADDR, M_WAITOK);
     293             : 
     294           0 :         if_map->limit = limit;
     295           0 :         map = (struct srp *)(if_map + 1);
     296           0 :         for (i = 0; i < limit; i++)
     297           0 :                 srp_init(&map[i]);
     298             : 
     299             :         /* this is called early so there's nothing to race with */
     300           0 :         srp_update_locked(&if_map_gc, &if_idxmap.map, if_map);
     301           0 : }
     302             : 
     303             : void
     304           0 : if_idxmap_insert(struct ifnet *ifp)
     305             : {
     306             :         struct if_map *if_map;
     307             :         struct srp *map;
     308             :         unsigned int index, i;
     309             : 
     310           0 :         refcnt_init(&ifp->if_refcnt);
     311             : 
     312             :         /* the kernel lock guarantees serialised modifications to if_idxmap */
     313           0 :         KERNEL_ASSERT_LOCKED();
     314             : 
     315           0 :         if (++if_idxmap.count > USHRT_MAX)
     316           0 :                 panic("too many interfaces");
     317             : 
     318           0 :         if_map = srp_get_locked(&if_idxmap.map);
     319           0 :         map = (struct srp *)(if_map + 1);
     320             : 
     321           0 :         index = if_idxmap.serial++ & USHRT_MAX;
     322             : 
     323           0 :         if (index >= if_map->limit) {
     324             :                 struct if_map *nif_map;
     325             :                 struct srp *nmap;
     326             :                 unsigned int nlimit;
     327             :                 struct ifnet *nifp;
     328             : 
     329           0 :                 nlimit = if_map->limit * 2;
     330           0 :                 nif_map = malloc(sizeof(*nif_map) + nlimit * sizeof(*nmap),
     331             :                     M_IFADDR, M_WAITOK);
     332           0 :                 nmap = (struct srp *)(nif_map + 1);
     333             : 
     334           0 :                 nif_map->limit = nlimit;
     335           0 :                 for (i = 0; i < if_map->limit; i++) {
     336           0 :                         srp_init(&nmap[i]);
     337           0 :                         nifp = srp_get_locked(&map[i]);
     338           0 :                         if (nifp != NULL) {
     339           0 :                                 srp_update_locked(&if_ifp_gc, &nmap[i],
     340           0 :                                     if_ref(nifp));
     341           0 :                         }
     342             :                 }
     343             : 
     344           0 :                 while (i < nlimit) {
     345           0 :                         srp_init(&nmap[i]);
     346           0 :                         i++;
     347             :                 }
     348             : 
     349           0 :                 srp_update_locked(&if_map_gc, &if_idxmap.map, nif_map);
     350             :                 if_map = nif_map;
     351             :                 map = nmap;
     352           0 :         }
     353             : 
     354             :         /* pick the next free index */
     355           0 :         for (i = 0; i < USHRT_MAX; i++) {
     356           0 :                 if (index != 0 && srp_get_locked(&map[index]) == NULL)
     357             :                         break;
     358             : 
     359           0 :                 index = if_idxmap.serial++ & USHRT_MAX;
     360             :         }
     361             : 
     362             :         /* commit */
     363           0 :         ifp->if_index = index;
     364           0 :         srp_update_locked(&if_ifp_gc, &map[index], if_ref(ifp));
     365           0 : }
     366             : 
     367             : void
     368           0 : if_idxmap_remove(struct ifnet *ifp)
     369             : {
     370             :         struct if_map *if_map;
     371             :         struct srp *map;
     372             :         unsigned int index;
     373             : 
     374           0 :         index = ifp->if_index;
     375             : 
     376             :         /* the kernel lock guarantees serialised modifications to if_idxmap */
     377           0 :         KERNEL_ASSERT_LOCKED();
     378             : 
     379           0 :         if_map = srp_get_locked(&if_idxmap.map);
     380           0 :         KASSERT(index < if_map->limit);
     381             : 
     382           0 :         map = (struct srp *)(if_map + 1);
     383           0 :         KASSERT(ifp == (struct ifnet *)srp_get_locked(&map[index]));
     384             : 
     385           0 :         srp_update_locked(&if_ifp_gc, &map[index], NULL);
     386           0 :         if_idxmap.count--;
     387             :         /* end of if_idxmap modifications */
     388             : 
     389             :         /* sleep until the last reference is released */
     390           0 :         refcnt_finalize(&ifp->if_refcnt, "ifidxrm");
     391           0 : }
     392             : 
     393             : void
     394           0 : if_ifp_dtor(void *null, void *ifp)
     395             : {
     396           0 :         if_put(ifp);
     397           0 : }
     398             : 
     399             : void
     400           0 : if_map_dtor(void *null, void *m)
     401             : {
     402           0 :         struct if_map *if_map = m;
     403           0 :         struct srp *map = (struct srp *)(if_map + 1);
     404             :         unsigned int i;
     405             : 
     406             :         /*
     407             :          * dont need to serialize the use of update_locked since this is
     408             :          * the last reference to this map. there's nothing to race against.
     409             :          */
     410           0 :         for (i = 0; i < if_map->limit; i++)
     411           0 :                 srp_update_locked(&if_ifp_gc, &map[i], NULL);
     412             : 
     413           0 :         free(if_map, M_IFADDR, sizeof(*if_map) + if_map->limit * sizeof(*map));
     414           0 : }
     415             : 
     416             : /*
     417             :  * Attach an interface to the
     418             :  * list of "active" interfaces.
     419             :  */
     420             : void
     421           0 : if_attachsetup(struct ifnet *ifp)
     422             : {
     423             :         unsigned long ifidx;
     424             : 
     425           0 :         NET_ASSERT_LOCKED();
     426             : 
     427           0 :         TAILQ_INIT(&ifp->if_groups);
     428             : 
     429           0 :         if_addgroup(ifp, IFG_ALL);
     430             : 
     431           0 :         if_attachdomain(ifp);
     432             : #if NPF > 0
     433           0 :         pfi_attach_ifnet(ifp);
     434             : #endif
     435             : 
     436           0 :         timeout_set(&ifp->if_slowtimo, if_slowtimo, ifp);
     437           0 :         if_slowtimo(ifp);
     438             : 
     439           0 :         if_idxmap_insert(ifp);
     440           0 :         KASSERT(if_get(0) == NULL);
     441             : 
     442           0 :         ifidx = ifp->if_index;
     443             : 
     444           0 :         task_set(&ifp->if_watchdogtask, if_watchdog_task, (void *)ifidx);
     445           0 :         task_set(&ifp->if_linkstatetask, if_linkstate_task, (void *)ifidx);
     446             : 
     447             :         /* Announce the interface. */
     448           0 :         rtm_ifannounce(ifp, IFAN_ARRIVAL);
     449           0 : }
     450             : 
     451             : /*
     452             :  * Allocate the link level name for the specified interface.  This
     453             :  * is an attachment helper.  It must be called after ifp->if_addrlen
     454             :  * is initialized, which may not be the case when if_attach() is
     455             :  * called.
     456             :  */
     457             : void
     458           0 : if_alloc_sadl(struct ifnet *ifp)
     459             : {
     460             :         unsigned int socksize;
     461             :         int namelen, masklen;
     462             :         struct sockaddr_dl *sdl;
     463             : 
     464             :         /*
     465             :          * If the interface already has a link name, release it
     466             :          * now.  This is useful for interfaces that can change
     467             :          * link types, and thus switch link names often.
     468             :          */
     469           0 :         if (ifp->if_sadl != NULL)
     470           0 :                 if_free_sadl(ifp);
     471             : 
     472           0 :         namelen = strlen(ifp->if_xname);
     473           0 :         masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
     474           0 :         socksize = masklen + ifp->if_addrlen;
     475             : #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
     476           0 :         if (socksize < sizeof(*sdl))
     477             :                 socksize = sizeof(*sdl);
     478           0 :         socksize = ROUNDUP(socksize);
     479           0 :         sdl = malloc(socksize, M_IFADDR, M_WAITOK|M_ZERO);
     480           0 :         sdl->sdl_len = socksize;
     481           0 :         sdl->sdl_family = AF_LINK;
     482           0 :         bcopy(ifp->if_xname, sdl->sdl_data, namelen);
     483           0 :         sdl->sdl_nlen = namelen;
     484           0 :         sdl->sdl_alen = ifp->if_addrlen;
     485           0 :         sdl->sdl_index = ifp->if_index;
     486           0 :         sdl->sdl_type = ifp->if_type;
     487           0 :         ifp->if_sadl = sdl;
     488           0 : }
     489             : 
     490             : /*
     491             :  * Free the link level name for the specified interface.  This is
     492             :  * a detach helper.  This is called from if_detach() or from
     493             :  * link layer type specific detach functions.
     494             :  */
     495             : void
     496           0 : if_free_sadl(struct ifnet *ifp)
     497             : {
     498           0 :         free(ifp->if_sadl, M_IFADDR, 0);
     499           0 :         ifp->if_sadl = NULL;
     500           0 : }
     501             : 
     502             : void
     503           0 : if_attachdomain(struct ifnet *ifp)
     504             : {
     505             :         struct domain *dp;
     506             :         int i, s;
     507             : 
     508           0 :         s = splnet();
     509             : 
     510             :         /* address family dependent data region */
     511           0 :         bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
     512           0 :         for (i = 0; (dp = domains[i]) != NULL; i++) {
     513           0 :                 if (dp->dom_ifattach)
     514           0 :                         ifp->if_afdata[dp->dom_family] =
     515           0 :                             (*dp->dom_ifattach)(ifp);
     516             :         }
     517             : 
     518           0 :         splx(s);
     519           0 : }
     520             : 
     521             : void
     522           0 : if_attachhead(struct ifnet *ifp)
     523             : {
     524           0 :         if_attach_common(ifp);
     525           0 :         NET_LOCK();
     526           0 :         TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
     527           0 :         if_attachsetup(ifp);
     528           0 :         NET_UNLOCK();
     529           0 : }
     530             : 
     531             : void
     532           0 : if_attach(struct ifnet *ifp)
     533             : {
     534           0 :         if_attach_common(ifp);
     535           0 :         NET_LOCK();
     536           0 :         TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
     537           0 :         if_attachsetup(ifp);
     538           0 :         NET_UNLOCK();
     539           0 : }
     540             : 
     541             : void
     542           0 : if_attach_queues(struct ifnet *ifp, unsigned int nqs)
     543             : {
     544             :         struct ifqueue **map;
     545             :         struct ifqueue *ifq;
     546             :         int i;
     547             : 
     548           0 :         KASSERT(ifp->if_ifqs == ifp->if_snd.ifq_ifqs);
     549           0 :         KASSERT(nqs != 0);
     550             : 
     551           0 :         map = mallocarray(sizeof(*map), nqs, M_DEVBUF, M_WAITOK);
     552             : 
     553           0 :         ifp->if_snd.ifq_softc = NULL;
     554           0 :         map[0] = &ifp->if_snd;
     555             : 
     556           0 :         for (i = 1; i < nqs; i++) {
     557           0 :                 ifq = malloc(sizeof(*ifq), M_DEVBUF, M_WAITOK|M_ZERO);
     558           0 :                 ifq_set_maxlen(ifq, ifp->if_snd.ifq_maxlen);
     559           0 :                 ifq_init(ifq, ifp, i);
     560           0 :                 map[i] = ifq;
     561             :         }
     562             : 
     563           0 :         ifp->if_ifqs = map;
     564           0 :         ifp->if_nifqs = nqs;
     565           0 : }
     566             : 
     567             : void
     568           0 : if_attach_iqueues(struct ifnet *ifp, unsigned int niqs)
     569             : {
     570             :         struct ifiqueue **map;
     571             :         struct ifiqueue *ifiq;
     572             :         unsigned int i;
     573             : 
     574           0 :         KASSERT(niqs != 0);
     575             : 
     576           0 :         map = mallocarray(niqs, sizeof(*map), M_DEVBUF, M_WAITOK);
     577             : 
     578           0 :         ifp->if_rcv.ifiq_softc = NULL;
     579           0 :         map[0] = &ifp->if_rcv;
     580             : 
     581           0 :         for (i = 1; i < niqs; i++) {
     582           0 :                 ifiq = malloc(sizeof(*ifiq), M_DEVBUF, M_WAITOK|M_ZERO);
     583           0 :                 ifiq_init(ifiq, ifp, i);
     584           0 :                 map[i] = ifiq;
     585             :         }
     586             : 
     587           0 :         ifp->if_iqs = map;
     588           0 :         ifp->if_niqs = niqs;
     589           0 : }
     590             : 
     591             : void
     592           0 : if_attach_common(struct ifnet *ifp)
     593             : {
     594           0 :         KASSERT(ifp->if_ioctl != NULL);
     595             : 
     596           0 :         TAILQ_INIT(&ifp->if_addrlist);
     597           0 :         TAILQ_INIT(&ifp->if_maddrlist);
     598             : 
     599           0 :         if (!ISSET(ifp->if_xflags, IFXF_MPSAFE)) {
     600           0 :                 KASSERTMSG(ifp->if_qstart == NULL,
     601             :                     "%s: if_qstart set without MPSAFE set", ifp->if_xname);
     602           0 :                 ifp->if_qstart = if_qstart_compat;
     603           0 :         } else {
     604           0 :                 KASSERTMSG(ifp->if_start == NULL,
     605             :                     "%s: if_start set with MPSAFE set", ifp->if_xname);
     606           0 :                 KASSERTMSG(ifp->if_qstart != NULL,
     607             :                     "%s: if_qstart not set with MPSAFE set", ifp->if_xname);
     608             :         }
     609             : 
     610           0 :         ifq_init(&ifp->if_snd, ifp, 0);
     611             : 
     612           0 :         ifp->if_snd.ifq_ifqs[0] = &ifp->if_snd;
     613           0 :         ifp->if_ifqs = ifp->if_snd.ifq_ifqs;
     614           0 :         ifp->if_nifqs = 1;
     615             : 
     616           0 :         ifiq_init(&ifp->if_rcv, ifp, 0);
     617             : 
     618           0 :         ifp->if_rcv.ifiq_ifiqs[0] = &ifp->if_rcv;
     619           0 :         ifp->if_iqs = ifp->if_rcv.ifiq_ifiqs;
     620           0 :         ifp->if_niqs = 1;
     621             : 
     622           0 :         ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
     623             :             M_TEMP, M_WAITOK);
     624           0 :         TAILQ_INIT(ifp->if_addrhooks);
     625           0 :         ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
     626             :             M_TEMP, M_WAITOK);
     627           0 :         TAILQ_INIT(ifp->if_linkstatehooks);
     628           0 :         ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
     629             :             M_TEMP, M_WAITOK);
     630           0 :         TAILQ_INIT(ifp->if_detachhooks);
     631             : 
     632           0 :         if (ifp->if_rtrequest == NULL)
     633           0 :                 ifp->if_rtrequest = if_rtrequest_dummy;
     634           0 :         ifp->if_llprio = IFQ_DEFPRIO;
     635             : 
     636           0 :         SRPL_INIT(&ifp->if_inputs);
     637           0 : }
     638             : 
     639             : void
     640           0 : if_attach_ifq(struct ifnet *ifp, const struct ifq_ops *newops, void *args)
     641             : {
     642             :         /*
     643             :          * only switch the ifq_ops on the first ifq on an interface.
     644             :          *
     645             :          * the only ifq_ops we provide priq and hfsc, and hfsc only
     646             :          * works on a single ifq. because the code uses the ifq_ops
     647             :          * on the first ifq (if_snd) to select a queue for an mbuf,
     648             :          * by switching only the first one we change both the algorithm
     649             :          * and force the routing of all new packets to it.
     650             :          */
     651           0 :         ifq_attach(&ifp->if_snd, newops, args);
     652           0 : }
     653             : 
     654             : void
     655           0 : if_start(struct ifnet *ifp)
     656             : {
     657           0 :         KASSERT(ifp->if_qstart == if_qstart_compat);
     658           0 :         if_qstart_compat(&ifp->if_snd);
     659           0 : }
     660             : void
     661           0 : if_qstart_compat(struct ifqueue *ifq)
     662             : {
     663           0 :         struct ifnet *ifp = ifq->ifq_if;
     664             :         int s;
     665             : 
     666             :         /*
     667             :          * the stack assumes that an interface can have multiple
     668             :          * transmit rings, but a lot of drivers are still written
     669             :          * so that interfaces and send rings have a 1:1 mapping.
     670             :          * this provides compatability between the stack and the older
     671             :          * drivers by translating from the only queue they have
     672             :          * (ifp->if_snd) back to the interface and calling if_start.
     673             :          */
     674             : 
     675           0 :         KERNEL_LOCK();
     676           0 :         s = splnet();
     677           0 :         (*ifp->if_start)(ifp);
     678           0 :         splx(s);
     679           0 :         KERNEL_UNLOCK();
     680           0 : }
     681             : 
     682             : int
     683           0 : if_enqueue(struct ifnet *ifp, struct mbuf *m)
     684             : {
     685             :         unsigned int idx;
     686             :         struct ifqueue *ifq;
     687             :         int error;
     688             : 
     689             : #if NPF > 0
     690           0 :         if (m->m_pkthdr.pf.delay > 0)
     691           0 :                 return (pf_delay_pkt(m, ifp->if_index));
     692             : #endif
     693             : 
     694             : #if NBRIDGE > 0
     695           0 :         if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) {
     696           0 :                 KERNEL_LOCK();
     697           0 :                 error = bridge_output(ifp, m, NULL, NULL);
     698           0 :                 KERNEL_UNLOCK();
     699           0 :                 return (error);
     700             :         }
     701             : #endif
     702             : 
     703             : #if NPF > 0
     704           0 :         pf_pkt_addr_changed(m);
     705             : #endif  /* NPF > 0 */
     706             : 
     707             :         /*
     708             :          * use the operations on the first ifq to pick which of the array
     709             :          * gets this mbuf.
     710             :          */
     711           0 :         idx = ifq_idx(&ifp->if_snd, ifp->if_nifqs, m);
     712           0 :         ifq = ifp->if_ifqs[idx];
     713             : 
     714           0 :         error = ifq_enqueue(ifq, m);
     715           0 :         if (error)
     716           0 :                 return (error);
     717             : 
     718           0 :         ifq_start(ifq);
     719             : 
     720           0 :         return (0);
     721           0 : }
     722             : 
     723             : void
     724           0 : if_input(struct ifnet *ifp, struct mbuf_list *ml)
     725             : {
     726           0 :         ifiq_input(&ifp->if_rcv, ml, 2048);
     727           0 : }
     728             : 
     729             : int
     730           0 : if_input_local(struct ifnet *ifp, struct mbuf *m, sa_family_t af)
     731             : {
     732             : #if NBPFILTER > 0
     733             :         /*
     734             :          * Only send packets to bpf if they are destinated to local
     735             :          * addresses.
     736             :          *
     737             :          * if_input_local() is also called for SIMPLEX interfaces to
     738             :          * duplicate packets for local use.  But don't dup them to bpf.
     739             :          */
     740           0 :         if (ifp->if_flags & IFF_LOOPBACK) {
     741           0 :                 caddr_t if_bpf = ifp->if_bpf;
     742             : 
     743           0 :                 if (if_bpf)
     744           0 :                         bpf_mtap_af(if_bpf, af, m, BPF_DIRECTION_OUT);
     745           0 :         }
     746             : #endif
     747           0 :         m_resethdr(m);
     748           0 :         m->m_flags |= M_LOOP;
     749           0 :         m->m_pkthdr.ph_ifidx = ifp->if_index;
     750           0 :         m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
     751             : 
     752           0 :         ifp->if_opackets++;
     753           0 :         ifp->if_obytes += m->m_pkthdr.len;
     754             : 
     755           0 :         ifp->if_ipackets++;
     756           0 :         ifp->if_ibytes += m->m_pkthdr.len;
     757             : 
     758           0 :         switch (af) {
     759             :         case AF_INET:
     760           0 :                 ipv4_input(ifp, m);
     761           0 :                 break;
     762             : #ifdef INET6
     763             :         case AF_INET6:
     764           0 :                 ipv6_input(ifp, m);
     765           0 :                 break;
     766             : #endif /* INET6 */
     767             : #ifdef MPLS
     768             :         case AF_MPLS:
     769           0 :                 mpls_input(ifp, m);
     770           0 :                 break;
     771             : #endif /* MPLS */
     772             :         default:
     773           0 :                 printf("%s: can't handle af%d\n", ifp->if_xname, af);
     774           0 :                 m_freem(m);
     775           0 :                 return (EAFNOSUPPORT);
     776             :         }
     777             : 
     778           0 :         return (0);
     779           0 : }
     780             : 
     781             : int
     782           0 : if_output_local(struct ifnet *ifp, struct mbuf *m, sa_family_t af)
     783             : {
     784             :         struct ifiqueue *ifiq;
     785             :         unsigned int flow = 0;
     786             : 
     787           0 :         m->m_pkthdr.ph_family = af;
     788           0 :         m->m_pkthdr.ph_ifidx = ifp->if_index;
     789           0 :         m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
     790             : 
     791           0 :         if (ISSET(m->m_pkthdr.ph_flowid, M_FLOWID_VALID))
     792           0 :                 flow = m->m_pkthdr.ph_flowid & M_FLOWID_MASK;
     793             : 
     794           0 :         ifiq = ifp->if_iqs[flow % ifp->if_niqs];
     795             : 
     796           0 :         return (ifiq_enqueue(ifiq, m) == 0 ? 0 : ENOBUFS);
     797             : }
     798             : 
     799             : struct ifih {
     800             :         SRPL_ENTRY(ifih)          ifih_next;
     801             :         int                     (*ifih_input)(struct ifnet *, struct mbuf *,
     802             :                                       void *);
     803             :         void                     *ifih_cookie;
     804             :         int                       ifih_refcnt;
     805             :         struct refcnt             ifih_srpcnt;
     806             : };
     807             : 
     808             : void    if_ih_ref(void *, void *);
     809             : void    if_ih_unref(void *, void *);
     810             : 
     811             : struct srpl_rc ifih_rc = SRPL_RC_INITIALIZER(if_ih_ref, if_ih_unref, NULL);
     812             : 
     813             : void
     814           0 : if_ih_insert(struct ifnet *ifp, int (*input)(struct ifnet *, struct mbuf *,
     815             :     void *), void *cookie)
     816             : {
     817             :         struct ifih *ifih;
     818             : 
     819             :         /* the kernel lock guarantees serialised modifications to if_inputs */
     820           0 :         KERNEL_ASSERT_LOCKED();
     821             : 
     822           0 :         SRPL_FOREACH_LOCKED(ifih, &ifp->if_inputs, ifih_next) {
     823           0 :                 if (ifih->ifih_input == input && ifih->ifih_cookie == cookie) {
     824           0 :                         ifih->ifih_refcnt++;
     825           0 :                         break;
     826             :                 }
     827             :         }
     828             : 
     829           0 :         if (ifih == NULL) {
     830           0 :                 ifih = malloc(sizeof(*ifih), M_DEVBUF, M_WAITOK);
     831             : 
     832           0 :                 ifih->ifih_input = input;
     833           0 :                 ifih->ifih_cookie = cookie;
     834           0 :                 ifih->ifih_refcnt = 1;
     835           0 :                 refcnt_init(&ifih->ifih_srpcnt);
     836           0 :                 SRPL_INSERT_HEAD_LOCKED(&ifih_rc, &ifp->if_inputs,
     837             :                     ifih, ifih_next);
     838           0 :         }
     839           0 : }
     840             : 
     841             : void
     842           0 : if_ih_ref(void *null, void *i)
     843             : {
     844           0 :         struct ifih *ifih = i;
     845             : 
     846           0 :         refcnt_take(&ifih->ifih_srpcnt);
     847           0 : }
     848             : 
     849             : void
     850           0 : if_ih_unref(void *null, void *i)
     851             : {
     852           0 :         struct ifih *ifih = i;
     853             : 
     854           0 :         refcnt_rele_wake(&ifih->ifih_srpcnt);
     855           0 : }
     856             : 
     857             : void
     858           0 : if_ih_remove(struct ifnet *ifp, int (*input)(struct ifnet *, struct mbuf *,
     859             :     void *), void *cookie)
     860             : {
     861             :         struct ifih *ifih;
     862             : 
     863             :         /* the kernel lock guarantees serialised modifications to if_inputs */
     864           0 :         KERNEL_ASSERT_LOCKED();
     865             : 
     866           0 :         SRPL_FOREACH_LOCKED(ifih, &ifp->if_inputs, ifih_next) {
     867           0 :                 if (ifih->ifih_input == input && ifih->ifih_cookie == cookie)
     868             :                         break;
     869             :         }
     870             : 
     871           0 :         KASSERT(ifih != NULL);
     872             : 
     873           0 :         if (--ifih->ifih_refcnt == 0) {
     874           0 :                 SRPL_REMOVE_LOCKED(&ifih_rc, &ifp->if_inputs, ifih,
     875             :                     ifih, ifih_next);
     876             : 
     877           0 :                 refcnt_finalize(&ifih->ifih_srpcnt, "ifihrm");
     878           0 :                 free(ifih, M_DEVBUF, sizeof(*ifih));
     879           0 :         }
     880           0 : }
     881             : 
     882             : void
     883           0 : if_input_process(struct ifnet *ifp, struct mbuf_list *ml)
     884             : {
     885             :         struct mbuf *m;
     886             :         struct ifih *ifih;
     887           0 :         struct srp_ref sr;
     888             :         int s;
     889             : 
     890           0 :         if (ml_empty(ml))
     891           0 :                 return;
     892             : 
     893           0 :         if (!ISSET(ifp->if_xflags, IFXF_CLONED))
     894           0 :                 enqueue_randomness(ml_len(ml));
     895             : 
     896             :         /*
     897             :          * We grab the NET_LOCK() before processing any packet to
     898             :          * ensure there's no contention on the routing table lock.
     899             :          *
     900             :          * Without it we could race with a userland thread to insert
     901             :          * a L2 entry in ip{6,}_output().  Such race would result in
     902             :          * one of the threads sleeping *inside* the IP output path.
     903             :          *
     904             :          * Since we have a NET_LOCK() we also use it to serialize access
     905             :          * to PF globals, pipex globals, unicast and multicast addresses
     906             :          * lists.
     907             :          */
     908           0 :         NET_RLOCK();
     909           0 :         s = splnet();
     910           0 :         while ((m = ml_dequeue(ml)) != NULL) {
     911             :                 /*
     912             :                  * Pass this mbuf to all input handlers of its
     913             :                  * interface until it is consumed.
     914             :                  */
     915           0 :                 SRPL_FOREACH(ifih, &sr, &ifp->if_inputs, ifih_next) {
     916           0 :                         if ((*ifih->ifih_input)(ifp, m, ifih->ifih_cookie))
     917             :                                 break;
     918             :                 }
     919           0 :                 SRPL_LEAVE(&sr);
     920             : 
     921           0 :                 if (ifih == NULL)
     922           0 :                         m_freem(m);
     923             :         }
     924           0 :         splx(s);
     925           0 :         NET_RUNLOCK();
     926           0 : }
     927             : 
     928             : void
     929           0 : if_netisr(void *unused)
     930             : {
     931             :         int n, t = 0;
     932             : 
     933           0 :         NET_LOCK();
     934             : 
     935           0 :         while ((n = netisr) != 0) {
     936             :                 /* Like sched_pause() but with a rwlock dance. */
     937           0 :                 if (curcpu()->ci_schedstate.spc_schedflags & SPCF_SHOULDYIELD) {
     938           0 :                         NET_UNLOCK();
     939           0 :                         yield();
     940           0 :                         NET_LOCK();
     941           0 :                 }
     942             : 
     943           0 :                 atomic_clearbits_int(&netisr, n);
     944             : 
     945             : #if NETHER > 0
     946           0 :                 if (n & (1 << NETISR_ARP)) {
     947           0 :                         KERNEL_LOCK();
     948           0 :                         arpintr();
     949           0 :                         KERNEL_UNLOCK();
     950           0 :                 }
     951             : #endif
     952           0 :                 if (n & (1 << NETISR_IP))
     953           0 :                         ipintr();
     954             : #ifdef INET6
     955           0 :                 if (n & (1 << NETISR_IPV6))
     956           0 :                         ip6intr();
     957             : #endif
     958             : #if NPPP > 0
     959           0 :                 if (n & (1 << NETISR_PPP)) {
     960           0 :                         KERNEL_LOCK();
     961           0 :                         pppintr();
     962           0 :                         KERNEL_UNLOCK();
     963           0 :                 }
     964             : #endif
     965             : #if NBRIDGE > 0
     966           0 :                 if (n & (1 << NETISR_BRIDGE)) {
     967           0 :                         KERNEL_LOCK();
     968           0 :                         bridgeintr();
     969           0 :                         KERNEL_UNLOCK();
     970           0 :                 }
     971             : #endif
     972             : #if NSWITCH > 0
     973           0 :                 if (n & (1 << NETISR_SWITCH)) {
     974           0 :                         KERNEL_LOCK();
     975           0 :                         switchintr();
     976           0 :                         KERNEL_UNLOCK();
     977           0 :                 }
     978             : #endif
     979             : #if NPPPOE > 0
     980           0 :                 if (n & (1 << NETISR_PPPOE)) {
     981           0 :                         KERNEL_LOCK();
     982           0 :                         pppoeintr();
     983           0 :                         KERNEL_UNLOCK();
     984           0 :                 }
     985             : #endif
     986             : #ifdef PIPEX
     987           0 :                 if (n & (1 << NETISR_PIPEX)) {
     988           0 :                         KERNEL_LOCK();
     989           0 :                         pipexintr();
     990           0 :                         KERNEL_UNLOCK();
     991           0 :                 }
     992             : #endif
     993           0 :                 t |= n;
     994             :         }
     995             : 
     996             : #if NPFSYNC > 0
     997           0 :         if (t & (1 << NETISR_PFSYNC)) {
     998           0 :                 KERNEL_LOCK();
     999           0 :                 pfsyncintr();
    1000           0 :                 KERNEL_UNLOCK();
    1001           0 :         }
    1002             : #endif
    1003             : 
    1004           0 :         NET_UNLOCK();
    1005           0 : }
    1006             : 
    1007             : void
    1008           0 : if_deactivate(struct ifnet *ifp)
    1009             : {
    1010           0 :         NET_LOCK();
    1011             :         /*
    1012             :          * Call detach hooks from head to tail.  To make sure detach
    1013             :          * hooks are executed in the reverse order they were added, all
    1014             :          * the hooks have to be added to the head!
    1015             :          */
    1016           0 :         dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
    1017             : 
    1018           0 :         NET_UNLOCK();
    1019           0 : }
    1020             : 
    1021             : /*
    1022             :  * Detach an interface from everything in the kernel.  Also deallocate
    1023             :  * private resources.
    1024             :  */
    1025             : void
    1026           0 : if_detach(struct ifnet *ifp)
    1027             : {
    1028             :         struct ifaddr *ifa;
    1029             :         struct ifg_list *ifg;
    1030             :         struct domain *dp;
    1031             :         int i, s;
    1032             : 
    1033             :         /* Undo pseudo-driver changes. */
    1034           0 :         if_deactivate(ifp);
    1035             : 
    1036           0 :         ifq_clr_oactive(&ifp->if_snd);
    1037             : 
    1038             :         /* Other CPUs must not have a reference before we start destroying. */
    1039           0 :         if_idxmap_remove(ifp);
    1040             : 
    1041             : #if NBPFILTER > 0
    1042           0 :         bpfdetach(ifp);
    1043             : #endif
    1044             : 
    1045           0 :         NET_LOCK();
    1046           0 :         s = splnet();
    1047           0 :         ifp->if_qstart = if_detached_qstart;
    1048           0 :         ifp->if_ioctl = if_detached_ioctl;
    1049           0 :         ifp->if_watchdog = NULL;
    1050             : 
    1051             :         /* Remove the watchdog timeout & task */
    1052           0 :         timeout_del(&ifp->if_slowtimo);
    1053           0 :         task_del(net_tq(ifp->if_index), &ifp->if_watchdogtask);
    1054             : 
    1055             :         /* Remove the link state task */
    1056           0 :         task_del(net_tq(ifp->if_index), &ifp->if_linkstatetask);
    1057             : 
    1058           0 :         rti_delete(ifp);
    1059             : #if NETHER > 0 && defined(NFSCLIENT)
    1060           0 :         if (ifp->if_index == revarp_ifidx)
    1061           0 :                 revarp_ifidx = 0;
    1062             : #endif
    1063             : #ifdef MROUTING
    1064           0 :         vif_delete(ifp);
    1065             : #endif
    1066           0 :         in_ifdetach(ifp);
    1067             : #ifdef INET6
    1068           0 :         in6_ifdetach(ifp);
    1069             : #endif
    1070             : #if NPF > 0
    1071           0 :         pfi_detach_ifnet(ifp);
    1072             : #endif
    1073             : 
    1074             :         /* Remove the interface from the list of all interfaces.  */
    1075           0 :         TAILQ_REMOVE(&ifnet, ifp, if_list);
    1076             : 
    1077           0 :         while ((ifg = TAILQ_FIRST(&ifp->if_groups)) != NULL)
    1078           0 :                 if_delgroup(ifp, ifg->ifgl_group->ifg_group);
    1079             : 
    1080           0 :         if_free_sadl(ifp);
    1081             : 
    1082             :         /* We should not have any address left at this point. */
    1083           0 :         if (!TAILQ_EMPTY(&ifp->if_addrlist)) {
    1084             : #ifdef DIAGNOSTIC
    1085           0 :                 printf("%s: address list non empty\n", ifp->if_xname);
    1086             : #endif
    1087           0 :                 while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
    1088           0 :                         ifa_del(ifp, ifa);
    1089           0 :                         ifa->ifa_ifp = NULL;
    1090           0 :                         ifafree(ifa);
    1091             :                 }
    1092             :         }
    1093             : 
    1094           0 :         free(ifp->if_addrhooks, M_TEMP, 0);
    1095           0 :         free(ifp->if_linkstatehooks, M_TEMP, 0);
    1096           0 :         free(ifp->if_detachhooks, M_TEMP, 0);
    1097             : 
    1098           0 :         for (i = 0; (dp = domains[i]) != NULL; i++) {
    1099           0 :                 if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
    1100           0 :                         (*dp->dom_ifdetach)(ifp,
    1101             :                             ifp->if_afdata[dp->dom_family]);
    1102             :         }
    1103             : 
    1104             :         /* Announce that the interface is gone. */
    1105           0 :         rtm_ifannounce(ifp, IFAN_DEPARTURE);
    1106           0 :         splx(s);
    1107           0 :         NET_UNLOCK();
    1108             : 
    1109           0 :         for (i = 0; i < ifp->if_nifqs; i++)
    1110           0 :                 ifq_destroy(ifp->if_ifqs[i]);
    1111           0 :         if (ifp->if_ifqs != ifp->if_snd.ifq_ifqs) {
    1112           0 :                 for (i = 1; i < ifp->if_nifqs; i++) {
    1113           0 :                         free(ifp->if_ifqs[i], M_DEVBUF,
    1114             :                             sizeof(struct ifqueue));
    1115             :                 }
    1116           0 :                 free(ifp->if_ifqs, M_DEVBUF,
    1117           0 :                     sizeof(struct ifqueue *) * ifp->if_nifqs);
    1118           0 :         }
    1119             : 
    1120           0 :         for (i = 0; i < ifp->if_niqs; i++)
    1121           0 :                 ifiq_destroy(ifp->if_iqs[i]);
    1122           0 :         if (ifp->if_iqs != ifp->if_rcv.ifiq_ifiqs) {
    1123           0 :                 for (i = 1; i < ifp->if_niqs; i++) {
    1124           0 :                         free(ifp->if_iqs[i], M_DEVBUF,
    1125             :                             sizeof(struct ifiqueue));
    1126             :                 }
    1127           0 :                 free(ifp->if_iqs, M_DEVBUF,
    1128           0 :                     sizeof(struct ifiqueue *) * ifp->if_niqs);
    1129           0 :         }
    1130           0 : }
    1131             : 
    1132             : /*
    1133             :  * Returns true if ``ifp0'' is connected to the interface with index ``ifidx''.
    1134             :  */
    1135             : int
    1136           0 : if_isconnected(const struct ifnet *ifp0, unsigned int ifidx)
    1137             : {
    1138             :         struct ifnet *ifp;
    1139             :         int connected = 0;
    1140             : 
    1141           0 :         ifp = if_get(ifidx);
    1142           0 :         if (ifp == NULL)
    1143           0 :                 return (0);
    1144             : 
    1145           0 :         if (ifp0->if_index == ifp->if_index)
    1146           0 :                 connected = 1;
    1147             : 
    1148             : #if NBRIDGE > 0
    1149           0 :         if (SAME_BRIDGE(ifp0->if_bridgeport, ifp->if_bridgeport))
    1150           0 :                 connected = 1;
    1151             : #endif
    1152             : #if NCARP > 0
    1153           0 :         if ((ifp0->if_type == IFT_CARP && ifp0->if_carpdev == ifp) ||
    1154           0 :             (ifp->if_type == IFT_CARP && ifp->if_carpdev == ifp0))
    1155           0 :                 connected = 1;
    1156             : #endif
    1157             : 
    1158           0 :         if_put(ifp);
    1159           0 :         return (connected);
    1160           0 : }
    1161             : 
    1162             : /*
    1163             :  * Create a clone network interface.
    1164             :  */
    1165             : int
    1166           0 : if_clone_create(const char *name, int rdomain)
    1167             : {
    1168             :         struct if_clone *ifc;
    1169             :         struct ifnet *ifp;
    1170           0 :         int unit, ret;
    1171             : 
    1172           0 :         NET_ASSERT_LOCKED();
    1173             : 
    1174           0 :         ifc = if_clone_lookup(name, &unit);
    1175           0 :         if (ifc == NULL)
    1176           0 :                 return (EINVAL);
    1177             : 
    1178           0 :         if (ifunit(name) != NULL)
    1179           0 :                 return (EEXIST);
    1180             : 
    1181             :         /* XXXSMP breaks atomicity */
    1182           0 :         NET_UNLOCK();
    1183           0 :         ret = (*ifc->ifc_create)(ifc, unit);
    1184           0 :         NET_LOCK();
    1185             : 
    1186           0 :         if (ret != 0 || (ifp = ifunit(name)) == NULL)
    1187           0 :                 return (ret);
    1188             : 
    1189           0 :         if_addgroup(ifp, ifc->ifc_name);
    1190           0 :         if (rdomain != 0)
    1191           0 :                 if_setrdomain(ifp, rdomain);
    1192             : 
    1193           0 :         return (ret);
    1194           0 : }
    1195             : 
    1196             : /*
    1197             :  * Destroy a clone network interface.
    1198             :  */
    1199             : int
    1200           0 : if_clone_destroy(const char *name)
    1201             : {
    1202             :         struct if_clone *ifc;
    1203             :         struct ifnet *ifp;
    1204             :         int ret;
    1205             : 
    1206           0 :         NET_ASSERT_LOCKED();
    1207             : 
    1208           0 :         ifc = if_clone_lookup(name, NULL);
    1209           0 :         if (ifc == NULL)
    1210           0 :                 return (EINVAL);
    1211             : 
    1212           0 :         ifp = ifunit(name);
    1213           0 :         if (ifp == NULL)
    1214           0 :                 return (ENXIO);
    1215             : 
    1216           0 :         if (ifc->ifc_destroy == NULL)
    1217           0 :                 return (EOPNOTSUPP);
    1218             : 
    1219           0 :         if (ifp->if_flags & IFF_UP) {
    1220             :                 int s;
    1221           0 :                 s = splnet();
    1222           0 :                 if_down(ifp);
    1223           0 :                 splx(s);
    1224           0 :         }
    1225             : 
    1226             :         /* XXXSMP breaks atomicity */
    1227           0 :         NET_UNLOCK();
    1228           0 :         ret = (*ifc->ifc_destroy)(ifp);
    1229           0 :         NET_LOCK();
    1230             : 
    1231           0 :         return (ret);
    1232           0 : }
    1233             : 
    1234             : /*
    1235             :  * Look up a network interface cloner.
    1236             :  */
    1237             : struct if_clone *
    1238           0 : if_clone_lookup(const char *name, int *unitp)
    1239             : {
    1240             :         struct if_clone *ifc;
    1241             :         const char *cp;
    1242             :         int unit;
    1243             : 
    1244             :         /* separate interface name from unit */
    1245           0 :         for (cp = name;
    1246           0 :             cp - name < IFNAMSIZ && *cp && (*cp < '0' || *cp > '9');
    1247           0 :             cp++)
    1248             :                 continue;
    1249             : 
    1250           0 :         if (cp == name || cp - name == IFNAMSIZ || !*cp)
    1251           0 :                 return (NULL);  /* No name or unit number */
    1252             : 
    1253           0 :         if (cp - name < IFNAMSIZ-1 && *cp == '0' && cp[1] != '\0')
    1254           0 :                 return (NULL);  /* unit number 0 padded */
    1255             : 
    1256           0 :         LIST_FOREACH(ifc, &if_cloners, ifc_list) {
    1257           0 :                 if (strlen(ifc->ifc_name) == cp - name &&
    1258           0 :                     !strncmp(name, ifc->ifc_name, cp - name))
    1259             :                         break;
    1260             :         }
    1261             : 
    1262           0 :         if (ifc == NULL)
    1263           0 :                 return (NULL);
    1264             : 
    1265             :         unit = 0;
    1266           0 :         while (cp - name < IFNAMSIZ && *cp) {
    1267           0 :                 if (*cp < '0' || *cp > '9' ||
    1268           0 :                     unit > (INT_MAX - (*cp - '0')) / 10) {
    1269             :                         /* Bogus unit number. */
    1270           0 :                         return (NULL);
    1271             :                 }
    1272           0 :                 unit = (unit * 10) + (*cp++ - '0');
    1273             :         }
    1274             : 
    1275           0 :         if (unitp != NULL)
    1276           0 :                 *unitp = unit;
    1277           0 :         return (ifc);
    1278           0 : }
    1279             : 
    1280             : /*
    1281             :  * Register a network interface cloner.
    1282             :  */
    1283             : void
    1284           0 : if_clone_attach(struct if_clone *ifc)
    1285             : {
    1286             :         /*
    1287             :          * we are called at kernel boot by main(), when pseudo devices are
    1288             :          * being attached. The main() is the only guy which may alter the
    1289             :          * if_cloners. While system is running and main() is done with
    1290             :          * initialization, the if_cloners becomes immutable. 
    1291             :          */
    1292           0 :         KASSERT(pdevinit_done == 0);
    1293           0 :         LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
    1294           0 :         if_cloners_count++;
    1295           0 : }
    1296             : 
    1297             : /*
    1298             :  * Provide list of interface cloners to userspace.
    1299             :  */
    1300             : int
    1301           0 : if_clone_list(struct if_clonereq *ifcr)
    1302             : {
    1303           0 :         char outbuf[IFNAMSIZ], *dst;
    1304             :         struct if_clone *ifc;
    1305             :         int count, error = 0;
    1306             : 
    1307           0 :         if ((dst = ifcr->ifcr_buffer) == NULL) {
    1308             :                 /* Just asking how many there are. */
    1309           0 :                 ifcr->ifcr_total = if_cloners_count;
    1310           0 :                 return (0);
    1311             :         }
    1312             : 
    1313           0 :         if (ifcr->ifcr_count < 0)
    1314           0 :                 return (EINVAL);
    1315             : 
    1316           0 :         ifcr->ifcr_total = if_cloners_count;
    1317           0 :         count = MIN(if_cloners_count, ifcr->ifcr_count);
    1318             : 
    1319           0 :         LIST_FOREACH(ifc, &if_cloners, ifc_list) {
    1320           0 :                 if (count == 0)
    1321             :                         break;
    1322           0 :                 bzero(outbuf, sizeof outbuf);
    1323           0 :                 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
    1324           0 :                 error = copyout(outbuf, dst, IFNAMSIZ);
    1325           0 :                 if (error)
    1326             :                         break;
    1327           0 :                 count--;
    1328           0 :                 dst += IFNAMSIZ;
    1329             :         }
    1330             : 
    1331           0 :         return (error);
    1332           0 : }
    1333             : 
    1334             : /*
    1335             :  * set queue congestion marker
    1336             :  */
    1337             : void
    1338           0 : if_congestion(void)
    1339             : {
    1340             :         extern int ticks;
    1341             : 
    1342           0 :         ifq_congestion = ticks;
    1343           0 : }
    1344             : 
    1345             : int
    1346           0 : if_congested(void)
    1347             : {
    1348             :         extern int ticks;
    1349             :         int diff;
    1350             : 
    1351           0 :         diff = ticks - ifq_congestion;
    1352           0 :         if (diff < 0) {
    1353           0 :                 ifq_congestion = ticks - hz;
    1354           0 :                 return (0);
    1355             :         }
    1356             : 
    1357           0 :         return (diff <= (hz / 100));
    1358           0 : }
    1359             : 
    1360             : #define equal(a1, a2)   \
    1361             :         (bcmp((caddr_t)(a1), (caddr_t)(a2),     \
    1362             :         (a1)->sa_len) == 0)
    1363             : 
    1364             : /*
    1365             :  * Locate an interface based on a complete address.
    1366             :  */
    1367             : struct ifaddr *
    1368           0 : ifa_ifwithaddr(struct sockaddr *addr, u_int rtableid)
    1369             : {
    1370             :         struct ifnet *ifp;
    1371             :         struct ifaddr *ifa;
    1372             :         u_int rdomain;
    1373             : 
    1374           0 :         rdomain = rtable_l2(rtableid);
    1375           0 :         KERNEL_LOCK();
    1376           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    1377           0 :                 if (ifp->if_rdomain != rdomain)
    1378             :                         continue;
    1379             : 
    1380           0 :                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    1381           0 :                         if (ifa->ifa_addr->sa_family != addr->sa_family)
    1382             :                                 continue;
    1383             : 
    1384           0 :                         if (equal(addr, ifa->ifa_addr)) {
    1385           0 :                                 KERNEL_UNLOCK();
    1386           0 :                                 return (ifa);
    1387             :                         }
    1388             :                 }
    1389             :         }
    1390           0 :         KERNEL_UNLOCK();
    1391           0 :         return (NULL);
    1392           0 : }
    1393             : 
    1394             : /*
    1395             :  * Locate the point to point interface with a given destination address.
    1396             :  */
    1397             : struct ifaddr *
    1398           0 : ifa_ifwithdstaddr(struct sockaddr *addr, u_int rdomain)
    1399             : {
    1400             :         struct ifnet *ifp;
    1401             :         struct ifaddr *ifa;
    1402             : 
    1403           0 :         rdomain = rtable_l2(rdomain);
    1404           0 :         KERNEL_LOCK();
    1405           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    1406           0 :                 if (ifp->if_rdomain != rdomain)
    1407             :                         continue;
    1408           0 :                 if (ifp->if_flags & IFF_POINTOPOINT) {
    1409           0 :                         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    1410           0 :                                 if (ifa->ifa_addr->sa_family !=
    1411           0 :                                     addr->sa_family || ifa->ifa_dstaddr == NULL)
    1412             :                                         continue;
    1413           0 :                                 if (equal(addr, ifa->ifa_dstaddr)) {
    1414           0 :                                         KERNEL_UNLOCK();
    1415           0 :                                         return (ifa);
    1416             :                                 }
    1417             :                         }
    1418             :                 }
    1419             :         }
    1420           0 :         KERNEL_UNLOCK();
    1421           0 :         return (NULL);
    1422           0 : }
    1423             : 
    1424             : /*
    1425             :  * Find an interface address specific to an interface best matching
    1426             :  * a given address.
    1427             :  */
    1428             : struct ifaddr *
    1429           0 : ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
    1430             : {
    1431             :         struct ifaddr *ifa;
    1432             :         char *cp, *cp2, *cp3;
    1433             :         char *cplim;
    1434             :         struct ifaddr *ifa_maybe = NULL;
    1435           0 :         u_int af = addr->sa_family;
    1436             : 
    1437           0 :         if (af >= AF_MAX)
    1438           0 :                 return (NULL);
    1439           0 :         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    1440           0 :                 if (ifa->ifa_addr->sa_family != af)
    1441             :                         continue;
    1442           0 :                 if (ifa_maybe == NULL)
    1443           0 :                         ifa_maybe = ifa;
    1444           0 :                 if (ifa->ifa_netmask == 0 || ifp->if_flags & IFF_POINTOPOINT) {
    1445           0 :                         if (equal(addr, ifa->ifa_addr) ||
    1446           0 :                             (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
    1447           0 :                                 return (ifa);
    1448             :                         continue;
    1449             :                 }
    1450           0 :                 cp = addr->sa_data;
    1451           0 :                 cp2 = ifa->ifa_addr->sa_data;
    1452           0 :                 cp3 = ifa->ifa_netmask->sa_data;
    1453           0 :                 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
    1454           0 :                 for (; cp3 < cplim; cp3++)
    1455           0 :                         if ((*cp++ ^ *cp2++) & *cp3)
    1456             :                                 break;
    1457           0 :                 if (cp3 == cplim)
    1458           0 :                         return (ifa);
    1459             :         }
    1460           0 :         return (ifa_maybe);
    1461           0 : }
    1462             : 
    1463             : void
    1464           0 : if_rtrequest_dummy(struct ifnet *ifp, int req, struct rtentry *rt)
    1465             : {
    1466           0 : }
    1467             : 
    1468             : /*
    1469             :  * Default action when installing a local route on a point-to-point
    1470             :  * interface.
    1471             :  */
    1472             : void
    1473           0 : p2p_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
    1474             : {
    1475             :         struct ifnet *lo0ifp;
    1476             :         struct ifaddr *ifa, *lo0ifa;
    1477             : 
    1478           0 :         switch (req) {
    1479             :         case RTM_ADD:
    1480           0 :                 if (!ISSET(rt->rt_flags, RTF_LOCAL))
    1481             :                         break;
    1482             : 
    1483           0 :                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    1484           0 :                         if (memcmp(rt_key(rt), ifa->ifa_addr,
    1485           0 :                             rt_key(rt)->sa_len) == 0)
    1486             :                                 break;
    1487             :                 }
    1488             : 
    1489           0 :                 if (ifa == NULL)
    1490             :                         break;
    1491             : 
    1492           0 :                 KASSERT(ifa == rt->rt_ifa);
    1493             : 
    1494           0 :                 lo0ifp = if_get(rtable_loindex(ifp->if_rdomain));
    1495           0 :                 KASSERT(lo0ifp != NULL);
    1496           0 :                 TAILQ_FOREACH(lo0ifa, &lo0ifp->if_addrlist, ifa_list) {
    1497           0 :                         if (lo0ifa->ifa_addr->sa_family ==
    1498           0 :                             ifa->ifa_addr->sa_family)
    1499             :                                 break;
    1500             :                 }
    1501           0 :                 if_put(lo0ifp);
    1502             : 
    1503           0 :                 if (lo0ifa == NULL)
    1504             :                         break;
    1505             : 
    1506           0 :                 rt->rt_flags &= ~RTF_LLINFO;
    1507           0 :                 break;
    1508             :         case RTM_DELETE:
    1509             :         case RTM_RESOLVE:
    1510             :         default:
    1511             :                 break;
    1512             :         }
    1513           0 : }
    1514             : 
    1515             : 
    1516             : /*
    1517             :  * Bring down all interfaces
    1518             :  */
    1519             : void
    1520           0 : if_downall(void)
    1521             : {
    1522           0 :         struct ifreq ifrq;      /* XXX only partly built */
    1523             :         struct ifnet *ifp;
    1524             : 
    1525           0 :         NET_LOCK();
    1526           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    1527           0 :                 if ((ifp->if_flags & IFF_UP) == 0)
    1528             :                         continue;
    1529           0 :                 if_down(ifp);
    1530           0 :                 ifrq.ifr_flags = ifp->if_flags;
    1531           0 :                 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
    1532           0 :         }
    1533           0 :         NET_UNLOCK();
    1534           0 : }
    1535             : 
    1536             : /*
    1537             :  * Mark an interface down and notify protocols of
    1538             :  * the transition.
    1539             :  */
    1540             : void
    1541           0 : if_down(struct ifnet *ifp)
    1542             : {
    1543           0 :         NET_ASSERT_LOCKED();
    1544             : 
    1545           0 :         ifp->if_flags &= ~IFF_UP;
    1546           0 :         getmicrotime(&ifp->if_lastchange);
    1547           0 :         IFQ_PURGE(&ifp->if_snd);
    1548             : 
    1549           0 :         if_linkstate(ifp);
    1550           0 : }
    1551             : 
    1552             : /*
    1553             :  * Mark an interface up and notify protocols of
    1554             :  * the transition.
    1555             :  */
    1556             : void
    1557           0 : if_up(struct ifnet *ifp)
    1558             : {
    1559           0 :         NET_ASSERT_LOCKED();
    1560             : 
    1561           0 :         ifp->if_flags |= IFF_UP;
    1562           0 :         getmicrotime(&ifp->if_lastchange);
    1563             : 
    1564             : #ifdef INET6
    1565             :         /* Userland expects the kernel to set ::1 on default lo(4). */
    1566           0 :         if (ifp->if_index == rtable_loindex(ifp->if_rdomain))
    1567           0 :                 in6_ifattach(ifp);
    1568             : #endif
    1569             : 
    1570           0 :         if_linkstate(ifp);
    1571           0 : }
    1572             : 
    1573             : /*
    1574             :  * Notify userland, the routing table and hooks owner of
    1575             :  * a link-state transition.
    1576             :  */
    1577             : void
    1578           0 : if_linkstate_task(void *xifidx)
    1579             : {
    1580           0 :         unsigned int ifidx = (unsigned long)xifidx;
    1581             :         struct ifnet *ifp;
    1582             : 
    1583           0 :         KERNEL_LOCK();
    1584           0 :         NET_LOCK();
    1585             : 
    1586           0 :         ifp = if_get(ifidx);
    1587           0 :         if (ifp != NULL)
    1588           0 :                 if_linkstate(ifp);
    1589           0 :         if_put(ifp);
    1590             : 
    1591           0 :         NET_UNLOCK();
    1592           0 :         KERNEL_UNLOCK();
    1593           0 : }
    1594             : 
    1595             : void
    1596           0 : if_linkstate(struct ifnet *ifp)
    1597             : {
    1598           0 :         NET_ASSERT_LOCKED();
    1599             : 
    1600           0 :         rtm_ifchg(ifp);
    1601           0 :         rt_if_track(ifp);
    1602           0 :         dohooks(ifp->if_linkstatehooks, 0);
    1603           0 : }
    1604             : 
    1605             : /*
    1606             :  * Schedule a link state change task.
    1607             :  */
    1608             : void
    1609           0 : if_link_state_change(struct ifnet *ifp)
    1610             : {
    1611           0 :         task_add(net_tq(ifp->if_index), &ifp->if_linkstatetask);
    1612           0 : }
    1613             : 
    1614             : /*
    1615             :  * Handle interface watchdog timer routine.  Called
    1616             :  * from softclock, we decrement timer (if set) and
    1617             :  * call the appropriate interface routine on expiration.
    1618             :  */
    1619             : void
    1620           0 : if_slowtimo(void *arg)
    1621             : {
    1622           0 :         struct ifnet *ifp = arg;
    1623           0 :         int s = splnet();
    1624             : 
    1625           0 :         if (ifp->if_watchdog) {
    1626           0 :                 if (ifp->if_timer > 0 && --ifp->if_timer == 0)
    1627           0 :                         task_add(net_tq(ifp->if_index), &ifp->if_watchdogtask);
    1628           0 :                 timeout_add(&ifp->if_slowtimo, hz / IFNET_SLOWHZ);
    1629           0 :         }
    1630           0 :         splx(s);
    1631           0 : }
    1632             : 
    1633             : void
    1634           0 : if_watchdog_task(void *xifidx)
    1635             : {
    1636           0 :         unsigned int ifidx = (unsigned long)xifidx;
    1637             :         struct ifnet *ifp;
    1638             :         int s;
    1639             : 
    1640           0 :         ifp = if_get(ifidx);
    1641           0 :         if (ifp == NULL)
    1642           0 :                 return;
    1643             : 
    1644           0 :         KERNEL_LOCK();
    1645           0 :         s = splnet();
    1646           0 :         if (ifp->if_watchdog)
    1647           0 :                 (*ifp->if_watchdog)(ifp);
    1648           0 :         splx(s);
    1649           0 :         KERNEL_UNLOCK();
    1650             : 
    1651           0 :         if_put(ifp);
    1652           0 : }
    1653             : 
    1654             : /*
    1655             :  * Map interface name to interface structure pointer.
    1656             :  */
    1657             : struct ifnet *
    1658           0 : ifunit(const char *name)
    1659             : {
    1660             :         struct ifnet *ifp;
    1661             : 
    1662           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    1663           0 :                 if (strcmp(ifp->if_xname, name) == 0)
    1664           0 :                         return (ifp);
    1665             :         }
    1666           0 :         return (NULL);
    1667           0 : }
    1668             : 
    1669             : /*
    1670             :  * Map interface index to interface structure pointer.
    1671             :  */
    1672             : struct ifnet *
    1673           0 : if_get(unsigned int index)
    1674             : {
    1675           0 :         struct srp_ref sr;
    1676             :         struct if_map *if_map;
    1677             :         struct srp *map;
    1678             :         struct ifnet *ifp = NULL;
    1679             : 
    1680           0 :         if_map = srp_enter(&sr, &if_idxmap.map);
    1681           0 :         if (index < if_map->limit) {
    1682           0 :                 map = (struct srp *)(if_map + 1);
    1683             : 
    1684           0 :                 ifp = srp_follow(&sr, &map[index]);
    1685           0 :                 if (ifp != NULL) {
    1686           0 :                         KASSERT(ifp->if_index == index);
    1687           0 :                         if_ref(ifp);
    1688           0 :                 }
    1689             :         }
    1690           0 :         srp_leave(&sr);
    1691             : 
    1692           0 :         return (ifp);
    1693           0 : }
    1694             : 
    1695             : struct ifnet *
    1696           0 : if_ref(struct ifnet *ifp)
    1697             : {
    1698           0 :         refcnt_take(&ifp->if_refcnt);
    1699             : 
    1700           0 :         return (ifp);
    1701             : }
    1702             : 
    1703             : void
    1704           0 : if_put(struct ifnet *ifp)
    1705             : {
    1706           0 :         if (ifp == NULL)
    1707             :                 return;
    1708             : 
    1709           0 :         refcnt_rele_wake(&ifp->if_refcnt);
    1710           0 : }
    1711             : 
    1712             : int
    1713           0 : if_setlladdr(struct ifnet *ifp, const uint8_t *lladdr)
    1714             : {
    1715           0 :         if (ifp->if_sadl == NULL)
    1716           0 :                 return (EINVAL);
    1717             : 
    1718           0 :         memcpy(((struct arpcom *)ifp)->ac_enaddr, lladdr, ETHER_ADDR_LEN);
    1719           0 :         memcpy(LLADDR(ifp->if_sadl), lladdr, ETHER_ADDR_LEN);
    1720             : 
    1721           0 :         return (0);
    1722           0 : }
    1723             : 
    1724             : int
    1725           0 : if_createrdomain(int rdomain, struct ifnet *ifp)
    1726             : {
    1727             :         int error;
    1728             :         struct ifnet *loifp;
    1729           0 :         char loifname[IFNAMSIZ];
    1730             :         unsigned int unit = rdomain;
    1731             : 
    1732           0 :         if (!rtable_exists(rdomain) && (error = rtable_add(rdomain)) != 0)
    1733           0 :                 return (error);
    1734           0 :         if (!rtable_empty(rdomain))
    1735           0 :                 return (EEXIST);
    1736             : 
    1737             :         /* Create rdomain including its loopback if with unit == rdomain */
    1738           0 :         snprintf(loifname, sizeof(loifname), "lo%u", unit);
    1739           0 :         error = if_clone_create(loifname, 0);
    1740           0 :         if ((loifp = ifunit(loifname)) == NULL)
    1741           0 :                 return (ENXIO);
    1742           0 :         if (error && (ifp != loifp || error != EEXIST))
    1743           0 :                 return (error);
    1744             : 
    1745           0 :         rtable_l2set(rdomain, rdomain, loifp->if_index);
    1746           0 :         loifp->if_rdomain = rdomain;
    1747             : 
    1748           0 :         return (0);
    1749           0 : }
    1750             : 
    1751             : int
    1752           0 : if_setrdomain(struct ifnet *ifp, int rdomain)
    1753             : {
    1754           0 :         struct ifreq ifr;
    1755             :         int error, up = 0, s;
    1756             : 
    1757           0 :         if (rdomain < 0 || rdomain > RT_TABLEID_MAX)
    1758           0 :                 return (EINVAL);
    1759             : 
    1760           0 :         if (rdomain != ifp->if_rdomain &&
    1761           0 :             (ifp->if_flags & IFF_LOOPBACK) &&
    1762           0 :             (ifp->if_index == rtable_loindex(ifp->if_rdomain)))
    1763           0 :                 return (EPERM);
    1764             : 
    1765           0 :         if (!rtable_exists(rdomain))
    1766           0 :                 return (ESRCH);
    1767             : 
    1768             :         /* make sure that the routing table is a real rdomain */
    1769           0 :         if (rdomain != rtable_l2(rdomain))
    1770           0 :                 return (EINVAL);
    1771             : 
    1772           0 :         if (rdomain != ifp->if_rdomain) {
    1773           0 :                 s = splnet();
    1774             :                 /*
    1775             :                  * We are tearing down the world.
    1776             :                  * Take down the IF so:
    1777             :                  * 1. everything that cares gets a message
    1778             :                  * 2. the automagic IPv6 bits are recreated
    1779             :                  */
    1780           0 :                 if (ifp->if_flags & IFF_UP) {
    1781             :                         up = 1;
    1782           0 :                         if_down(ifp);
    1783           0 :                 }
    1784           0 :                 rti_delete(ifp);
    1785             : #ifdef MROUTING
    1786           0 :                 vif_delete(ifp);
    1787             : #endif
    1788           0 :                 in_ifdetach(ifp);
    1789             : #ifdef INET6
    1790           0 :                 in6_ifdetach(ifp);
    1791             : #endif
    1792           0 :                 splx(s);
    1793           0 :         }
    1794             : 
    1795             :         /* Let devices like enc(4) or mpe(4) know about the change */
    1796           0 :         ifr.ifr_rdomainid = rdomain;
    1797           0 :         if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFRDOMAIN,
    1798           0 :             (caddr_t)&ifr)) != ENOTTY)
    1799           0 :                 return (error);
    1800             :         error = 0;
    1801             : 
    1802             :         /* Add interface to the specified rdomain */
    1803           0 :         ifp->if_rdomain = rdomain;
    1804             : 
    1805             :         /* If we took down the IF, bring it back */
    1806           0 :         if (up) {
    1807           0 :                 s = splnet();
    1808           0 :                 if_up(ifp);
    1809           0 :                 splx(s);
    1810           0 :         }
    1811             : 
    1812           0 :         return (0);
    1813           0 : }
    1814             : 
    1815             : /*
    1816             :  * Interface ioctls.
    1817             :  */
    1818             : int
    1819           0 : ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
    1820             : {
    1821             :         struct ifnet *ifp;
    1822           0 :         struct ifreq *ifr = (struct ifreq *)data;
    1823           0 :         struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
    1824           0 :         struct if_afreq *ifar = (struct if_afreq *)data;
    1825           0 :         char ifdescrbuf[IFDESCRSIZE];
    1826           0 :         char ifrtlabelbuf[RTLABEL_LEN];
    1827             :         int s, error = 0, oif_xflags;
    1828           0 :         size_t bytesdone;
    1829             :         unsigned short oif_flags;
    1830             : 
    1831           0 :         switch (cmd) {
    1832             :         case SIOCIFCREATE:
    1833           0 :                 if ((error = suser(p)) != 0)
    1834           0 :                         return (error);
    1835           0 :                 NET_LOCK();
    1836           0 :                 error = if_clone_create(ifr->ifr_name, 0);
    1837           0 :                 NET_UNLOCK();
    1838           0 :                 return (error);
    1839             :         case SIOCIFDESTROY:
    1840           0 :                 if ((error = suser(p)) != 0)
    1841           0 :                         return (error);
    1842           0 :                 NET_LOCK();
    1843           0 :                 error = if_clone_destroy(ifr->ifr_name);
    1844           0 :                 NET_UNLOCK();
    1845           0 :                 return (error);
    1846             :         case SIOCSIFGATTR:
    1847           0 :                 if ((error = suser(p)) != 0)
    1848           0 :                         return (error);
    1849           0 :                 NET_LOCK();
    1850           0 :                 error = if_setgroupattribs(data);
    1851           0 :                 NET_UNLOCK();
    1852           0 :                 return (error);
    1853             :         case SIOCGIFCONF:
    1854             :         case SIOCIFGCLONERS:
    1855             :         case SIOCGIFGMEMB:
    1856             :         case SIOCGIFGATTR:
    1857             :         case SIOCGIFGLIST:
    1858             :         case SIOCGIFFLAGS:
    1859             :         case SIOCGIFXFLAGS:
    1860             :         case SIOCGIFMETRIC:
    1861             :         case SIOCGIFMTU:
    1862             :         case SIOCGIFHARDMTU:
    1863             :         case SIOCGIFDATA:
    1864             :         case SIOCGIFDESCR:
    1865             :         case SIOCGIFRTLABEL:
    1866             :         case SIOCGIFPRIORITY:
    1867             :         case SIOCGIFRDOMAIN:
    1868             :         case SIOCGIFGROUP:
    1869             :         case SIOCGIFLLPRIO:
    1870           0 :                 return (ifioctl_get(cmd, data));
    1871             :         }
    1872             : 
    1873           0 :         ifp = ifunit(ifr->ifr_name);
    1874           0 :         if (ifp == NULL)
    1875           0 :                 return (ENXIO);
    1876           0 :         oif_flags = ifp->if_flags;
    1877           0 :         oif_xflags = ifp->if_xflags;
    1878             : 
    1879           0 :         switch (cmd) {
    1880             :         case SIOCIFAFATTACH:
    1881             :         case SIOCIFAFDETACH:
    1882           0 :                 if ((error = suser(p)) != 0)
    1883             :                         break;
    1884           0 :                 NET_LOCK();
    1885           0 :                 switch (ifar->ifar_af) {
    1886             :                 case AF_INET:
    1887             :                         /* attach is a noop for AF_INET */
    1888           0 :                         if (cmd == SIOCIFAFDETACH)
    1889           0 :                                 in_ifdetach(ifp);
    1890             :                         break;
    1891             : #ifdef INET6
    1892             :                 case AF_INET6:
    1893           0 :                         if (cmd == SIOCIFAFATTACH)
    1894           0 :                                 error = in6_ifattach(ifp);
    1895             :                         else
    1896           0 :                                 in6_ifdetach(ifp);
    1897             :                         break;
    1898             : #endif /* INET6 */
    1899             :                 default:
    1900             :                         error = EAFNOSUPPORT;
    1901           0 :                 }
    1902           0 :                 NET_UNLOCK();
    1903           0 :                 break;
    1904             : 
    1905             :         case SIOCSIFFLAGS:
    1906           0 :                 if ((error = suser(p)) != 0)
    1907             :                         break;
    1908             : 
    1909           0 :                 NET_LOCK();
    1910           0 :                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
    1911           0 :                         (ifr->ifr_flags & ~IFF_CANTCHANGE);
    1912             : 
    1913           0 :                 error = (*ifp->if_ioctl)(ifp, cmd, data);
    1914           0 :                 if (error != 0) {
    1915           0 :                         ifp->if_flags = oif_flags;
    1916           0 :                 } else if (ISSET(oif_flags ^ ifp->if_flags, IFF_UP)) {
    1917           0 :                         s = splnet();
    1918           0 :                         if (ISSET(ifp->if_flags, IFF_UP))
    1919           0 :                                 if_up(ifp);
    1920             :                         else
    1921           0 :                                 if_down(ifp);
    1922           0 :                         splx(s);
    1923           0 :                 }
    1924           0 :                 NET_UNLOCK();
    1925           0 :                 break;
    1926             : 
    1927             :         case SIOCSIFXFLAGS:
    1928           0 :                 if ((error = suser(p)) != 0)
    1929             :                         break;
    1930             : 
    1931           0 :                 NET_LOCK();
    1932             : #ifdef INET6
    1933           0 :                 if (ISSET(ifr->ifr_flags, IFXF_AUTOCONF6)) {
    1934           0 :                         error = in6_ifattach(ifp);
    1935           0 :                         if (error != 0) {
    1936           0 :                                 NET_UNLOCK();
    1937           0 :                                 break;
    1938             :                         }
    1939             :                 }
    1940             : 
    1941           0 :                 if (ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) &&
    1942           0 :                     !ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) {
    1943           0 :                         ifp->if_xflags |= IFXF_INET6_NOSOII;
    1944           0 :                         in6_soiiupdate(ifp);
    1945           0 :                 }
    1946             : 
    1947           0 :                 if (!ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) &&
    1948           0 :                     ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) {
    1949           0 :                         ifp->if_xflags &= ~IFXF_INET6_NOSOII;
    1950           0 :                         in6_soiiupdate(ifp);
    1951           0 :                 }
    1952             : 
    1953             : #endif  /* INET6 */
    1954             : 
    1955             : #ifdef MPLS
    1956           0 :                 if (ISSET(ifr->ifr_flags, IFXF_MPLS) &&
    1957           0 :                     !ISSET(ifp->if_xflags, IFXF_MPLS)) {
    1958           0 :                         s = splnet();
    1959           0 :                         ifp->if_xflags |= IFXF_MPLS;
    1960           0 :                         ifp->if_ll_output = ifp->if_output;
    1961           0 :                         ifp->if_output = mpls_output;
    1962           0 :                         splx(s);
    1963           0 :                 }
    1964           0 :                 if (ISSET(ifp->if_xflags, IFXF_MPLS) &&
    1965           0 :                     !ISSET(ifr->ifr_flags, IFXF_MPLS)) {
    1966           0 :                         s = splnet();
    1967           0 :                         ifp->if_xflags &= ~IFXF_MPLS;
    1968           0 :                         ifp->if_output = ifp->if_ll_output;
    1969           0 :                         ifp->if_ll_output = NULL;
    1970           0 :                         splx(s);
    1971           0 :                 }
    1972             : #endif  /* MPLS */
    1973             : 
    1974             : #ifndef SMALL_KERNEL
    1975           0 :                 if (ifp->if_capabilities & IFCAP_WOL) {
    1976           0 :                         if (ISSET(ifr->ifr_flags, IFXF_WOL) &&
    1977           0 :                             !ISSET(ifp->if_xflags, IFXF_WOL)) {
    1978           0 :                                 s = splnet();
    1979           0 :                                 ifp->if_xflags |= IFXF_WOL;
    1980           0 :                                 error = ifp->if_wol(ifp, 1);
    1981           0 :                                 splx(s);
    1982           0 :                         }
    1983           0 :                         if (ISSET(ifp->if_xflags, IFXF_WOL) &&
    1984           0 :                             !ISSET(ifr->ifr_flags, IFXF_WOL)) {
    1985           0 :                                 s = splnet();
    1986           0 :                                 ifp->if_xflags &= ~IFXF_WOL;
    1987           0 :                                 error = ifp->if_wol(ifp, 0);
    1988           0 :                                 splx(s);
    1989           0 :                         }
    1990           0 :                 } else if (ISSET(ifr->ifr_flags, IFXF_WOL)) {
    1991           0 :                         ifr->ifr_flags &= ~IFXF_WOL;
    1992             :                         error = ENOTSUP;
    1993           0 :                 }
    1994             : #endif
    1995             : 
    1996           0 :                 if (error == 0)
    1997           0 :                         ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) |
    1998           0 :                                 (ifr->ifr_flags & ~IFXF_CANTCHANGE);
    1999           0 :                 NET_UNLOCK();
    2000           0 :                 break;
    2001             : 
    2002             :         case SIOCSIFMETRIC:
    2003           0 :                 if ((error = suser(p)) != 0)
    2004             :                         break;
    2005           0 :                 NET_LOCK();
    2006           0 :                 ifp->if_metric = ifr->ifr_metric;
    2007           0 :                 NET_UNLOCK();
    2008           0 :                 break;
    2009             : 
    2010             :         case SIOCSIFMTU:
    2011           0 :                 if ((error = suser(p)) != 0)
    2012             :                         break;
    2013           0 :                 NET_LOCK();
    2014           0 :                 error = (*ifp->if_ioctl)(ifp, cmd, data);
    2015           0 :                 NET_UNLOCK();
    2016           0 :                 if (!error)
    2017           0 :                         rtm_ifchg(ifp);
    2018             :                 break;
    2019             : 
    2020             :         case SIOCSIFDESCR:
    2021           0 :                 if ((error = suser(p)) != 0)
    2022             :                         break;
    2023           0 :                 error = copyinstr(ifr->ifr_data, ifdescrbuf,
    2024             :                     IFDESCRSIZE, &bytesdone);
    2025           0 :                 if (error == 0) {
    2026           0 :                         (void)memset(ifp->if_description, 0, IFDESCRSIZE);
    2027           0 :                         strlcpy(ifp->if_description, ifdescrbuf, IFDESCRSIZE);
    2028           0 :                 }
    2029             :                 break;
    2030             : 
    2031             :         case SIOCSIFRTLABEL:
    2032           0 :                 if ((error = suser(p)) != 0)
    2033             :                         break;
    2034           0 :                 error = copyinstr(ifr->ifr_data, ifrtlabelbuf,
    2035             :                     RTLABEL_LEN, &bytesdone);
    2036           0 :                 if (error == 0) {
    2037           0 :                         rtlabel_unref(ifp->if_rtlabelid);
    2038           0 :                         ifp->if_rtlabelid = rtlabel_name2id(ifrtlabelbuf);
    2039           0 :                 }
    2040             :                 break;
    2041             : 
    2042             :         case SIOCSIFPRIORITY:
    2043           0 :                 if ((error = suser(p)) != 0)
    2044             :                         break;
    2045           0 :                 if (ifr->ifr_metric < 0 || ifr->ifr_metric > 15) {
    2046             :                         error = EINVAL;
    2047           0 :                         break;
    2048             :                 }
    2049           0 :                 ifp->if_priority = ifr->ifr_metric;
    2050           0 :                 break;
    2051             : 
    2052             :         case SIOCSIFRDOMAIN:
    2053           0 :                 if ((error = suser(p)) != 0)
    2054             :                         break;
    2055           0 :                 NET_LOCK();
    2056           0 :                 error = if_createrdomain(ifr->ifr_rdomainid, ifp);
    2057           0 :                 if (!error || error == EEXIST)
    2058           0 :                         error = if_setrdomain(ifp, ifr->ifr_rdomainid);
    2059           0 :                 NET_UNLOCK();
    2060           0 :                 break;
    2061             : 
    2062             :         case SIOCAIFGROUP:
    2063           0 :                 if ((error = suser(p)))
    2064             :                         break;
    2065           0 :                 NET_LOCK();
    2066           0 :                 error = if_addgroup(ifp, ifgr->ifgr_group);
    2067           0 :                 if (error == 0) {
    2068           0 :                         error = (*ifp->if_ioctl)(ifp, cmd, data);
    2069           0 :                         if (error == ENOTTY)
    2070             :                                 error = 0;
    2071           0 :                 }
    2072           0 :                 NET_UNLOCK();
    2073           0 :                 break;
    2074             : 
    2075             :         case SIOCDIFGROUP:
    2076           0 :                 if ((error = suser(p)))
    2077             :                         break;
    2078           0 :                 NET_LOCK();
    2079           0 :                 error = (*ifp->if_ioctl)(ifp, cmd, data);
    2080           0 :                 if (error == ENOTTY)
    2081             :                         error = 0;
    2082           0 :                 if (error == 0)
    2083           0 :                         error = if_delgroup(ifp, ifgr->ifgr_group);
    2084           0 :                 NET_UNLOCK();
    2085           0 :                 break;
    2086             : 
    2087             :         case SIOCSIFLLADDR:
    2088           0 :                 if ((error = suser(p)))
    2089             :                         break;
    2090           0 :                 if ((ifp->if_sadl == NULL) ||
    2091           0 :                     (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN) ||
    2092           0 :                     (ETHER_IS_MULTICAST(ifr->ifr_addr.sa_data))) {
    2093             :                         error = EINVAL;
    2094           0 :                         break;
    2095             :                 }
    2096           0 :                 NET_LOCK();
    2097           0 :                 switch (ifp->if_type) {
    2098             :                 case IFT_ETHER:
    2099             :                 case IFT_CARP:
    2100             :                 case IFT_XETHER:
    2101             :                 case IFT_ISO88025:
    2102           0 :                         error = (*ifp->if_ioctl)(ifp, cmd, data);
    2103           0 :                         if (error == ENOTTY)
    2104             :                                 error = 0;
    2105           0 :                         if (error == 0)
    2106           0 :                                 error = if_setlladdr(ifp,
    2107             :                                     ifr->ifr_addr.sa_data);
    2108             :                         break;
    2109             :                 default:
    2110             :                         error = ENODEV;
    2111           0 :                 }
    2112             : 
    2113           0 :                 if (error == 0)
    2114           0 :                         ifnewlladdr(ifp);
    2115           0 :                 NET_UNLOCK();
    2116           0 :                 break;
    2117             : 
    2118             :         case SIOCSIFLLPRIO:
    2119           0 :                 if ((error = suser(p)))
    2120             :                         break;
    2121           0 :                 if (ifr->ifr_llprio < IFQ_MINPRIO ||
    2122           0 :                     ifr->ifr_llprio > IFQ_MAXPRIO) {
    2123             :                         error = EINVAL;
    2124           0 :                         break;
    2125             :                 }
    2126           0 :                 NET_LOCK();
    2127           0 :                 ifp->if_llprio = ifr->ifr_llprio;
    2128           0 :                 NET_UNLOCK();
    2129           0 :                 break;
    2130             : 
    2131             :         case SIOCSETKALIVE:
    2132             :         case SIOCDIFPHYADDR:
    2133             :         case SIOCSLIFPHYADDR:
    2134             :         case SIOCSLIFPHYRTABLE:
    2135             :         case SIOCSLIFPHYTTL:
    2136             :         case SIOCSLIFPHYDF:
    2137             :         case SIOCADDMULTI:
    2138             :         case SIOCDELMULTI:
    2139             :         case SIOCSIFMEDIA:
    2140             :         case SIOCSVNETID:
    2141             :         case SIOCSVNETFLOWID:
    2142             :         case SIOCSIFPAIR:
    2143             :         case SIOCSIFPARENT:
    2144             :         case SIOCDIFPARENT:
    2145           0 :                 if ((error = suser(p)) != 0)
    2146             :                         break;
    2147             :                 /* FALLTHROUGH */
    2148             :         default:
    2149           0 :                 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
    2150           0 :                         (struct mbuf *) cmd, (struct mbuf *) data,
    2151           0 :                         (struct mbuf *) ifp, p));
    2152           0 :                 if (error == EOPNOTSUPP) {
    2153           0 :                         NET_LOCK();
    2154           0 :                         error = ((*ifp->if_ioctl)(ifp, cmd, data));
    2155           0 :                         NET_UNLOCK();
    2156           0 :                 }
    2157             :                 break;
    2158             :         }
    2159             : 
    2160           0 :         if (oif_flags != ifp->if_flags || oif_xflags != ifp->if_xflags)
    2161           0 :                 rtm_ifchg(ifp);
    2162             : 
    2163           0 :         if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0)
    2164           0 :                 getmicrotime(&ifp->if_lastchange);
    2165             : 
    2166           0 :         return (error);
    2167           0 : }
    2168             : 
    2169             : int
    2170           0 : ifioctl_get(u_long cmd, caddr_t data)
    2171             : {
    2172             :         struct ifnet *ifp;
    2173           0 :         struct ifreq *ifr = (struct ifreq *)data;
    2174           0 :         char ifdescrbuf[IFDESCRSIZE];
    2175           0 :         char ifrtlabelbuf[RTLABEL_LEN];
    2176             :         int error = 0;
    2177           0 :         size_t bytesdone;
    2178             :         const char *label;
    2179             : 
    2180           0 :         switch(cmd) {
    2181             :         case SIOCGIFCONF:
    2182           0 :                 NET_RLOCK();
    2183           0 :                 error = ifconf(data);
    2184           0 :                 NET_RUNLOCK();
    2185           0 :                 return (error);
    2186             :         case SIOCIFGCLONERS:
    2187           0 :                 error = if_clone_list((struct if_clonereq *)data);
    2188           0 :                 return (error);
    2189             :         case SIOCGIFGMEMB:
    2190           0 :                 NET_RLOCK();
    2191           0 :                 error = if_getgroupmembers(data);
    2192           0 :                 NET_RUNLOCK();
    2193           0 :                 return (error);
    2194             :         case SIOCGIFGATTR:
    2195           0 :                 NET_RLOCK();
    2196           0 :                 error = if_getgroupattribs(data);
    2197           0 :                 NET_RUNLOCK();
    2198           0 :                 return (error);
    2199             :         case SIOCGIFGLIST:
    2200           0 :                 NET_RLOCK();
    2201           0 :                 error = if_getgrouplist(data);
    2202           0 :                 NET_RUNLOCK();
    2203           0 :                 return (error);
    2204             :         }
    2205             : 
    2206           0 :         ifp = ifunit(ifr->ifr_name);
    2207           0 :         if (ifp == NULL)
    2208           0 :                 return (ENXIO);
    2209             : 
    2210           0 :         NET_RLOCK();
    2211             : 
    2212           0 :         switch(cmd) {
    2213             :         case SIOCGIFFLAGS:
    2214           0 :                 ifr->ifr_flags = ifp->if_flags;
    2215           0 :                 if (ifq_is_oactive(&ifp->if_snd))
    2216           0 :                         ifr->ifr_flags |= IFF_OACTIVE;
    2217             :                 break;
    2218             : 
    2219             :         case SIOCGIFXFLAGS:
    2220           0 :                 ifr->ifr_flags = ifp->if_xflags & ~(IFXF_MPSAFE|IFXF_CLONED);
    2221           0 :                 break;
    2222             : 
    2223             :         case SIOCGIFMETRIC:
    2224           0 :                 ifr->ifr_metric = ifp->if_metric;
    2225           0 :                 break;
    2226             : 
    2227             :         case SIOCGIFMTU:
    2228           0 :                 ifr->ifr_mtu = ifp->if_mtu;
    2229           0 :                 break;
    2230             : 
    2231             :         case SIOCGIFHARDMTU:
    2232           0 :                 ifr->ifr_hardmtu = ifp->if_hardmtu;
    2233           0 :                 break;
    2234             : 
    2235             :         case SIOCGIFDATA: {
    2236           0 :                 struct if_data ifdata;
    2237           0 :                 if_getdata(ifp, &ifdata);
    2238           0 :                 error = copyout(&ifdata, ifr->ifr_data, sizeof(ifdata));
    2239             :                 break;
    2240           0 :         }
    2241             : 
    2242             :         case SIOCGIFDESCR:
    2243           0 :                 strlcpy(ifdescrbuf, ifp->if_description, IFDESCRSIZE);
    2244           0 :                 error = copyoutstr(ifdescrbuf, ifr->ifr_data, IFDESCRSIZE,
    2245             :                     &bytesdone);
    2246           0 :                 break;
    2247             : 
    2248             :         case SIOCGIFRTLABEL:
    2249           0 :                 if (ifp->if_rtlabelid &&
    2250           0 :                     (label = rtlabel_id2name(ifp->if_rtlabelid)) != NULL) {
    2251           0 :                         strlcpy(ifrtlabelbuf, label, RTLABEL_LEN);
    2252           0 :                         error = copyoutstr(ifrtlabelbuf, ifr->ifr_data,
    2253             :                             RTLABEL_LEN, &bytesdone);
    2254           0 :                 } else
    2255             :                         error = ENOENT;
    2256             :                 break;
    2257             : 
    2258             :         case SIOCGIFPRIORITY:
    2259           0 :                 ifr->ifr_metric = ifp->if_priority;
    2260           0 :                 break;
    2261             : 
    2262             :         case SIOCGIFRDOMAIN:
    2263           0 :                 ifr->ifr_rdomainid = ifp->if_rdomain;
    2264           0 :                 break;
    2265             : 
    2266             :         case SIOCGIFGROUP:
    2267           0 :                 error = if_getgroup(data, ifp);
    2268           0 :                 break;
    2269             : 
    2270             :         case SIOCGIFLLPRIO:
    2271           0 :                 ifr->ifr_llprio = ifp->if_llprio;
    2272           0 :                 break;
    2273             : 
    2274             :         default:
    2275           0 :                 panic("invalid ioctl %lu", cmd);
    2276             :         }
    2277             : 
    2278           0 :         NET_RUNLOCK();
    2279             : 
    2280           0 :         return (error);
    2281           0 : }
    2282             : 
    2283             : /*
    2284             :  * Return interface configuration
    2285             :  * of system.  List may be used
    2286             :  * in later ioctl's (above) to get
    2287             :  * other information.
    2288             :  */
    2289             : int
    2290           0 : ifconf(caddr_t data)
    2291             : {
    2292           0 :         struct ifconf *ifc = (struct ifconf *)data;
    2293             :         struct ifnet *ifp;
    2294             :         struct ifaddr *ifa;
    2295           0 :         struct ifreq ifr, *ifrp;
    2296           0 :         int space = ifc->ifc_len, error = 0;
    2297             : 
    2298             :         /* If ifc->ifc_len is 0, fill it in with the needed size and return. */
    2299           0 :         if (space == 0) {
    2300           0 :                 TAILQ_FOREACH(ifp, &ifnet, if_list) {
    2301             :                         struct sockaddr *sa;
    2302             : 
    2303           0 :                         if (TAILQ_EMPTY(&ifp->if_addrlist))
    2304           0 :                                 space += sizeof (ifr);
    2305             :                         else
    2306           0 :                                 TAILQ_FOREACH(ifa,
    2307             :                                     &ifp->if_addrlist, ifa_list) {
    2308           0 :                                         sa = ifa->ifa_addr;
    2309           0 :                                         if (sa->sa_len > sizeof(*sa))
    2310           0 :                                                 space += sa->sa_len -
    2311             :                                                     sizeof(*sa);
    2312           0 :                                         space += sizeof(ifr);
    2313             :                                 }
    2314             :                 }
    2315           0 :                 ifc->ifc_len = space;
    2316           0 :                 return (0);
    2317             :         }
    2318             : 
    2319           0 :         ifrp = ifc->ifc_req;
    2320           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    2321           0 :                 if (space < sizeof(ifr))
    2322             :                         break;
    2323           0 :                 bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
    2324           0 :                 if (TAILQ_EMPTY(&ifp->if_addrlist)) {
    2325           0 :                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
    2326           0 :                         error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
    2327             :                             sizeof(ifr));
    2328           0 :                         if (error)
    2329             :                                 break;
    2330           0 :                         space -= sizeof (ifr), ifrp++;
    2331           0 :                 } else
    2332           0 :                         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    2333           0 :                                 struct sockaddr *sa = ifa->ifa_addr;
    2334             : 
    2335           0 :                                 if (space < sizeof(ifr))
    2336           0 :                                         break;
    2337           0 :                                 if (sa->sa_len <= sizeof(*sa)) {
    2338           0 :                                         ifr.ifr_addr = *sa;
    2339           0 :                                         error = copyout((caddr_t)&ifr,
    2340           0 :                                             (caddr_t)ifrp, sizeof (ifr));
    2341           0 :                                         ifrp++;
    2342           0 :                                 } else {
    2343           0 :                                         space -= sa->sa_len - sizeof(*sa);
    2344           0 :                                         if (space < sizeof (ifr))
    2345           0 :                                                 break;
    2346           0 :                                         error = copyout((caddr_t)&ifr,
    2347           0 :                                             (caddr_t)ifrp,
    2348             :                                             sizeof(ifr.ifr_name));
    2349           0 :                                         if (error == 0)
    2350           0 :                                                 error = copyout((caddr_t)sa,
    2351           0 :                                                     (caddr_t)&ifrp->ifr_addr,
    2352           0 :                                                     sa->sa_len);
    2353           0 :                                         ifrp = (struct ifreq *)(sa->sa_len +
    2354           0 :                                             (caddr_t)&ifrp->ifr_addr);
    2355             :                                 }
    2356           0 :                                 if (error)
    2357           0 :                                         break;
    2358           0 :                                 space -= sizeof (ifr);
    2359           0 :                         }
    2360             :         }
    2361           0 :         ifc->ifc_len -= space;
    2362           0 :         return (error);
    2363           0 : }
    2364             : 
    2365             : void
    2366           0 : if_getdata(struct ifnet *ifp, struct if_data *data)
    2367             : {
    2368             :         unsigned int i;
    2369             : 
    2370           0 :         *data = ifp->if_data;
    2371             : 
    2372           0 :         for (i = 0; i < ifp->if_nifqs; i++) {
    2373           0 :                 struct ifqueue *ifq = ifp->if_ifqs[i];
    2374             : 
    2375           0 :                 ifq_add_data(ifq, data);
    2376             :         }
    2377             : 
    2378           0 :         for (i = 0; i < ifp->if_niqs; i++) {
    2379           0 :                 struct ifiqueue *ifiq = ifp->if_iqs[i];
    2380             : 
    2381           0 :                 ifiq_add_data(ifiq, data);
    2382             :         }
    2383           0 : }
    2384             : 
    2385             : /*
    2386             :  * Dummy functions replaced in ifnet during detach (if protocols decide to
    2387             :  * fiddle with the if during detach.
    2388             :  */
    2389             : void
    2390           0 : if_detached_qstart(struct ifqueue *ifq)
    2391             : {
    2392           0 :         ifq_purge(ifq);
    2393           0 : }
    2394             : 
    2395             : int
    2396           0 : if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
    2397             : {
    2398           0 :         return ENODEV;
    2399             : }
    2400             : 
    2401             : /*
    2402             :  * Create interface group without members
    2403             :  */
    2404             : struct ifg_group *
    2405           0 : if_creategroup(const char *groupname)
    2406             : {
    2407             :         struct ifg_group        *ifg;
    2408             : 
    2409           0 :         if ((ifg = malloc(sizeof(*ifg), M_TEMP, M_NOWAIT)) == NULL)
    2410           0 :                 return (NULL);
    2411             : 
    2412           0 :         strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
    2413           0 :         ifg->ifg_refcnt = 0;
    2414           0 :         ifg->ifg_carp_demoted = 0;
    2415           0 :         TAILQ_INIT(&ifg->ifg_members);
    2416             : #if NPF > 0
    2417           0 :         pfi_attach_ifgroup(ifg);
    2418             : #endif
    2419           0 :         TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
    2420             : 
    2421           0 :         return (ifg);
    2422           0 : }
    2423             : 
    2424             : /*
    2425             :  * Add a group to an interface
    2426             :  */
    2427             : int
    2428           0 : if_addgroup(struct ifnet *ifp, const char *groupname)
    2429             : {
    2430             :         struct ifg_list         *ifgl;
    2431             :         struct ifg_group        *ifg = NULL;
    2432             :         struct ifg_member       *ifgm;
    2433             : 
    2434           0 :         if (groupname[0] && groupname[strlen(groupname) - 1] >= '0' &&
    2435           0 :             groupname[strlen(groupname) - 1] <= '9')
    2436           0 :                 return (EINVAL);
    2437             : 
    2438           0 :         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
    2439           0 :                 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
    2440           0 :                         return (EEXIST);
    2441             : 
    2442           0 :         if ((ifgl = malloc(sizeof(*ifgl), M_TEMP, M_NOWAIT)) == NULL)
    2443           0 :                 return (ENOMEM);
    2444             : 
    2445           0 :         if ((ifgm = malloc(sizeof(*ifgm), M_TEMP, M_NOWAIT)) == NULL) {
    2446           0 :                 free(ifgl, M_TEMP, sizeof(*ifgl));
    2447           0 :                 return (ENOMEM);
    2448             :         }
    2449             : 
    2450           0 :         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
    2451           0 :                 if (!strcmp(ifg->ifg_group, groupname))
    2452             :                         break;
    2453             : 
    2454           0 :         if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) {
    2455           0 :                 free(ifgl, M_TEMP, sizeof(*ifgl));
    2456           0 :                 free(ifgm, M_TEMP, sizeof(*ifgm));
    2457           0 :                 return (ENOMEM);
    2458             :         }
    2459             : 
    2460           0 :         ifg->ifg_refcnt++;
    2461           0 :         ifgl->ifgl_group = ifg;
    2462           0 :         ifgm->ifgm_ifp = ifp;
    2463             : 
    2464           0 :         TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
    2465           0 :         TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
    2466             : 
    2467             : #if NPF > 0
    2468           0 :         pfi_group_addmember(groupname, ifp);
    2469             : #endif
    2470             : 
    2471           0 :         return (0);
    2472           0 : }
    2473             : 
    2474             : /*
    2475             :  * Remove a group from an interface
    2476             :  */
    2477             : int
    2478           0 : if_delgroup(struct ifnet *ifp, const char *groupname)
    2479             : {
    2480             :         struct ifg_list         *ifgl;
    2481             :         struct ifg_member       *ifgm;
    2482             : 
    2483           0 :         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
    2484           0 :                 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
    2485             :                         break;
    2486           0 :         if (ifgl == NULL)
    2487           0 :                 return (ENOENT);
    2488             : 
    2489           0 :         TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
    2490             : 
    2491           0 :         TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
    2492           0 :                 if (ifgm->ifgm_ifp == ifp)
    2493             :                         break;
    2494             : 
    2495           0 :         if (ifgm != NULL) {
    2496           0 :                 TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
    2497           0 :                 free(ifgm, M_TEMP, sizeof(*ifgm));
    2498           0 :         }
    2499             : 
    2500           0 :         if (--ifgl->ifgl_group->ifg_refcnt == 0) {
    2501           0 :                 TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
    2502             : #if NPF > 0
    2503           0 :                 pfi_detach_ifgroup(ifgl->ifgl_group);
    2504             : #endif
    2505           0 :                 free(ifgl->ifgl_group, M_TEMP, 0);
    2506           0 :         }
    2507             : 
    2508           0 :         free(ifgl, M_TEMP, sizeof(*ifgl));
    2509             : 
    2510             : #if NPF > 0
    2511           0 :         pfi_group_change(groupname);
    2512             : #endif
    2513             : 
    2514           0 :         return (0);
    2515           0 : }
    2516             : 
    2517             : /*
    2518             :  * Stores all groups from an interface in memory pointed
    2519             :  * to by data
    2520             :  */
    2521             : int
    2522           0 : if_getgroup(caddr_t data, struct ifnet *ifp)
    2523             : {
    2524             :         int                      len, error;
    2525             :         struct ifg_list         *ifgl;
    2526           0 :         struct ifg_req           ifgrq, *ifgp;
    2527           0 :         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
    2528             : 
    2529           0 :         if (ifgr->ifgr_len == 0) {
    2530           0 :                 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
    2531           0 :                         ifgr->ifgr_len += sizeof(struct ifg_req);
    2532           0 :                 return (0);
    2533             :         }
    2534             : 
    2535             :         len = ifgr->ifgr_len;
    2536           0 :         ifgp = ifgr->ifgr_groups;
    2537           0 :         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
    2538           0 :                 if (len < sizeof(ifgrq))
    2539           0 :                         return (EINVAL);
    2540           0 :                 bzero(&ifgrq, sizeof ifgrq);
    2541           0 :                 strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
    2542             :                     sizeof(ifgrq.ifgrq_group));
    2543           0 :                 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
    2544             :                     sizeof(struct ifg_req))))
    2545           0 :                         return (error);
    2546           0 :                 len -= sizeof(ifgrq);
    2547           0 :                 ifgp++;
    2548             :         }
    2549             : 
    2550           0 :         return (0);
    2551           0 : }
    2552             : 
    2553             : /*
    2554             :  * Stores all members of a group in memory pointed to by data
    2555             :  */
    2556             : int
    2557           0 : if_getgroupmembers(caddr_t data)
    2558             : {
    2559           0 :         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
    2560             :         struct ifg_group        *ifg;
    2561             :         struct ifg_member       *ifgm;
    2562           0 :         struct ifg_req           ifgrq, *ifgp;
    2563             :         int                      len, error;
    2564             : 
    2565           0 :         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
    2566           0 :                 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
    2567             :                         break;
    2568           0 :         if (ifg == NULL)
    2569           0 :                 return (ENOENT);
    2570             : 
    2571           0 :         if (ifgr->ifgr_len == 0) {
    2572           0 :                 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
    2573           0 :                         ifgr->ifgr_len += sizeof(ifgrq);
    2574           0 :                 return (0);
    2575             :         }
    2576             : 
    2577             :         len = ifgr->ifgr_len;
    2578           0 :         ifgp = ifgr->ifgr_groups;
    2579           0 :         TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
    2580           0 :                 if (len < sizeof(ifgrq))
    2581           0 :                         return (EINVAL);
    2582           0 :                 bzero(&ifgrq, sizeof ifgrq);
    2583           0 :                 strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
    2584             :                     sizeof(ifgrq.ifgrq_member));
    2585           0 :                 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
    2586             :                     sizeof(struct ifg_req))))
    2587           0 :                         return (error);
    2588           0 :                 len -= sizeof(ifgrq);
    2589           0 :                 ifgp++;
    2590             :         }
    2591             : 
    2592           0 :         return (0);
    2593           0 : }
    2594             : 
    2595             : int
    2596           0 : if_getgroupattribs(caddr_t data)
    2597             : {
    2598           0 :         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
    2599             :         struct ifg_group        *ifg;
    2600             : 
    2601           0 :         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
    2602           0 :                 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
    2603             :                         break;
    2604           0 :         if (ifg == NULL)
    2605           0 :                 return (ENOENT);
    2606             : 
    2607           0 :         ifgr->ifgr_attrib.ifg_carp_demoted = ifg->ifg_carp_demoted;
    2608             : 
    2609           0 :         return (0);
    2610           0 : }
    2611             : 
    2612             : int
    2613           0 : if_setgroupattribs(caddr_t data)
    2614             : {
    2615           0 :         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
    2616             :         struct ifg_group        *ifg;
    2617             :         struct ifg_member       *ifgm;
    2618             :         int                      demote;
    2619             : 
    2620           0 :         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
    2621           0 :                 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
    2622             :                         break;
    2623           0 :         if (ifg == NULL)
    2624           0 :                 return (ENOENT);
    2625             : 
    2626           0 :         demote = ifgr->ifgr_attrib.ifg_carp_demoted;
    2627           0 :         if (demote + ifg->ifg_carp_demoted > 0xff ||
    2628           0 :             demote + ifg->ifg_carp_demoted < 0)
    2629           0 :                 return (EINVAL);
    2630             : 
    2631           0 :         ifg->ifg_carp_demoted += demote;
    2632             : 
    2633           0 :         TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
    2634           0 :                 ifgm->ifgm_ifp->if_ioctl(ifgm->ifgm_ifp, SIOCSIFGATTR, data);
    2635             : 
    2636           0 :         return (0);
    2637           0 : }
    2638             : 
    2639             : /*
    2640             :  * Stores all groups in memory pointed to by data
    2641             :  */
    2642             : int
    2643           0 : if_getgrouplist(caddr_t data)
    2644             : {
    2645           0 :         struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
    2646             :         struct ifg_group        *ifg;
    2647           0 :         struct ifg_req           ifgrq, *ifgp;
    2648             :         int                      len, error;
    2649             : 
    2650           0 :         if (ifgr->ifgr_len == 0) {
    2651           0 :                 TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
    2652           0 :                         ifgr->ifgr_len += sizeof(ifgrq);
    2653           0 :                 return (0);
    2654             :         }
    2655             : 
    2656             :         len = ifgr->ifgr_len;
    2657           0 :         ifgp = ifgr->ifgr_groups;
    2658           0 :         TAILQ_FOREACH(ifg, &ifg_head, ifg_next) {
    2659           0 :                 if (len < sizeof(ifgrq))
    2660           0 :                         return (EINVAL);
    2661           0 :                 bzero(&ifgrq, sizeof ifgrq);
    2662           0 :                 strlcpy(ifgrq.ifgrq_group, ifg->ifg_group,
    2663             :                     sizeof(ifgrq.ifgrq_group));
    2664           0 :                 if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
    2665             :                     sizeof(struct ifg_req))))
    2666           0 :                         return (error);
    2667           0 :                 len -= sizeof(ifgrq);
    2668           0 :                 ifgp++;
    2669             :         }
    2670             : 
    2671           0 :         return (0);
    2672           0 : }
    2673             : 
    2674             : void
    2675           0 : if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
    2676             : {
    2677           0 :         switch (dst->sa_family) {
    2678             :         case AF_INET:
    2679           0 :                 if (satosin(dst)->sin_addr.s_addr == INADDR_ANY &&
    2680           0 :                     mask && (mask->sa_len == 0 ||
    2681           0 :                     satosin(mask)->sin_addr.s_addr == INADDR_ANY))
    2682           0 :                         if_group_egress_build();
    2683             :                 break;
    2684             : #ifdef INET6
    2685             :         case AF_INET6:
    2686           0 :                 if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
    2687           0 :                     &in6addr_any) && mask && (mask->sa_len == 0 ||
    2688           0 :                     IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
    2689             :                     &in6addr_any)))
    2690           0 :                         if_group_egress_build();
    2691             :                 break;
    2692             : #endif
    2693             :         }
    2694           0 : }
    2695             : 
    2696             : int
    2697           0 : if_group_egress_build(void)
    2698             : {
    2699             :         struct ifnet            *ifp;
    2700             :         struct ifg_group        *ifg;
    2701             :         struct ifg_member       *ifgm, *next;
    2702           0 :         struct sockaddr_in       sa_in;
    2703             : #ifdef INET6
    2704           0 :         struct sockaddr_in6      sa_in6;
    2705             : #endif
    2706             :         struct rtentry          *rt;
    2707             : 
    2708           0 :         TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
    2709           0 :                 if (!strcmp(ifg->ifg_group, IFG_EGRESS))
    2710             :                         break;
    2711             : 
    2712           0 :         if (ifg != NULL)
    2713           0 :                 TAILQ_FOREACH_SAFE(ifgm, &ifg->ifg_members, ifgm_next, next)
    2714           0 :                         if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS);
    2715             : 
    2716           0 :         bzero(&sa_in, sizeof(sa_in));
    2717           0 :         sa_in.sin_len = sizeof(sa_in);
    2718           0 :         sa_in.sin_family = AF_INET;
    2719           0 :         rt = rtable_lookup(0, sintosa(&sa_in), sintosa(&sa_in), NULL, RTP_ANY);
    2720           0 :         while (rt != NULL) {
    2721           0 :                 ifp = if_get(rt->rt_ifidx);
    2722           0 :                 if (ifp != NULL) {
    2723           0 :                         if_addgroup(ifp, IFG_EGRESS);
    2724           0 :                         if_put(ifp);
    2725           0 :                 }
    2726           0 :                 rt = rtable_iterate(rt);
    2727             :         }
    2728             : 
    2729             : #ifdef INET6
    2730           0 :         bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
    2731           0 :         rt = rtable_lookup(0, sin6tosa(&sa_in6), sin6tosa(&sa_in6), NULL,
    2732             :             RTP_ANY);
    2733           0 :         while (rt != NULL) {
    2734           0 :                 ifp = if_get(rt->rt_ifidx);
    2735           0 :                 if (ifp != NULL) {
    2736           0 :                         if_addgroup(ifp, IFG_EGRESS);
    2737           0 :                         if_put(ifp);
    2738           0 :                 }
    2739           0 :                 rt = rtable_iterate(rt);
    2740             :         }
    2741             : #endif /* INET6 */
    2742             : 
    2743           0 :         return (0);
    2744           0 : }
    2745             : 
    2746             : /*
    2747             :  * Set/clear promiscuous mode on interface ifp based on the truth value
    2748             :  * of pswitch.  The calls are reference counted so that only the first
    2749             :  * "on" request actually has an effect, as does the final "off" request.
    2750             :  * Results are undefined if the "off" and "on" requests are not matched.
    2751             :  */
    2752             : int
    2753           0 : ifpromisc(struct ifnet *ifp, int pswitch)
    2754             : {
    2755           0 :         struct ifreq ifr;
    2756             :         unsigned short oif_flags;
    2757             :         int oif_pcount, error;
    2758             : 
    2759           0 :         oif_flags = ifp->if_flags;
    2760           0 :         oif_pcount = ifp->if_pcount;
    2761           0 :         if (pswitch) {
    2762           0 :                 if (ifp->if_pcount++ != 0)
    2763           0 :                         return (0);
    2764           0 :                 ifp->if_flags |= IFF_PROMISC;
    2765           0 :         } else {
    2766           0 :                 if (--ifp->if_pcount > 0)
    2767           0 :                         return (0);
    2768           0 :                 ifp->if_flags &= ~IFF_PROMISC;
    2769             :         }
    2770             : 
    2771           0 :         if ((ifp->if_flags & IFF_UP) == 0)
    2772           0 :                 return (0);
    2773             : 
    2774           0 :         memset(&ifr, 0, sizeof(ifr));
    2775           0 :         ifr.ifr_flags = ifp->if_flags;
    2776           0 :         error = ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
    2777           0 :         if (error) {
    2778           0 :                 ifp->if_flags = oif_flags;
    2779           0 :                 ifp->if_pcount = oif_pcount;
    2780           0 :         }
    2781             : 
    2782           0 :         return (error);
    2783           0 : }
    2784             : 
    2785             : void
    2786           0 : ifa_add(struct ifnet *ifp, struct ifaddr *ifa)
    2787             : {
    2788           0 :         TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);
    2789           0 : }
    2790             : 
    2791             : void
    2792           0 : ifa_del(struct ifnet *ifp, struct ifaddr *ifa)
    2793             : {
    2794           0 :         TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
    2795           0 : }
    2796             : 
    2797             : void
    2798           0 : ifa_update_broadaddr(struct ifnet *ifp, struct ifaddr *ifa, struct sockaddr *sa)
    2799             : {
    2800           0 :         if (ifa->ifa_broadaddr->sa_len != sa->sa_len)
    2801           0 :                 panic("ifa_update_broadaddr does not support dynamic length");
    2802           0 :         bcopy(sa, ifa->ifa_broadaddr, sa->sa_len);
    2803           0 : }
    2804             : 
    2805             : #ifdef DDB
    2806             : /* debug function, can be called from ddb> */
    2807             : void
    2808           0 : ifa_print_all(void)
    2809             : {
    2810             :         struct ifnet *ifp;
    2811             :         struct ifaddr *ifa;
    2812             : 
    2813           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    2814           0 :                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    2815           0 :                         char addr[INET6_ADDRSTRLEN];
    2816             : 
    2817           0 :                         switch (ifa->ifa_addr->sa_family) {
    2818             :                         case AF_INET:
    2819           0 :                                 printf("%s", inet_ntop(AF_INET,
    2820           0 :                                     &satosin(ifa->ifa_addr)->sin_addr,
    2821           0 :                                     addr, sizeof(addr)));
    2822           0 :                                 break;
    2823             : #ifdef INET6
    2824             :                         case AF_INET6:
    2825           0 :                                 printf("%s", inet_ntop(AF_INET6,
    2826           0 :                                     &(satosin6(ifa->ifa_addr))->sin6_addr,
    2827           0 :                                     addr, sizeof(addr)));
    2828           0 :                                 break;
    2829             : #endif
    2830             :                         }
    2831           0 :                         printf(" on %s\n", ifp->if_xname);
    2832           0 :                 }
    2833             :         }
    2834           0 : }
    2835             : #endif /* DDB */
    2836             : 
    2837             : void
    2838           0 : ifnewlladdr(struct ifnet *ifp)
    2839             : {
    2840             : #ifdef INET6
    2841             :         struct ifaddr *ifa;
    2842             : #endif
    2843           0 :         struct ifreq ifrq;
    2844             :         short up;
    2845             :         int s;
    2846             : 
    2847           0 :         s = splnet();
    2848           0 :         up = ifp->if_flags & IFF_UP;
    2849             : 
    2850           0 :         if (up) {
    2851             :                 /* go down for a moment... */
    2852           0 :                 ifp->if_flags &= ~IFF_UP;
    2853           0 :                 ifrq.ifr_flags = ifp->if_flags;
    2854           0 :                 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
    2855           0 :         }
    2856             : 
    2857           0 :         ifp->if_flags |= IFF_UP;
    2858           0 :         ifrq.ifr_flags = ifp->if_flags;
    2859           0 :         (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
    2860             : 
    2861             : #ifdef INET6
    2862             :         /*
    2863             :          * Update the link-local address.  Don't do it if we're
    2864             :          * a router to avoid confusing hosts on the network.
    2865             :          */
    2866           0 :         if (!ip6_forwarding) {
    2867           0 :                 ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa;
    2868           0 :                 if (ifa) {
    2869           0 :                         in6_purgeaddr(ifa);
    2870           0 :                         dohooks(ifp->if_addrhooks, 0);
    2871           0 :                         in6_ifattach(ifp);
    2872           0 :                 }
    2873             :         }
    2874             : #endif
    2875           0 :         if (!up) {
    2876             :                 /* go back down */
    2877           0 :                 ifp->if_flags &= ~IFF_UP;
    2878           0 :                 ifrq.ifr_flags = ifp->if_flags;
    2879           0 :                 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
    2880           0 :         }
    2881           0 :         splx(s);
    2882           0 : }
    2883             : 
    2884             : int net_ticks;
    2885             : u_int net_livelocks;
    2886             : 
    2887             : void
    2888           0 : net_tick(void *null)
    2889             : {
    2890             :         extern int ticks;
    2891             : 
    2892           0 :         if (ticks - net_ticks > 1)
    2893           0 :                 net_livelocks++;
    2894             : 
    2895           0 :         net_ticks = ticks;
    2896             : 
    2897           0 :         timeout_add(&net_tick_to, 1);
    2898           0 : }
    2899             : 
    2900             : int
    2901           0 : net_livelocked(void)
    2902             : {
    2903             :         extern int ticks;
    2904             : 
    2905           0 :         return (ticks - net_ticks > 1);
    2906             : }
    2907             : 
    2908             : void
    2909           0 : if_rxr_init(struct if_rxring *rxr, u_int lwm, u_int hwm)
    2910             : {
    2911             :         extern int ticks;
    2912             : 
    2913           0 :         memset(rxr, 0, sizeof(*rxr));
    2914             : 
    2915           0 :         rxr->rxr_adjusted = ticks;
    2916           0 :         rxr->rxr_cwm = rxr->rxr_lwm = lwm;
    2917           0 :         rxr->rxr_hwm = hwm;
    2918           0 : }
    2919             : 
    2920             : static inline void
    2921           0 : if_rxr_adjust_cwm(struct if_rxring *rxr)
    2922             : {
    2923             :         extern int ticks;
    2924             : 
    2925           0 :         if (net_livelocked()) {
    2926           0 :                 if (rxr->rxr_cwm > rxr->rxr_lwm)
    2927           0 :                         rxr->rxr_cwm--;
    2928             :                 else
    2929             :                         return;
    2930           0 :         } else if (rxr->rxr_alive >= rxr->rxr_lwm)
    2931             :                 return;
    2932           0 :         else if (rxr->rxr_cwm < rxr->rxr_hwm)
    2933           0 :                 rxr->rxr_cwm++;
    2934             : 
    2935           0 :         rxr->rxr_adjusted = ticks;
    2936           0 : }
    2937             : 
    2938             : void
    2939           0 : if_rxr_livelocked(struct if_rxring *rxr)
    2940             : {
    2941             :         extern int ticks;
    2942             : 
    2943           0 :         if (ticks - rxr->rxr_adjusted >= 1) {
    2944           0 :                 if (rxr->rxr_cwm > rxr->rxr_lwm)
    2945           0 :                         rxr->rxr_cwm--;
    2946             : 
    2947           0 :                 rxr->rxr_adjusted = ticks;
    2948           0 :         }
    2949           0 : }
    2950             : 
    2951             : u_int
    2952           0 : if_rxr_get(struct if_rxring *rxr, u_int max)
    2953             : {
    2954             :         extern int ticks;
    2955             :         u_int diff;
    2956             : 
    2957           0 :         if (ticks - rxr->rxr_adjusted >= 1) {
    2958             :                 /* we're free to try for an adjustment */
    2959           0 :                 if_rxr_adjust_cwm(rxr);
    2960           0 :         }
    2961             : 
    2962           0 :         if (rxr->rxr_alive >= rxr->rxr_cwm)
    2963           0 :                 return (0);
    2964             : 
    2965           0 :         diff = min(rxr->rxr_cwm - rxr->rxr_alive, max);
    2966           0 :         rxr->rxr_alive += diff;
    2967             : 
    2968           0 :         return (diff);
    2969           0 : }
    2970             : 
    2971             : int
    2972           0 : if_rxr_info_ioctl(struct if_rxrinfo *uifri, u_int t, struct if_rxring_info *e)
    2973             : {
    2974           0 :         struct if_rxrinfo kifri;
    2975             :         int error;
    2976             :         u_int n;
    2977             : 
    2978           0 :         error = copyin(uifri, &kifri, sizeof(kifri));
    2979           0 :         if (error)
    2980           0 :                 return (error);
    2981             : 
    2982           0 :         n = min(t, kifri.ifri_total);
    2983           0 :         kifri.ifri_total = t;
    2984             : 
    2985           0 :         if (n > 0) {
    2986           0 :                 error = copyout(e, kifri.ifri_entries, sizeof(*e) * n);
    2987           0 :                 if (error)
    2988           0 :                         return (error);
    2989             :         }
    2990             : 
    2991           0 :         return (copyout(&kifri, uifri, sizeof(kifri)));
    2992           0 : }
    2993             : 
    2994             : int
    2995           0 : if_rxr_ioctl(struct if_rxrinfo *ifri, const char *name, u_int size,
    2996             :     struct if_rxring *rxr)
    2997             : {
    2998           0 :         struct if_rxring_info ifr;
    2999             : 
    3000           0 :         memset(&ifr, 0, sizeof(ifr));
    3001             : 
    3002           0 :         if (name != NULL)
    3003           0 :                 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    3004             : 
    3005           0 :         ifr.ifr_size = size;
    3006           0 :         ifr.ifr_info = *rxr;
    3007             : 
    3008           0 :         return (if_rxr_info_ioctl(ifri, 1, &ifr));
    3009           0 : }
    3010             : 
    3011             : /*
    3012             :  * Network stack input queues.
    3013             :  */
    3014             : 
    3015             : void
    3016           0 : niq_init(struct niqueue *niq, u_int maxlen, u_int isr)
    3017             : {
    3018           0 :         mq_init(&niq->ni_q, maxlen, IPL_NET);
    3019           0 :         niq->ni_isr = isr;
    3020           0 : }
    3021             : 
    3022             : int
    3023           0 : niq_enqueue(struct niqueue *niq, struct mbuf *m)
    3024             : {
    3025             :         int rv;
    3026             : 
    3027           0 :         rv = mq_enqueue(&niq->ni_q, m);
    3028           0 :         if (rv == 0)
    3029           0 :                 schednetisr(niq->ni_isr);
    3030             :         else
    3031           0 :                 if_congestion();
    3032             : 
    3033           0 :         return (rv);
    3034             : }
    3035             : 
    3036             : int
    3037           0 : niq_enlist(struct niqueue *niq, struct mbuf_list *ml)
    3038             : {
    3039             :         int rv;
    3040             : 
    3041           0 :         rv = mq_enlist(&niq->ni_q, ml);
    3042           0 :         if (rv == 0)
    3043           0 :                 schednetisr(niq->ni_isr);
    3044             :         else
    3045           0 :                 if_congestion();
    3046             : 
    3047           0 :         return (rv);
    3048             : }
    3049             : 
    3050             : __dead void
    3051           0 : unhandled_af(int af)
    3052             : {
    3053           0 :         panic("unhandled af %d", af);
    3054             : }
    3055             : 
    3056             : /*
    3057             :  * XXXSMP This tunable is here to work around the fact that IPsec
    3058             :  * globals aren't ready to be accessed by multiple threads in
    3059             :  * parallel.
    3060             :  */
    3061             : int              nettaskqs = NET_TASKQ;
    3062             : 
    3063             : struct taskq *
    3064           0 : net_tq(unsigned int ifindex)
    3065             : {
    3066             :         struct taskq *t = NULL;
    3067             : 
    3068           0 :         t = nettqmp[ifindex % nettaskqs];
    3069             : 
    3070           0 :         return (t);
    3071             : }

Generated by: LCOV version 1.13