[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*-
  2  * Copyright (c) 1980, 1986, 1993
  3  *      The Regents of the University of California.  All rights reserved.
  4  *
  5  * Redistribution and use in source and binary forms, with or without
  6  * modification, are permitted provided that the following conditions
  7  * are met:
  8  * 1. Redistributions of source code must retain the above copyright
  9  *    notice, this list of conditions and the following disclaimer.
 10  * 2. Redistributions in binary form must reproduce the above copyright
 11  *    notice, this list of conditions and the following disclaimer in the
 12  *    documentation and/or other materials provided with the distribution.
 13  * 4. Neither the name of the University nor the names of its contributors
 14  *    may be used to endorse or promote products derived from this software
 15  *    without specific prior written permission.
 16  *
 17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 27  * SUCH DAMAGE.
 28  *
 29  *      @(#)if.c        8.5 (Berkeley) 1/9/95
 30  * $FreeBSD: src/sys/net/if.c,v 1.290 2008/11/06 15:26:09 bz Exp $
 31  */
 32 
 33 #include "opt_compat.h"
 34 #include "opt_inet6.h"
 35 #include "opt_inet.h"
 36 #include "opt_mac.h"
 37 #include "opt_carp.h"
 38 
 39 #include <sys/param.h>
 40 #include <sys/types.h>
 41 #include <sys/conf.h>
 42 #include <sys/malloc.h>
 43 #include <sys/sbuf.h>
 44 #include <sys/bus.h>
 45 #include <sys/mbuf.h>
 46 #include <sys/systm.h>
 47 #include <sys/priv.h>
 48 #include <sys/proc.h>
 49 #include <sys/socket.h>
 50 #include <sys/socketvar.h>
 51 #include <sys/protosw.h>
 52 #include <sys/kernel.h>
 53 #include <sys/sockio.h>
 54 #include <sys/syslog.h>
 55 #include <sys/sysctl.h>
 56 #include <sys/taskqueue.h>
 57 #include <sys/domain.h>
 58 #include <sys/jail.h>
 59 #include <sys/vimage.h>
 60 #include <machine/stdarg.h>
 61 
 62 #include <net/if.h>
 63 #include <net/if_arp.h>
 64 #include <net/if_clone.h>
 65 #include <net/if_dl.h>
 66 #include <net/if_types.h>
 67 #include <net/if_var.h>
 68 #include <net/radix.h>
 69 #include <net/route.h>
 70 
 71 #if defined(INET) || defined(INET6)
 72 /*XXX*/
 73 #include <netinet/in.h>
 74 #include <netinet/in_var.h>
 75 #ifdef INET6
 76 #include <netinet6/in6_var.h>
 77 #include <netinet6/in6_ifattach.h>
 78 #endif
 79 #endif
 80 #ifdef INET
 81 #include <netinet/if_ether.h>
 82 #endif
 83 #ifdef DEV_CARP
 84 #include <netinet/ip_carp.h>
 85 #endif
 86 
 87 #include <security/mac/mac_framework.h>
 88 
 89 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
 90 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
 91 
 92 /* Log link state change events */
 93 static int log_link_state_change = 1;
 94 
 95 SYSCTL_INT(_net_link, OID_AUTO, log_link_state_change, CTLFLAG_RW,
 96         &log_link_state_change, 0,
 97         "log interface link state change events");
 98 
 99 void    (*bstp_linkstate_p)(struct ifnet *ifp, int state);
100 void    (*ng_ether_link_state_p)(struct ifnet *ifp, int state);
101 void    (*lagg_linkstate_p)(struct ifnet *ifp, int state);
102 
103 struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL;
104 
105 /*
106  * XXX: Style; these should be sorted alphabetically, and unprototyped
107  * static functions should be prototyped. Currently they are sorted by
108  * declaration order.
109  */
110 static void     if_attachdomain(void *);
111 static void     if_attachdomain1(struct ifnet *);
112 static int      ifconf(u_long, caddr_t);
113 static void     if_freemulti(struct ifmultiaddr *);
114 static void     if_grow(void);
115 static void     if_init(void *);
116 static void     if_qflush(struct ifaltq *);
117 static void     if_route(struct ifnet *, int flag, int fam);
118 static int      if_setflag(struct ifnet *, int, int, int *, int);
119 static void     if_slowtimo(void *);
120 static void     if_unroute(struct ifnet *, int flag, int fam);
121 static void     link_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
122 static int      if_rtdel(struct radix_node *, void *);
123 static int      ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *);
124 static int      if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int);
125 static void     if_start_deferred(void *context, int pending);
126 static void     do_link_state_change(void *, int);
127 static int      if_getgroup(struct ifgroupreq *, struct ifnet *);
128 static int      if_getgroupmembers(struct ifgroupreq *);
129 #ifdef INET6
130 /*
131  * XXX: declare here to avoid to include many inet6 related files..
132  * should be more generalized?
133  */
134 extern void     nd6_setmtu(struct ifnet *);
135 #endif
136 
137 int     if_index = 0;
138 int     ifqmaxlen = IFQ_MAXLEN;
139 struct  ifnethead ifnet;        /* depend on static init XXX */
140 struct  ifgrouphead ifg_head;
141 struct  mtx ifnet_lock;
142 static  if_com_alloc_t *if_com_alloc[256];
143 static  if_com_free_t *if_com_free[256];
144 
145 static int      if_indexlim = 8;
146 static struct   knlist ifklist;
147 
148 /*
149  * Table of ifnet/cdev by index.  Locked with ifnet_lock.
150  */
151 static struct ifindex_entry *ifindex_table = NULL;
152 
153 static void     filt_netdetach(struct knote *kn);
154 static int      filt_netdev(struct knote *kn, long hint);
155 
156 static struct filterops netdev_filtops =
157     { 1, NULL, filt_netdetach, filt_netdev };
158 
159 /*
160  * System initialization
161  */
162 SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_FIRST, if_init, NULL);
163 SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_slowtimo, NULL);
164 
165 MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals");
166 MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
167 MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
168 
169 struct ifnet *
170 ifnet_byindex(u_short idx)
171 {
172         INIT_VNET_NET(curvnet);
173         struct ifnet *ifp;
174 
175         IFNET_RLOCK();
176         ifp = V_ifindex_table[idx].ife_ifnet;
177         IFNET_RUNLOCK();
178         return (ifp);
179 }
180 
181 static void
182 ifnet_setbyindex(u_short idx, struct ifnet *ifp)
183 {
184         INIT_VNET_NET(curvnet);
185 
186         IFNET_WLOCK_ASSERT();
187 
188         V_ifindex_table[idx].ife_ifnet = ifp;
189 }
190 
191 struct ifaddr *
192 ifaddr_byindex(u_short idx)
193 {
194         INIT_VNET_NET(curvnet);
195         struct ifaddr *ifa;
196 
197         IFNET_RLOCK();
198         ifa = ifnet_byindex(idx)->if_addr;
199         IFNET_RUNLOCK();
200         return (ifa);
201 }
202 
203 struct cdev *
204 ifdev_byindex(u_short idx)
205 {
206         INIT_VNET_NET(curvnet);
207         struct cdev *cdev;
208 
209         IFNET_RLOCK();
210         cdev = V_ifindex_table[idx].ife_dev;
211         IFNET_RUNLOCK();
212         return (cdev);
213 }
214 
215 static void
216 ifdev_setbyindex(u_short idx, struct cdev *cdev)
217 {
218         INIT_VNET_NET(curvnet);
219 
220         IFNET_WLOCK();
221         V_ifindex_table[idx].ife_dev = cdev;
222         IFNET_WUNLOCK();
223 }
224 
225 static d_open_t         netopen;
226 static d_close_t        netclose;
227 static d_ioctl_t        netioctl;
228 static d_kqfilter_t     netkqfilter;
229 
230 static struct cdevsw net_cdevsw = {
231         .d_version =    D_VERSION,
232         .d_flags =      D_NEEDGIANT,
233         .d_open =       netopen,
234         .d_close =      netclose,
235         .d_ioctl =      netioctl,
236         .d_name =       "net",
237         .d_kqfilter =   netkqfilter,
238 };
239 
240 static int
241 netopen(struct cdev *dev, int flag, int mode, struct thread *td)
242 {
243         return (0);
244 }
245 
246 static int
247 netclose(struct cdev *dev, int flags, int fmt, struct thread *td)
248 {
249         return (0);
250 }
251 
252 static int
253 netioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
254 {
255         struct ifnet *ifp;
256         int error, idx;
257 
258         /* only support interface specific ioctls */
259         if (IOCGROUP(cmd) != 'i')
260                 return (EOPNOTSUPP);
261         idx = dev2unit(dev);
262         if (idx == 0) {
263                 /*
264                  * special network device, not interface.
265                  */
266                 if (cmd == SIOCGIFCONF)
267                         return (ifconf(cmd, data));     /* XXX remove cmd */
268 #ifdef __amd64__
269                 if (cmd == SIOCGIFCONF32)
270                         return (ifconf(cmd, data));     /* XXX remove cmd */
271 #endif
272                 return (EOPNOTSUPP);
273         }
274 
275         ifp = ifnet_byindex(idx);
276         if (ifp == NULL)
277                 return (ENXIO);
278 
279         error = ifhwioctl(cmd, ifp, data, td);
280         if (error == ENOIOCTL)
281                 error = EOPNOTSUPP;
282         return (error);
283 }
284 
285 static int
286 netkqfilter(struct cdev *dev, struct knote *kn)
287 {
288         INIT_VNET_NET(curvnet);
289         struct knlist *klist;
290         struct ifnet *ifp;
291         int idx;
292 
293         switch (kn->kn_filter) {
294         case EVFILT_NETDEV:
295                 kn->kn_fop = &netdev_filtops;
296                 break;
297         default:
298                 return (EINVAL);
299         }
300 
301         idx = dev2unit(dev);
302         if (idx == 0) {
303                 klist = &V_ifklist;
304         } else {
305                 ifp = ifnet_byindex(idx);
306                 if (ifp == NULL)
307                         return (1);
308                 klist = &ifp->if_klist;
309         }
310 
311         kn->kn_hook = (caddr_t)klist;
312 
313         knlist_add(klist, kn, 0);
314 
315         return (0);
316 }
317 
318 static void
319 filt_netdetach(struct knote *kn)
320 {
321         struct knlist *klist = (struct knlist *)kn->kn_hook;
322 
323         knlist_remove(klist, kn, 0);
324 }
325 
326 static int
327 filt_netdev(struct knote *kn, long hint)
328 {
329         struct knlist *klist = (struct knlist *)kn->kn_hook;
330 
331         /*
332          * Currently NOTE_EXIT is abused to indicate device detach.
333          */
334         if (hint == NOTE_EXIT) {
335                 kn->kn_data = NOTE_LINKINV;
336                 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
337                 knlist_remove_inevent(klist, kn);
338                 return (1);
339         }
340         if (hint != 0)
341                 kn->kn_data = hint;                     /* current status */
342         if (kn->kn_sfflags & hint)
343                 kn->kn_fflags |= hint;
344         return (kn->kn_fflags != 0);
345 }
346 
347 /*
348  * Network interface utility routines.
349  *
350  * Routines with ifa_ifwith* names take sockaddr *'s as
351  * parameters.
352  */
353 
354 /* ARGSUSED*/
355 static void
356 if_init(void *dummy __unused)
357 {
358         INIT_VNET_NET(curvnet);
359 
360         IFNET_LOCK_INIT();
361         TAILQ_INIT(&V_ifnet);
362         TAILQ_INIT(&V_ifg_head);
363         knlist_init(&V_ifklist, NULL, NULL, NULL, NULL);
364         if_grow();                              /* create initial table */
365         ifdev_setbyindex(0, make_dev(&net_cdevsw, 0, UID_ROOT, GID_WHEEL,
366             0600, "network"));
367         if_clone_init();
368 }
369 
370 static void
371 if_grow(void)
372 {
373         INIT_VNET_NET(curvnet);
374         u_int n;
375         struct ifindex_entry *e;
376 
377         V_if_indexlim <<= 1;
378         n = V_if_indexlim * sizeof(*e);
379         e = malloc(n, M_IFNET, M_WAITOK | M_ZERO);
380         if (V_ifindex_table != NULL) {
381                 memcpy((caddr_t)e, (caddr_t)V_ifindex_table, n/2);
382                 free((caddr_t)V_ifindex_table, M_IFNET);
383         }
384         V_ifindex_table = e;
385 }
386 
387 /*
388  * Allocate a struct ifnet and an index for an interface.  A layer 2
389  * common structure will also be allocated if an allocation routine is
390  * registered for the passed type.
391  */
392 struct ifnet*
393 if_alloc(u_char type)
394 {
395         INIT_VNET_NET(curvnet);
396         struct ifnet *ifp;
397 
398         ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO);
399 
400         /*
401          * Try to find an empty slot below if_index.  If we fail, take
402          * the next slot.
403          *
404          * XXX: should be locked!
405          */
406         for (ifp->if_index = 1; ifp->if_index <= V_if_index; ifp->if_index++) {
407                 if (ifnet_byindex(ifp->if_index) == NULL)
408                         break;
409         }
410         /* Catch if_index overflow. */
411         if (ifp->if_index < 1) {
412                 free(ifp, M_IFNET);
413                 return (NULL);
414         }
415         if (ifp->if_index > V_if_index)
416                 V_if_index = ifp->if_index;
417         if (V_if_index >= V_if_indexlim)
418                 if_grow();
419 
420         ifp->if_type = type;
421 
422         if (if_com_alloc[type] != NULL) {
423                 ifp->if_l2com = if_com_alloc[type](type, ifp);
424                 if (ifp->if_l2com == NULL) {
425                         free(ifp, M_IFNET);
426                         return (NULL);
427                 }
428         }
429         IFNET_WLOCK();
430         ifnet_setbyindex(ifp->if_index, ifp);
431         IFNET_WUNLOCK();
432         IF_ADDR_LOCK_INIT(ifp);
433 
434         return (ifp);
435 }
436 
437 /*
438  * Free the struct ifnet, the associated index, and the layer 2 common
439  * structure if needed.  All the work is done in if_free_type().
440  *
441  * Do not add code to this function!  Add it to if_free_type().
442  */
443 void
444 if_free(struct ifnet *ifp)
445 {
446 
447         if_free_type(ifp, ifp->if_type);
448 }
449 
450 /*
451  * Do the actual work of freeing a struct ifnet, associated index, and
452  * layer 2 common structure.  This version should only be called by
453  * intefaces that switch their type after calling if_alloc().
454  */
455 void
456 if_free_type(struct ifnet *ifp, u_char type)
457 {
458         INIT_VNET_NET(curvnet); /* ifp->if_vnet can be NULL here ! */
459 
460         if (ifp != ifnet_byindex(ifp->if_index)) {
461                 if_printf(ifp, "%s: value was not if_alloced, skipping\n",
462                     __func__);
463                 return;
464         }
465 
466         IFNET_WLOCK();
467         ifnet_setbyindex(ifp->if_index, NULL);
468 
469         /* XXX: should be locked with if_findindex() */
470         while (V_if_index > 0 && ifnet_byindex(V_if_index) == NULL)
471                 V_if_index--;
472         IFNET_WUNLOCK();
473 
474         if (if_com_free[type] != NULL)
475                 if_com_free[type](ifp->if_l2com, type);
476 
477         IF_ADDR_LOCK_DESTROY(ifp);
478         free(ifp, M_IFNET);
479 };
480 
481 /*
482  * Perform generic interface initalization tasks and attach the interface
483  * to the list of "active" interfaces.
484  *
485  * XXX:
486  *  - The decision to return void and thus require this function to
487  *    succeed is questionable.
488  *  - We do more initialization here then is probably a good idea.
489  *    Some of this should probably move to if_alloc().
490  *  - We should probably do more sanity checking.  For instance we don't
491  *    do anything to insure if_xname is unique or non-empty.
492  */
493 void
494 if_attach(struct ifnet *ifp)
495 {
496         INIT_VNET_NET(curvnet);
497         unsigned socksize, ifasize;
498         int namelen, masklen;
499         struct sockaddr_dl *sdl;
500         struct ifaddr *ifa;
501 
502         if (ifp->if_index == 0 || ifp != ifnet_byindex(ifp->if_index))
503                 panic ("%s: BUG: if_attach called without if_alloc'd input()\n",
504                     ifp->if_xname);
505 
506         TASK_INIT(&ifp->if_starttask, 0, if_start_deferred, ifp);
507         TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp);
508         IF_AFDATA_LOCK_INIT(ifp);
509         ifp->if_afdata_initialized = 0;
510 
511         TAILQ_INIT(&ifp->if_addrhead);
512         TAILQ_INIT(&ifp->if_prefixhead);
513         TAILQ_INIT(&ifp->if_multiaddrs);
514         TAILQ_INIT(&ifp->if_groups);
515 
516         if_addgroup(ifp, IFG_ALL);
517 
518         knlist_init(&ifp->if_klist, NULL, NULL, NULL, NULL);
519         getmicrotime(&ifp->if_lastchange);
520         ifp->if_data.ifi_epoch = time_uptime;
521         ifp->if_data.ifi_datalen = sizeof(struct if_data);
522 
523 #ifdef MAC
524         mac_ifnet_init(ifp);
525         mac_ifnet_create(ifp);
526 #endif
527 
528         ifdev_setbyindex(ifp->if_index, make_dev(&net_cdevsw,
529             ifp->if_index, UID_ROOT, GID_WHEEL, 0600, "%s/%s",
530             net_cdevsw.d_name, ifp->if_xname));
531         make_dev_alias(ifdev_byindex(ifp->if_index), "%s%d",
532             net_cdevsw.d_name, ifp->if_index);
533 
534         mtx_init(&ifp->if_snd.ifq_mtx, ifp->if_xname, "if send queue", MTX_DEF);
535 
536         /*
537          * create a Link Level name for this device
538          */
539         namelen = strlen(ifp->if_xname);
540         /*
541          * Always save enough space for any possiable name so we can do
542          * a rename in place later.
543          */
544         masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + IFNAMSIZ;
545         socksize = masklen + ifp->if_addrlen;
546         if (socksize < sizeof(*sdl))
547                 socksize = sizeof(*sdl);
548         socksize = roundup2(socksize, sizeof(long));
549         ifasize = sizeof(*ifa) + 2 * socksize;
550         ifa = malloc(ifasize, M_IFADDR, M_WAITOK | M_ZERO);
551         IFA_LOCK_INIT(ifa);
552         sdl = (struct sockaddr_dl *)(ifa + 1);
553         sdl->sdl_len = socksize;
554         sdl->sdl_family = AF_LINK;
555         bcopy(ifp->if_xname, sdl->sdl_data, namelen);
556         sdl->sdl_nlen = namelen;
557         sdl->sdl_index = ifp->if_index;
558         sdl->sdl_type = ifp->if_type;
559         ifp->if_addr = ifa;
560         ifa->ifa_ifp = ifp;
561         ifa->ifa_rtrequest = link_rtrequest;
562         ifa->ifa_addr = (struct sockaddr *)sdl;
563         sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
564         ifa->ifa_netmask = (struct sockaddr *)sdl;
565         sdl->sdl_len = masklen;
566         while (namelen != 0)
567                 sdl->sdl_data[--namelen] = 0xff;
568         ifa->ifa_refcnt = 1;
569         TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
570         ifp->if_broadcastaddr = NULL; /* reliably crash if used uninitialized */
571 
572         /*
573          * XXX: why do we warn about this? We're correcting it and most
574          * drivers just set the value the way we do.
575          */
576         if (ifp->if_snd.ifq_maxlen == 0) {
577                 if_printf(ifp, "XXX: driver didn't set ifq_maxlen\n");
578                 ifp->if_snd.ifq_maxlen = ifqmaxlen;
579         }
580         ifp->if_snd.altq_type = 0;
581         ifp->if_snd.altq_disc = NULL;
582         ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
583         ifp->if_snd.altq_tbr  = NULL;
584         ifp->if_snd.altq_ifp  = ifp;
585 
586         IFNET_WLOCK();
587         TAILQ_INSERT_TAIL(&V_ifnet, ifp, if_link);
588         IFNET_WUNLOCK();
589 
590         if (domain_init_status >= 2)
591                 if_attachdomain1(ifp);
592 
593         EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp);
594         devctl_notify("IFNET", ifp->if_xname, "ATTACH", NULL);
595 
596         /* Announce the interface. */
597         rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
598 
599         if (ifp->if_watchdog != NULL)
600                 if_printf(ifp,
601                     "WARNING: using obsoleted if_watchdog interface\n");
602         if (ifp->if_flags & IFF_NEEDSGIANT)
603                 if_printf(ifp,
604                     "WARNING: using obsoleted IFF_NEEDSGIANT flag\n");
605 }
606 
607 static void
608 if_attachdomain(void *dummy)
609 {
610         INIT_VNET_NET(curvnet);
611         struct ifnet *ifp;
612         int s;
613 
614         s = splnet();
615         TAILQ_FOREACH(ifp, &V_ifnet, if_link)
616                 if_attachdomain1(ifp);
617         splx(s);
618 }
619 SYSINIT(domainifattach, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_SECOND,
620     if_attachdomain, NULL);
621 
622 static void
623 if_attachdomain1(struct ifnet *ifp)
624 {
625         struct domain *dp;
626         int s;
627 
628         s = splnet();
629 
630         /*
631          * Since dp->dom_ifattach calls malloc() with M_WAITOK, we
632          * cannot lock ifp->if_afdata initialization, entirely.
633          */
634         if (IF_AFDATA_TRYLOCK(ifp) == 0) {
635                 splx(s);
636                 return;
637         }
638         if (ifp->if_afdata_initialized >= domain_init_status) {
639                 IF_AFDATA_UNLOCK(ifp);
640                 splx(s);
641                 printf("if_attachdomain called more than once on %s\n",
642                     ifp->if_xname);
643                 return;
644         }
645         ifp->if_afdata_initialized = domain_init_status;
646         IF_AFDATA_UNLOCK(ifp);
647 
648         /* address family dependent data region */
649         bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
650         for (dp = domains; dp; dp = dp->dom_next) {
651                 if (dp->dom_ifattach)
652                         ifp->if_afdata[dp->dom_family] =
653                             (*dp->dom_ifattach)(ifp);
654         }
655 
656         splx(s);
657 }
658 
659 /*
660  * Remove any unicast or broadcast network addresses from an interface.
661  */
662 void
663 if_purgeaddrs(struct ifnet *ifp)
664 {
665         struct ifaddr *ifa, *next;
666 
667         TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
668                 if (ifa->ifa_addr->sa_family == AF_LINK)
669                         continue;
670 #ifdef INET
671                 /* XXX: Ugly!! ad hoc just for INET */
672                 if (ifa->ifa_addr->sa_family == AF_INET) {
673                         struct ifaliasreq ifr;
674 
675                         bzero(&ifr, sizeof(ifr));
676                         ifr.ifra_addr = *ifa->ifa_addr;
677                         if (ifa->ifa_dstaddr)
678                                 ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
679                         if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
680                             NULL) == 0)
681                                 continue;
682                 }
683 #endif /* INET */
684 #ifdef INET6
685                 if (ifa->ifa_addr->sa_family == AF_INET6) {
686                         in6_purgeaddr(ifa);
687                         /* ifp_addrhead is already updated */
688                         continue;
689                 }
690 #endif /* INET6 */
691                 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
692                 IFAFREE(ifa);
693         }
694 }
695 
696 /*
697  * Remove any multicast network addresses from an interface.
698  */
699 void
700 if_purgemaddrs(struct ifnet *ifp)
701 {
702         struct ifmultiaddr *ifma;
703         struct ifmultiaddr *next;
704 
705         IF_ADDR_LOCK(ifp);
706         TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
707                 if_delmulti_locked(ifp, ifma, 1);
708         IF_ADDR_UNLOCK(ifp);
709 }
710 
711 /*
712  * Detach an interface, removing it from the
713  * list of "active" interfaces.
714  *
715  * XXXRW: There are some significant questions about event ordering, and
716  * how to prevent things from starting to use the interface during detach.
717  */
718 void
719 if_detach(struct ifnet *ifp)
720 {
721         INIT_VNET_NET(ifp->if_vnet);
722         struct ifaddr *ifa;
723         struct radix_node_head  *rnh;
724         int s;
725         int i;
726         struct domain *dp;
727         struct ifnet *iter;
728         int found = 0;
729 
730         IFNET_WLOCK();
731         TAILQ_FOREACH(iter, &V_ifnet, if_link)
732                 if (iter == ifp) {
733                         TAILQ_REMOVE(&V_ifnet, ifp, if_link);
734                         found = 1;
735                         break;
736                 }
737         IFNET_WUNLOCK();
738         if (!found)
739                 return;
740 
741         /*
742          * Remove/wait for pending events.
743          */
744         taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
745 
746         /*
747          * Remove routes and flush queues.
748          */
749         s = splnet();
750         if_down(ifp);
751 #ifdef ALTQ
752         if (ALTQ_IS_ENABLED(&ifp->if_snd))
753                 altq_disable(&ifp->if_snd);
754         if (ALTQ_IS_ATTACHED(&ifp->if_snd))
755                 altq_detach(&ifp->if_snd);
756 #endif
757 
758         if_purgeaddrs(ifp);
759 
760 #ifdef INET
761         in_ifdetach(ifp);
762 #endif
763 
764 #ifdef INET6
765         /*
766          * Remove all IPv6 kernel structs related to ifp.  This should be done
767          * before removing routing entries below, since IPv6 interface direct
768          * routes are expected to be removed by the IPv6-specific kernel API.
769          * Otherwise, the kernel will detect some inconsistency and bark it.
770          */
771         in6_ifdetach(ifp);
772 #endif
773         if_purgemaddrs(ifp);
774 
775         /*
776          * Remove link ifaddr pointer and maybe decrement if_index.
777          * Clean up all addresses.
778          */
779         ifp->if_addr = NULL;
780         destroy_dev(ifdev_byindex(ifp->if_index));
781         ifdev_setbyindex(ifp->if_index, NULL);  
782 
783         /* We can now free link ifaddr. */
784         if (!TAILQ_EMPTY(&ifp->if_addrhead)) {
785                 ifa = TAILQ_FIRST(&ifp->if_addrhead);
786                 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
787                 IFAFREE(ifa);
788         }
789 
790         /*
791          * Delete all remaining routes using this interface
792          * Unfortuneatly the only way to do this is to slog through
793          * the entire routing table looking for routes which point
794          * to this interface...oh well...
795          */
796         for (i = 1; i <= AF_MAX; i++) {
797             int j;
798             for (j = 0; j < rt_numfibs; j++) {
799                 if ((rnh = V_rt_tables[j][i]) == NULL)
800                         continue;
801                 RADIX_NODE_HEAD_LOCK(rnh);
802                 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
803                 RADIX_NODE_HEAD_UNLOCK(rnh);
804             }
805         }
806 
807         /* Announce that the interface is gone. */
808         rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
809         EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
810         devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL);
811 
812         IF_AFDATA_LOCK(ifp);
813         for (dp = domains; dp; dp = dp->dom_next) {
814                 if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
815                         (*dp->dom_ifdetach)(ifp,
816                             ifp->if_afdata[dp->dom_family]);
817         }
818         IF_AFDATA_UNLOCK(ifp);
819 
820 #ifdef MAC
821         mac_ifnet_destroy(ifp);
822 #endif /* MAC */
823         KNOTE_UNLOCKED(&ifp->if_klist, NOTE_EXIT);
824         knlist_clear(&ifp->if_klist, 0);
825         knlist_destroy(&ifp->if_klist);
826         mtx_destroy(&ifp->if_snd.ifq_mtx);
827         IF_AFDATA_DESTROY(ifp);
828         splx(s);
829 }
830 
831 /*
832  * Add a group to an interface
833  */
834 int
835 if_addgroup(struct ifnet *ifp, const char *groupname)
836 {
837         INIT_VNET_NET(ifp->if_vnet);
838         struct ifg_list         *ifgl;
839         struct ifg_group        *ifg = NULL;
840         struct ifg_member       *ifgm;
841 
842         if (groupname[0] && groupname[strlen(groupname) - 1] >= '' &&
843             groupname[strlen(groupname) - 1] <= '9')
844                 return (EINVAL);
845 
846         IFNET_WLOCK();
847         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
848                 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) {
849                         IFNET_WUNLOCK();
850                         return (EEXIST);
851                 }
852 
853         if ((ifgl = (struct ifg_list *)malloc(sizeof(struct ifg_list), M_TEMP,
854             M_NOWAIT)) == NULL) {
855                 IFNET_WUNLOCK();
856                 return (ENOMEM);
857         }
858 
859         if ((ifgm = (struct ifg_member *)malloc(sizeof(struct ifg_member),
860             M_TEMP, M_NOWAIT)) == NULL) {
861                 free(ifgl, M_TEMP);
862                 IFNET_WUNLOCK();
863                 return (ENOMEM);
864         }
865 
866         TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next)
867                 if (!strcmp(ifg->ifg_group, groupname))
868                         break;
869 
870         if (ifg == NULL) {
871                 if ((ifg = (struct ifg_group *)malloc(sizeof(struct ifg_group),
872                     M_TEMP, M_NOWAIT)) == NULL) {
873                         free(ifgl, M_TEMP);
874                         free(ifgm, M_TEMP);
875                         IFNET_WUNLOCK();
876                         return (ENOMEM);
877                 }
878                 strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
879                 ifg->ifg_refcnt = 0;
880                 TAILQ_INIT(&ifg->ifg_members);
881                 EVENTHANDLER_INVOKE(group_attach_event, ifg);
882                 TAILQ_INSERT_TAIL(&V_ifg_head, ifg, ifg_next);
883         }
884 
885         ifg->ifg_refcnt++;
886         ifgl->ifgl_group = ifg;
887         ifgm->ifgm_ifp = ifp;
888 
889         IF_ADDR_LOCK(ifp);
890         TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
891         TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
892         IF_ADDR_UNLOCK(ifp);
893 
894         IFNET_WUNLOCK();
895 
896         EVENTHANDLER_INVOKE(group_change_event, groupname);
897 
898         return (0);
899 }
900 
901 /*
902  * Remove a group from an interface
903  */
904 int
905 if_delgroup(struct ifnet *ifp, const char *groupname)
906 {
907         INIT_VNET_NET(ifp->if_vnet);
908         struct ifg_list         *ifgl;
909         struct ifg_member       *ifgm;
910 
911         IFNET_WLOCK();
912         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
913                 if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
914                         break;
915         if (ifgl == NULL) {
916                 IFNET_WUNLOCK();
917                 return (ENOENT);
918         }
919 
920         IF_ADDR_LOCK(ifp);
921         TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
922         IF_ADDR_UNLOCK(ifp);
923 
924         TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
925                 if (ifgm->ifgm_ifp == ifp)
926                         break;
927 
928         if (ifgm != NULL) {
929                 TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
930                 free(ifgm, M_TEMP);
931         }
932 
933         if (--ifgl->ifgl_group->ifg_refcnt == 0) {
934                 TAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_next);
935                 EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group);
936                 free(ifgl->ifgl_group, M_TEMP);
937         }
938         IFNET_WUNLOCK();
939 
940         free(ifgl, M_TEMP);
941 
942         EVENTHANDLER_INVOKE(group_change_event, groupname);
943 
944         return (0);
945 }
946 
947 /*
948  * Stores all groups from an interface in memory pointed
949  * to by data
950  */
951 static int
952 if_getgroup(struct ifgroupreq *data, struct ifnet *ifp)
953 {
954         int                      len, error;
955         struct ifg_list         *ifgl;
956         struct ifg_req           ifgrq, *ifgp;
957         struct ifgroupreq       *ifgr = data;
958 
959         if (ifgr->ifgr_len == 0) {
960                 IF_ADDR_LOCK(ifp);
961                 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
962                         ifgr->ifgr_len += sizeof(struct ifg_req);
963                 IF_ADDR_UNLOCK(ifp);
964                 return (0);
965         }
966 
967         len = ifgr->ifgr_len;
968         ifgp = ifgr->ifgr_groups;
969         /* XXX: wire */
970         IF_ADDR_LOCK(ifp);
971         TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
972                 if (len < sizeof(ifgrq)) {
973                         IF_ADDR_UNLOCK(ifp);
974                         return (EINVAL);
975                 }
976                 bzero(&ifgrq, sizeof ifgrq);
977                 strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
978                     sizeof(ifgrq.ifgrq_group));
979                 if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) {
980                         IF_ADDR_UNLOCK(ifp);
981                         return (error);
982                 }
983                 len -= sizeof(ifgrq);
984                 ifgp++;
985         }
986         IF_ADDR_UNLOCK(ifp);
987 
988         return (0);
989 }
990 
991 /*
992  * Stores all members of a group in memory pointed to by data
993  */
994 static int
995 if_getgroupmembers(struct ifgroupreq *data)
996 {
997         INIT_VNET_NET(curvnet);
998         struct ifgroupreq       *ifgr = data;
999         struct ifg_group        *ifg;
1000         struct ifg_member       *ifgm;
1001         struct ifg_req           ifgrq, *ifgp;
1002         int                      len, error;
1003 
1004         IFNET_RLOCK();
1005         TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next)
1006                 if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
1007                         break;
1008         if (ifg == NULL) {
1009                 IFNET_RUNLOCK();
1010                 return (ENOENT);
1011         }
1012 
1013         if (ifgr->ifgr_len == 0) {
1014                 TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
1015                         ifgr->ifgr_len += sizeof(ifgrq);
1016                 IFNET_RUNLOCK();
1017                 return (0);
1018         }
1019 
1020         len = ifgr->ifgr_len;
1021         ifgp = ifgr->ifgr_groups;
1022         TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
1023                 if (len < sizeof(ifgrq)) {
1024                         IFNET_RUNLOCK();
1025                         return (EINVAL);
1026                 }
1027                 bzero(&ifgrq, sizeof ifgrq);
1028                 strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
1029                     sizeof(ifgrq.ifgrq_member));
1030                 if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) {
1031                         IFNET_RUNLOCK();
1032                         return (error);
1033                 }
1034                 len -= sizeof(ifgrq);
1035                 ifgp++;
1036         }
1037         IFNET_RUNLOCK();
1038 
1039         return (0);
1040 }
1041 
1042 /*
1043  * Delete Routes for a Network Interface
1044  *
1045  * Called for each routing entry via the rnh->rnh_walktree() call above
1046  * to delete all route entries referencing a detaching network interface.
1047  *
1048  * Arguments:
1049  *      rn      pointer to node in the routing table
1050  *      arg     argument passed to rnh->rnh_walktree() - detaching interface
1051  *
1052  * Returns:
1053  *      0       successful
1054  *      errno   failed - reason indicated
1055  *
1056  */
1057 static int
1058 if_rtdel(struct radix_node *rn, void *arg)
1059 {
1060         struct rtentry  *rt = (struct rtentry *)rn;
1061         struct ifnet    *ifp = arg;
1062         int             err;
1063 
1064         if (rt->rt_ifp == ifp) {
1065 
1066                 /*
1067                  * Protect (sorta) against walktree recursion problems
1068                  * with cloned routes
1069                  */
1070                 if ((rt->rt_flags & RTF_UP) == 0)
1071                         return (0);
1072 
1073                 err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
1074                                 rt_mask(rt), rt->rt_flags,
1075                                 (struct rtentry **) NULL, rt->rt_fibnum);
1076                 if (err) {
1077                         log(LOG_WARNING, "if_rtdel: error %d\n", err);
1078                 }
1079         }
1080 
1081         return (0);
1082 }
1083 
1084 /*
1085  * XXX: Because sockaddr_dl has deeper structure than the sockaddr
1086  * structs used to represent other address families, it is necessary
1087  * to perform a different comparison.
1088  */
1089 
1090 #define sa_equal(a1, a2)        \
1091         (bcmp((a1), (a2), ((a1))->sa_len) == 0)
1092 
1093 #define sa_dl_equal(a1, a2)     \
1094         ((((struct sockaddr_dl *)(a1))->sdl_len ==                      \
1095          ((struct sockaddr_dl *)(a2))->sdl_len) &&                      \
1096          (bcmp(LLADDR((struct sockaddr_dl *)(a1)),                      \
1097                LLADDR((struct sockaddr_dl *)(a2)),                      \
1098                ((struct sockaddr_dl *)(a1))->sdl_alen) == 0))
1099 
1100 /*
1101  * Locate an interface based on a complete address.
1102  */
1103 /*ARGSUSED*/
1104 struct ifaddr *
1105 ifa_ifwithaddr(struct sockaddr *addr)
1106 {
1107         INIT_VNET_NET(curvnet);
1108         struct ifnet *ifp;
1109         struct ifaddr *ifa;
1110 
1111         IFNET_RLOCK();
1112         TAILQ_FOREACH(ifp, &V_ifnet, if_link)
1113