root/net/if.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ifinit
  2. if_attachsetup
  3. if_alloc_sadl
  4. if_free_sadl
  5. if_attachdomain
  6. if_attachdomain1
  7. if_attachhead
  8. if_attach
  9. if_detach
  10. if_detach_queues
  11. if_clone_create
  12. if_clone_destroy
  13. if_clone_lookup
  14. if_clone_attach
  15. if_clone_detach
  16. if_clone_list
  17. if_congestion
  18. if_congestion_clear
  19. ifa_ifwithaddr
  20. ifa_ifwithdstaddr
  21. ifa_ifwithnet
  22. ifa_ifwithaf
  23. ifaof_ifpforaddr
  24. link_rtrequest
  25. if_down
  26. if_up
  27. if_link_state_change
  28. if_qflush
  29. if_slowtimo
  30. ifunit
  31. ifioctl
  32. ifconf
  33. if_detached_start
  34. if_detached_ioctl
  35. if_detached_init
  36. if_detached_watchdog
  37. if_creategroup
  38. if_addgroup
  39. if_delgroup
  40. if_getgroup
  41. if_getgroupmembers
  42. if_getgroupattribs
  43. if_setgroupattribs
  44. if_group_routechange
  45. if_group_egress_build
  46. ifpromisc
  47. sysctl_ifq
  48. netrndintr

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

/* [<][>][^][v][top][bottom][index][help] */