Home | History | Annotate | Line # | Download | only in net
if.c revision 1.72
      1 /*	$NetBSD: if.c,v 1.72 2000/10/04 21:12:40 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by William Studnemund and Jason R. Thorpe.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
     41  * All rights reserved.
     42  *
     43  * Redistribution and use in source and binary forms, with or without
     44  * modification, are permitted provided that the following conditions
     45  * are met:
     46  * 1. Redistributions of source code must retain the above copyright
     47  *    notice, this list of conditions and the following disclaimer.
     48  * 2. Redistributions in binary form must reproduce the above copyright
     49  *    notice, this list of conditions and the following disclaimer in the
     50  *    documentation and/or other materials provided with the distribution.
     51  * 3. Neither the name of the project nor the names of its contributors
     52  *    may be used to endorse or promote products derived from this software
     53  *    without specific prior written permission.
     54  *
     55  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     56  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     58  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     59  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     60  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     61  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     63  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     64  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     65  * SUCH DAMAGE.
     66  */
     67 
     68 /*
     69  * Copyright (c) 1980, 1986, 1993
     70  *	The Regents of the University of California.  All rights reserved.
     71  *
     72  * Redistribution and use in source and binary forms, with or without
     73  * modification, are permitted provided that the following conditions
     74  * are met:
     75  * 1. Redistributions of source code must retain the above copyright
     76  *    notice, this list of conditions and the following disclaimer.
     77  * 2. Redistributions in binary form must reproduce the above copyright
     78  *    notice, this list of conditions and the following disclaimer in the
     79  *    documentation and/or other materials provided with the distribution.
     80  * 3. All advertising materials mentioning features or use of this software
     81  *    must display the following acknowledgement:
     82  *	This product includes software developed by the University of
     83  *	California, Berkeley and its contributors.
     84  * 4. Neither the name of the University nor the names of its contributors
     85  *    may be used to endorse or promote products derived from this software
     86  *    without specific prior written permission.
     87  *
     88  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     89  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     90  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     91  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     92  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     93  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     94  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     95  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     96  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     97  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     98  * SUCH DAMAGE.
     99  *
    100  *	@(#)if.c	8.5 (Berkeley) 1/9/95
    101  */
    102 
    103 #include "opt_inet.h"
    104 
    105 #include "opt_compat_linux.h"
    106 #include "opt_compat_svr4.h"
    107 #include "opt_compat_43.h"
    108 #include "opt_atalk.h"
    109 
    110 #include <sys/param.h>
    111 #include <sys/mbuf.h>
    112 #include <sys/systm.h>
    113 #include <sys/callout.h>
    114 #include <sys/proc.h>
    115 #include <sys/socket.h>
    116 #include <sys/socketvar.h>
    117 #include <sys/domain.h>
    118 #include <sys/protosw.h>
    119 #include <sys/kernel.h>
    120 #include <sys/ioctl.h>
    121 
    122 #include <net/if.h>
    123 #include <net/if_dl.h>
    124 #include <net/if_ether.h>
    125 #include <net/if_ieee80211.h>
    126 #include <net/if_types.h>
    127 #include <net/radix.h>
    128 #include <net/route.h>
    129 #ifdef NETATALK
    130 #include <netatalk/at_extern.h>
    131 #include <netatalk/at.h>
    132 #endif
    133 
    134 #ifdef INET6
    135 /*XXX*/
    136 #include <netinet/in.h>
    137 #include <netinet6/in6_var.h>
    138 #endif
    139 
    140 int	ifqmaxlen = IFQ_MAXLEN;
    141 struct	callout if_slowtimo_ch;
    142 
    143 #ifdef INET6
    144 /*
    145  * XXX: declare here to avoid to include many inet6 related files..
    146  * should be more generalized?
    147  */
    148 extern void nd6_setmtu __P((struct ifnet *));
    149 #endif
    150 
    151 int	if_rt_walktree __P((struct radix_node *, void *));
    152 
    153 struct if_clone *if_clone_lookup __P((const char *, int *));
    154 int if_clone_list __P((struct if_clonereq *));
    155 
    156 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
    157 int if_cloners_count;
    158 
    159 /*
    160  * Network interface utility routines.
    161  *
    162  * Routines with ifa_ifwith* names take sockaddr *'s as
    163  * parameters.
    164  */
    165 void
    166 ifinit()
    167 {
    168 
    169 	callout_init(&if_slowtimo_ch);
    170 	if_slowtimo(NULL);
    171 }
    172 
    173 /*
    174  * Null routines used while an interface is going away.  These routines
    175  * just return an error.
    176  */
    177 
    178 int
    179 if_nulloutput(ifp, m, so, rt)
    180 	struct ifnet *ifp;
    181 	struct mbuf *m;
    182 	struct sockaddr *so;
    183 	struct rtentry *rt;
    184 {
    185 
    186 	return (ENXIO);
    187 }
    188 
    189 void
    190 if_nullinput(ifp, m)
    191 	struct ifnet *ifp;
    192 	struct mbuf *m;
    193 {
    194 
    195 	/* Nothing. */
    196 }
    197 
    198 void
    199 if_nullstart(ifp)
    200 	struct ifnet *ifp;
    201 {
    202 
    203 	/* Nothing. */
    204 }
    205 
    206 int
    207 if_nullioctl(ifp, cmd, data)
    208 	struct ifnet *ifp;
    209 	u_long cmd;
    210 	caddr_t data;
    211 {
    212 
    213 	return (ENXIO);
    214 }
    215 
    216 int
    217 if_nullreset(ifp)
    218 	struct ifnet *ifp;
    219 {
    220 
    221 	return (ENXIO);
    222 }
    223 
    224 void
    225 if_nullwatchdog(ifp)
    226 	struct ifnet *ifp;
    227 {
    228 
    229 	/* Nothing. */
    230 }
    231 
    232 void
    233 if_nulldrain(ifp)
    234 	struct ifnet *ifp;
    235 {
    236 
    237 	/* Nothing. */
    238 }
    239 
    240 int if_index = 0;
    241 struct ifaddr **ifnet_addrs = NULL;
    242 struct ifnet **ifindex2ifnet = NULL;
    243 
    244 /*
    245  * Attach an interface to the
    246  * list of "active" interfaces.
    247  */
    248 void
    249 if_attach(ifp)
    250 	struct ifnet *ifp;
    251 {
    252 	unsigned socksize, ifasize;
    253 	int namelen, masklen;
    254 	struct sockaddr_dl *sdl;
    255 	struct ifaddr *ifa;
    256 	static size_t if_indexlim = 8;
    257 
    258 	if (if_index == 0)
    259 		TAILQ_INIT(&ifnet);
    260 	TAILQ_INIT(&ifp->if_addrlist);
    261 	TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
    262 	ifp->if_index = ++if_index;
    263 
    264 	/*
    265 	 * We have some arrays that should be indexed by if_index.
    266 	 * since if_index will grow dynamically, they should grow too.
    267 	 *	struct ifadd **ifnet_addrs
    268 	 *	struct ifnet **ifindex2ifnet
    269 	 */
    270 	if (ifnet_addrs == 0 || ifindex2ifnet == 0 ||
    271 	    ifp->if_index >= if_indexlim) {
    272 		size_t n;
    273 		caddr_t q;
    274 
    275 		while (ifp->if_index >= if_indexlim)
    276 			if_indexlim <<= 1;
    277 
    278 		/* grow ifnet_addrs */
    279 		n = if_indexlim * sizeof(ifa);
    280 		q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
    281 		bzero(q, n);
    282 		if (ifnet_addrs) {
    283 			bcopy((caddr_t)ifnet_addrs, q, n/2);
    284 			free((caddr_t)ifnet_addrs, M_IFADDR);
    285 		}
    286 		ifnet_addrs = (struct ifaddr **)q;
    287 
    288 		/* grow ifindex2ifnet */
    289 		n = if_indexlim * sizeof(struct ifnet *);
    290 		q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
    291 		bzero(q, n);
    292 		if (ifindex2ifnet) {
    293 			bcopy((caddr_t)ifindex2ifnet, q, n/2);
    294 			free((caddr_t)ifindex2ifnet, M_IFADDR);
    295 		}
    296 		ifindex2ifnet = (struct ifnet **)q;
    297 	}
    298 
    299 	ifindex2ifnet[ifp->if_index] = ifp;
    300 
    301 	/*
    302 	 * create a Link Level name for this device
    303 	 */
    304 	namelen = strlen(ifp->if_xname);
    305 	masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
    306 	socksize = masklen + ifp->if_addrlen;
    307 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
    308 	if (socksize < sizeof(*sdl))
    309 		socksize = sizeof(*sdl);
    310 	socksize = ROUNDUP(socksize);
    311 	ifasize = sizeof(*ifa) + 2 * socksize;
    312 	ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
    313 	bzero((caddr_t)ifa, ifasize);
    314 	sdl = (struct sockaddr_dl *)(ifa + 1);
    315 	sdl->sdl_len = socksize;
    316 	sdl->sdl_family = AF_LINK;
    317 	bcopy(ifp->if_xname, sdl->sdl_data, namelen);
    318 	sdl->sdl_nlen = namelen;
    319 	sdl->sdl_index = ifp->if_index;
    320 	sdl->sdl_type = ifp->if_type;
    321 	ifnet_addrs[ifp->if_index] = ifa;
    322 	IFAREF(ifa);
    323 	ifa->ifa_ifp = ifp;
    324 	ifa->ifa_rtrequest = link_rtrequest;
    325 	TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
    326 	IFAREF(ifa);
    327 	ifa->ifa_addr = (struct sockaddr *)sdl;
    328 	ifp->if_sadl = sdl;
    329 	sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
    330 	ifa->ifa_netmask = (struct sockaddr *)sdl;
    331 	sdl->sdl_len = masklen;
    332 	while (namelen != 0)
    333 		sdl->sdl_data[--namelen] = 0xff;
    334 	if (ifp->if_snd.ifq_maxlen == 0)
    335 	    ifp->if_snd.ifq_maxlen = ifqmaxlen;
    336 	ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
    337 
    338 	ifp->if_link_state = LINK_STATE_UNKNOWN;
    339 
    340 	/* Announce the interface. */
    341 	rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
    342 }
    343 
    344 /*
    345  * Deactivate an interface.  This points all of the procedure
    346  * handles at error stubs.  May be called from interrupt context.
    347  */
    348 void
    349 if_deactivate(ifp)
    350 	struct ifnet *ifp;
    351 {
    352 	int s;
    353 
    354 	s = splimp();
    355 
    356 	ifp->if_output	 = if_nulloutput;
    357 	ifp->if_input	 = if_nullinput;
    358 	ifp->if_start	 = if_nullstart;
    359 	ifp->if_ioctl	 = if_nullioctl;
    360 	ifp->if_reset	 = if_nullreset;
    361 	ifp->if_watchdog = if_nullwatchdog;
    362 	ifp->if_drain	 = if_nulldrain;
    363 
    364 	/* No more packets may be enqueued. */
    365 	ifp->if_snd.ifq_maxlen = 0;
    366 
    367 	splx(s);
    368 }
    369 
    370 /*
    371  * Detach an interface from the list of "active" interfaces,
    372  * freeing any resources as we go along.
    373  *
    374  * NOTE: This routine must be called with a valid thread context,
    375  * as it may block.
    376  */
    377 void
    378 if_detach(ifp)
    379 	struct ifnet *ifp;
    380 {
    381 	struct socket so;
    382 	struct ifaddr *ifa;
    383 #ifdef IFAREF_DEBUG
    384 	struct ifaddr *last_ifa = NULL;
    385 #endif
    386 	struct domain *dp;
    387 	struct protosw *pr;
    388 	struct radix_node_head *rnh;
    389 	int s, i, family, purged;
    390 
    391 	/*
    392 	 * XXX It's kind of lame that we have to have the
    393 	 * XXX socket structure...
    394 	 */
    395 	memset(&so, 0, sizeof(so));
    396 
    397 	s = splimp();
    398 
    399 	/*
    400 	 * Do an if_down() to give protocols a chance to do something.
    401 	 */
    402 	if_down(ifp);
    403 
    404 	/*
    405 	 * Rip all the addresses off the interface.  This should make
    406 	 * all of the routes go away.
    407 	 */
    408 	while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
    409 		family = ifa->ifa_addr->sa_family;
    410 #ifdef IFAREF_DEBUG
    411 		printf("if_detach: ifaddr %p, family %d, refcnt %d\n",
    412 		    ifa, family, ifa->ifa_refcnt);
    413 		if (last_ifa != NULL && ifa == last_ifa)
    414 			panic("if_detach: loop detected");
    415 		last_ifa = ifa;
    416 #endif
    417 		if (family == AF_LINK) {
    418 			rtinit(ifa, RTM_DELETE, 0);
    419 			TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
    420 			IFAFREE(ifa);
    421 		} else {
    422 			dp = pffinddomain(family);
    423 #ifdef DIAGNOSTIC
    424 			if (dp == NULL)
    425 				panic("if_detach: no domain for AF %d\n",
    426 				    family);
    427 #endif
    428 			purged = 0;
    429 			for (pr = dp->dom_protosw;
    430 			     pr < dp->dom_protoswNPROTOSW; pr++) {
    431 				so.so_proto = pr;
    432 				if (pr->pr_usrreq != NULL) {
    433 					(void) (*pr->pr_usrreq)(&so,
    434 					    PRU_PURGEIF, NULL, NULL,
    435 					    (struct mbuf *) ifp, curproc);
    436 					purged = 1;
    437 				}
    438 			}
    439 			if (purged == 0) {
    440 				/*
    441 				 * XXX What's really the best thing to do
    442 				 * XXX here?  --thorpej (at) netbsd.org
    443 				 */
    444 				printf("if_detach: WARNING: AF %d not purged\n",
    445 				    family);
    446 			}
    447 		}
    448 	}
    449 
    450 	/* Walk the routing table looking for straglers. */
    451 	for (i = 0; i <= AF_MAX; i++) {
    452 		if ((rnh = rt_tables[i]) != NULL)
    453 			(void) (*rnh->rnh_walktree)(rnh, if_rt_walktree, ifp);
    454 	}
    455 
    456 	IFAFREE(ifnet_addrs[ifp->if_index]);
    457 	ifnet_addrs[ifp->if_index] = NULL;
    458 
    459 	/* Announce that the interface is gone. */
    460 	rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
    461 
    462 	TAILQ_REMOVE(&ifnet, ifp, if_list);
    463 
    464 	splx(s);
    465 }
    466 
    467 /*
    468  * Callback for a radix tree walk to delete all references to an
    469  * ifnet.
    470  */
    471 int
    472 if_rt_walktree(rn, v)
    473 	struct radix_node *rn;
    474 	void *v;
    475 {
    476 	struct ifnet *ifp = (struct ifnet *)v;
    477 	struct rtentry *rt = (struct rtentry *)rn;
    478 	int error;
    479 
    480 	if (rt->rt_ifp == ifp) {
    481 		/* Delete the entry. */
    482 		error = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
    483 		    rt_mask(rt), rt->rt_flags, NULL);
    484 		if (error)
    485 			printf("%s: warning: unable to delete rtentry @ %p, "
    486 			    "error = %d\n", ifp->if_xname, rt, error);
    487 	}
    488 	return (0);
    489 }
    490 
    491 /*
    492  * Create a clone network interface.
    493  */
    494 int
    495 if_clone_create(name)
    496 	const char *name;
    497 {
    498 	struct if_clone *ifc;
    499 	int unit;
    500 
    501 	ifc = if_clone_lookup(name, &unit);
    502 	if (ifc == NULL)
    503 		return (EINVAL);
    504 
    505 	if (ifunit(name) != NULL)
    506 		return (EEXIST);
    507 
    508 	return ((*ifc->ifc_create)(ifc, unit));
    509 }
    510 
    511 /*
    512  * Destroy a clone network interface.
    513  */
    514 int
    515 if_clone_destroy(name)
    516 	const char *name;
    517 {
    518 	struct if_clone *ifc;
    519 	struct ifnet *ifp;
    520 
    521 	ifc = if_clone_lookup(name, NULL);
    522 	if (ifc == NULL)
    523 		return (EINVAL);
    524 
    525 	ifp = ifunit(name);
    526 	if (ifp == NULL)
    527 		return (ENXIO);
    528 
    529 	if (ifc->ifc_destroy == NULL)
    530 		return (EOPNOTSUPP);
    531 
    532 	(*ifc->ifc_destroy)(ifp);
    533 	return (0);
    534 }
    535 
    536 /*
    537  * Look up a network interface cloner.
    538  */
    539 struct if_clone *
    540 if_clone_lookup(name, unitp)
    541 	const char *name;
    542 	int *unitp;
    543 {
    544 	struct if_clone *ifc;
    545 	const char *cp;
    546 	int i;
    547 
    548 	for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
    549 		for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
    550 			if (ifc->ifc_name[i] != *cp)
    551 				goto next_ifc;
    552 		}
    553 		goto found_name;
    554  next_ifc:
    555 		ifc = LIST_NEXT(ifc, ifc_list);
    556 	}
    557 
    558 	/* No match. */
    559 	return (NULL);
    560 
    561  found_name:
    562 	for (i = 0; *cp != '\0'; cp++) {
    563 		if (*cp < '0' || *cp > '9') {
    564 			/* Bogus unit number. */
    565 			return (NULL);
    566 		}
    567 		i = (i * 10) + (*cp - '0');
    568 	}
    569 
    570 	if (unitp != NULL)
    571 		*unitp = i;
    572 	return (ifc);
    573 }
    574 
    575 /*
    576  * Register a network interface cloner.
    577  */
    578 void
    579 if_clone_attach(ifc)
    580 	struct if_clone *ifc;
    581 {
    582 
    583 	LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
    584 	if_cloners_count++;
    585 }
    586 
    587 /*
    588  * Unregister a network interface cloner.
    589  */
    590 void
    591 if_clone_detach(ifc)
    592 	struct if_clone *ifc;
    593 {
    594 
    595 	LIST_REMOVE(ifc, ifc_list);
    596 	if_cloners_count--;
    597 }
    598 
    599 /*
    600  * Provide list of interface cloners to userspace.
    601  */
    602 int
    603 if_clone_list(ifcr)
    604 	struct if_clonereq *ifcr;
    605 {
    606 	char outbuf[IFNAMSIZ], *dst;
    607 	struct if_clone *ifc;
    608 	int count, error = 0;
    609 
    610 	ifcr->ifcr_total = if_cloners_count;
    611 	if ((dst = ifcr->ifcr_buffer) == NULL) {
    612 		/* Just asking how many there are. */
    613 		return (0);
    614 	}
    615 
    616 	if (ifcr->ifcr_count < 0)
    617 		return (EINVAL);
    618 
    619 	count = (if_cloners_count < ifcr->ifcr_count) ?
    620 	    if_cloners_count : ifcr->ifcr_count;
    621 
    622 	for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
    623 	     ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
    624 		strncpy(outbuf, ifc->ifc_name, IFNAMSIZ);
    625 		outbuf[IFNAMSIZ - 1] = '\0';	/* sanity */
    626 		error = copyout(outbuf, dst, IFNAMSIZ);
    627 		if (error)
    628 			break;
    629 	}
    630 
    631 	return (error);
    632 }
    633 
    634 /*
    635  * Locate an interface based on a complete address.
    636  */
    637 /*ARGSUSED*/
    638 struct ifaddr *
    639 ifa_ifwithaddr(addr)
    640 	struct sockaddr *addr;
    641 {
    642 	struct ifnet *ifp;
    643 	struct ifaddr *ifa;
    644 
    645 #define	equal(a1, a2) \
    646   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
    647 
    648 	for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
    649 	     ifp = TAILQ_NEXT(ifp, if_list)) {
    650 		if (ifp->if_output == if_nulloutput)
    651 			continue;
    652 		for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
    653 		     ifa = TAILQ_NEXT(ifa, ifa_list)) {
    654 			if (ifa->ifa_addr->sa_family != addr->sa_family)
    655 				continue;
    656 			if (equal(addr, ifa->ifa_addr))
    657 				return (ifa);
    658 			if ((ifp->if_flags & IFF_BROADCAST) &&
    659 			    ifa->ifa_broadaddr &&
    660 			    /* IP6 doesn't have broadcast */
    661 			    ifa->ifa_broadaddr->sa_len != 0 &&
    662 			    equal(ifa->ifa_broadaddr, addr))
    663 				return (ifa);
    664 		}
    665 	}
    666 	return (NULL);
    667 }
    668 
    669 /*
    670  * Locate the point to point interface with a given destination address.
    671  */
    672 /*ARGSUSED*/
    673 struct ifaddr *
    674 ifa_ifwithdstaddr(addr)
    675 	struct sockaddr *addr;
    676 {
    677 	struct ifnet *ifp;
    678 	struct ifaddr *ifa;
    679 
    680 	for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
    681 	     ifp = TAILQ_NEXT(ifp, if_list)) {
    682 		if (ifp->if_output == if_nulloutput)
    683 			continue;
    684 		if (ifp->if_flags & IFF_POINTOPOINT) {
    685 			for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
    686 			     ifa = TAILQ_NEXT(ifa, ifa_list)) {
    687 				if (ifa->ifa_addr->sa_family !=
    688 				      addr->sa_family ||
    689 				    ifa->ifa_dstaddr == NULL)
    690 					continue;
    691 				if (equal(addr, ifa->ifa_dstaddr))
    692 					return (ifa);
    693 			}
    694 		}
    695 	}
    696 	return (NULL);
    697 }
    698 
    699 /*
    700  * Find an interface on a specific network.  If many, choice
    701  * is most specific found.
    702  */
    703 struct ifaddr *
    704 ifa_ifwithnet(addr)
    705 	struct sockaddr *addr;
    706 {
    707 	struct ifnet *ifp;
    708 	struct ifaddr *ifa;
    709 	struct sockaddr_dl *sdl;
    710 	struct ifaddr *ifa_maybe = 0;
    711 	u_int af = addr->sa_family;
    712 	char *addr_data = addr->sa_data, *cplim;
    713 
    714 	if (af == AF_LINK) {
    715 		sdl = (struct sockaddr_dl *)addr;
    716 		if (sdl->sdl_index && sdl->sdl_index <= if_index &&
    717 		    ifindex2ifnet[sdl->sdl_index]->if_output != if_nulloutput)
    718 			return (ifnet_addrs[sdl->sdl_index]);
    719 	}
    720 #ifdef NETATALK
    721 	if (af == AF_APPLETALK) {
    722 		struct sockaddr_at *sat, *sat2;
    723 		sat = (struct sockaddr_at *)addr;
    724 		for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
    725 		     ifp = TAILQ_NEXT(ifp, if_list)) {
    726 			if (ifp->if_output == if_nulloutput)
    727 				continue;
    728 			ifa = at_ifawithnet((struct sockaddr_at *)addr, ifp);
    729 			if (ifa == NULL)
    730 				continue;
    731 			sat2 = (struct sockaddr_at *)ifa->ifa_addr;
    732 			if (sat2->sat_addr.s_net == sat->sat_addr.s_net)
    733 				return (ifa); /* exact match */
    734 			if (ifa_maybe == NULL) {
    735 				/* else keep the if with the rigth range */
    736 				ifa_maybe = ifa;
    737 			}
    738 		}
    739 		return (ifa_maybe);
    740 	}
    741 #endif
    742 	for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
    743 	     ifp = TAILQ_NEXT(ifp, if_list)) {
    744 		if (ifp->if_output == if_nulloutput)
    745 			continue;
    746 		for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
    747 		     ifa = TAILQ_NEXT(ifa, ifa_list)) {
    748 			char *cp, *cp2, *cp3;
    749 
    750 			if (ifa->ifa_addr->sa_family != af ||
    751 			    ifa->ifa_netmask == 0)
    752  next:				continue;
    753 			cp = addr_data;
    754 			cp2 = ifa->ifa_addr->sa_data;
    755 			cp3 = ifa->ifa_netmask->sa_data;
    756 			cplim = (char *)ifa->ifa_netmask +
    757 			    ifa->ifa_netmask->sa_len;
    758 			while (cp3 < cplim) {
    759 				if ((*cp++ ^ *cp2++) & *cp3++) {
    760 					/* want to continue for() loop */
    761 					goto next;
    762 				}
    763 			}
    764 			if (ifa_maybe == 0 ||
    765 			    rn_refines((caddr_t)ifa->ifa_netmask,
    766 			    (caddr_t)ifa_maybe->ifa_netmask))
    767 				ifa_maybe = ifa;
    768 		}
    769 	}
    770 	return (ifa_maybe);
    771 }
    772 
    773 /*
    774  * Find the interface of the addresss.
    775  */
    776 struct ifaddr *
    777 ifa_ifwithladdr(addr)
    778 	struct sockaddr *addr;
    779 {
    780 	struct ifaddr *ia;
    781 
    782 	if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr)) ||
    783 	    (ia = ifa_ifwithnet(addr)))
    784 		return (ia);
    785 	return (NULL);
    786 }
    787 
    788 /*
    789  * Find an interface using a specific address family
    790  */
    791 struct ifaddr *
    792 ifa_ifwithaf(af)
    793 	int af;
    794 {
    795 	struct ifnet *ifp;
    796 	struct ifaddr *ifa;
    797 
    798 	for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
    799 	     ifp = TAILQ_NEXT(ifp, if_list)) {
    800 		if (ifp->if_output == if_nulloutput)
    801 			continue;
    802 		for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
    803 		     ifa = TAILQ_NEXT(ifa, ifa_list)) {
    804 			if (ifa->ifa_addr->sa_family == af)
    805 				return (ifa);
    806 		}
    807 	}
    808 	return (NULL);
    809 }
    810 
    811 /*
    812  * Find an interface address specific to an interface best matching
    813  * a given address.
    814  */
    815 struct ifaddr *
    816 ifaof_ifpforaddr(addr, ifp)
    817 	struct sockaddr *addr;
    818 	struct ifnet *ifp;
    819 {
    820 	struct ifaddr *ifa;
    821 	char *cp, *cp2, *cp3;
    822 	char *cplim;
    823 	struct ifaddr *ifa_maybe = 0;
    824 	u_int af = addr->sa_family;
    825 
    826 	if (ifp->if_output == if_nulloutput)
    827 		return (NULL);
    828 
    829 	if (af >= AF_MAX)
    830 		return (NULL);
    831 
    832 	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
    833 	     ifa = TAILQ_NEXT(ifa, ifa_list)) {
    834 		if (ifa->ifa_addr->sa_family != af)
    835 			continue;
    836 		ifa_maybe = ifa;
    837 		if (ifa->ifa_netmask == 0) {
    838 			if (equal(addr, ifa->ifa_addr) ||
    839 			    (ifa->ifa_dstaddr &&
    840 			     equal(addr, ifa->ifa_dstaddr)))
    841 				return (ifa);
    842 			continue;
    843 		}
    844 		cp = addr->sa_data;
    845 		cp2 = ifa->ifa_addr->sa_data;
    846 		cp3 = ifa->ifa_netmask->sa_data;
    847 		cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
    848 		for (; cp3 < cplim; cp3++) {
    849 			if ((*cp++ ^ *cp2++) & *cp3)
    850 				break;
    851 		}
    852 		if (cp3 == cplim)
    853 			return (ifa);
    854 	}
    855 	return (ifa_maybe);
    856 }
    857 
    858 /*
    859  * Default action when installing a route with a Link Level gateway.
    860  * Lookup an appropriate real ifa to point to.
    861  * This should be moved to /sys/net/link.c eventually.
    862  */
    863 void
    864 link_rtrequest(cmd, rt, sa)
    865 	int cmd;
    866 	struct rtentry *rt;
    867 	struct sockaddr *sa;
    868 {
    869 	struct ifaddr *ifa;
    870 	struct sockaddr *dst;
    871 	struct ifnet *ifp;
    872 
    873 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
    874 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
    875 		return;
    876 	if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
    877 		IFAFREE(rt->rt_ifa);
    878 		rt->rt_ifa = ifa;
    879 		IFAREF(ifa);
    880 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
    881 			ifa->ifa_rtrequest(cmd, rt, sa);
    882 	}
    883 }
    884 
    885 /*
    886  * Mark an interface down and notify protocols of
    887  * the transition.
    888  * NOTE: must be called at splsoftnet or equivalent.
    889  */
    890 void
    891 if_down(ifp)
    892 	struct ifnet *ifp;
    893 {
    894 	struct ifaddr *ifa;
    895 
    896 	ifp->if_flags &= ~IFF_UP;
    897 	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
    898 	     ifa = TAILQ_NEXT(ifa, ifa_list))
    899 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
    900 	if_qflush(&ifp->if_snd);
    901 	rt_ifmsg(ifp);
    902 }
    903 
    904 /*
    905  * Mark an interface up and notify protocols of
    906  * the transition.
    907  * NOTE: must be called at splsoftnet or equivalent.
    908  */
    909 void
    910 if_up(ifp)
    911 	struct ifnet *ifp;
    912 {
    913 #ifdef notyet
    914 	struct ifaddr *ifa;
    915 #endif
    916 
    917 	ifp->if_flags |= IFF_UP;
    918 #ifdef notyet
    919 	/* this has no effect on IP, and will kill all ISO connections XXX */
    920 	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
    921 	     ifa = TAILQ_NEXT(ifa, ifa_list))
    922 		pfctlinput(PRC_IFUP, ifa->ifa_addr);
    923 #endif
    924 	rt_ifmsg(ifp);
    925 #ifdef INET6
    926 	in6_if_up(ifp);
    927 #endif
    928 }
    929 
    930 /*
    931  * Flush an interface queue.
    932  */
    933 void
    934 if_qflush(ifq)
    935 	struct ifqueue *ifq;
    936 {
    937 	struct mbuf *m, *n;
    938 
    939 	n = ifq->ifq_head;
    940 	while ((m = n) != NULL) {
    941 		n = m->m_act;
    942 		m_freem(m);
    943 	}
    944 	ifq->ifq_head = 0;
    945 	ifq->ifq_tail = 0;
    946 	ifq->ifq_len = 0;
    947 }
    948 
    949 /*
    950  * Handle interface watchdog timer routines.  Called
    951  * from softclock, we decrement timers (if set) and
    952  * call the appropriate interface routine on expiration.
    953  */
    954 void
    955 if_slowtimo(arg)
    956 	void *arg;
    957 {
    958 	struct ifnet *ifp;
    959 	int s = splimp();
    960 
    961 	for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
    962 	     ifp = TAILQ_NEXT(ifp, if_list)) {
    963 		if (ifp->if_timer == 0 || --ifp->if_timer)
    964 			continue;
    965 		if (ifp->if_watchdog)
    966 			(*ifp->if_watchdog)(ifp);
    967 	}
    968 	splx(s);
    969 	callout_reset(&if_slowtimo_ch, hz / IFNET_SLOWHZ,
    970 	    if_slowtimo, NULL);
    971 }
    972 
    973 /*
    974  * Set/clear promiscuous mode on interface ifp based on the truth value
    975  * of pswitch.  The calls are reference counted so that only the first
    976  * "on" request actually has an effect, as does the final "off" request.
    977  * Results are undefined if the "off" and "on" requests are not matched.
    978  */
    979 int
    980 ifpromisc(ifp, pswitch)
    981 	struct ifnet *ifp;
    982 	int pswitch;
    983 {
    984 	int pcount, ret;
    985 	short flags;
    986 	struct ifreq ifr;
    987 
    988 	pcount = ifp->if_pcount;
    989 	flags = ifp->if_flags;
    990 	if (pswitch) {
    991 		/*
    992 		 * Allow the device to be "placed" into promiscuous
    993 		 * mode even if it is not configured up.  It will
    994 		 * consult IFF_PROMISC when it is is brought up.
    995 		 */
    996 		if (ifp->if_pcount++ != 0)
    997 			return (0);
    998 		ifp->if_flags |= IFF_PROMISC;
    999 		if ((ifp->if_flags & IFF_UP) == 0)
   1000 			return (0);
   1001 	} else {
   1002 		if (--ifp->if_pcount > 0)
   1003 			return (0);
   1004 		ifp->if_flags &= ~IFF_PROMISC;
   1005 		/*
   1006 		 * If the device is not configured up, we should not need to
   1007 		 * turn off promiscuous mode (device should have turned it
   1008 		 * off when interface went down; and will look at IFF_PROMISC
   1009 		 * again next time interface comes up).
   1010 		 */
   1011 		if ((ifp->if_flags & IFF_UP) == 0)
   1012 			return (0);
   1013 	}
   1014 	memset(&ifr, 0, sizeof(ifr));
   1015 	ifr.ifr_flags = ifp->if_flags;
   1016 	ret = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t) &ifr);
   1017 	/* Restore interface state if not successful. */
   1018 	if (ret != 0) {
   1019 		ifp->if_pcount = pcount;
   1020 		ifp->if_flags = flags;
   1021 	}
   1022 	return (ret);
   1023 }
   1024 
   1025 /*
   1026  * Map interface name to
   1027  * interface structure pointer.
   1028  */
   1029 struct ifnet *
   1030 ifunit(name)
   1031 	const char *name;
   1032 {
   1033 	struct ifnet *ifp;
   1034 
   1035 	for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
   1036 	     ifp = TAILQ_NEXT(ifp, if_list)) {
   1037 		if (ifp->if_output == if_nulloutput)
   1038 			continue;
   1039 	 	if (strcmp(ifp->if_xname, name) == 0)
   1040 			return (ifp);
   1041 	}
   1042 	return (NULL);
   1043 }
   1044 
   1045 /*
   1046  * Interface ioctls.
   1047  */
   1048 int
   1049 ifioctl(so, cmd, data, p)
   1050 	struct socket *so;
   1051 	u_long cmd;
   1052 	caddr_t data;
   1053 	struct proc *p;
   1054 {
   1055 	struct ifnet *ifp;
   1056 	struct ifreq *ifr;
   1057 	int error = 0;
   1058 	short oif_flags;
   1059 
   1060 	switch (cmd) {
   1061 
   1062 	case SIOCGIFCONF:
   1063 	case OSIOCGIFCONF:
   1064 		return (ifconf(cmd, data));
   1065 	}
   1066 	ifr = (struct ifreq *)data;
   1067 
   1068 	switch (cmd) {
   1069 	case SIOCIFCREATE:
   1070 	case SIOCIFDESTROY:
   1071 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
   1072 			return (error);
   1073 		return ((cmd == SIOCIFCREATE) ?
   1074 			if_clone_create(ifr->ifr_name) :
   1075 			if_clone_destroy(ifr->ifr_name));
   1076 
   1077 	case SIOCIFGCLONERS:
   1078 		return (if_clone_list((struct if_clonereq *)data));
   1079 	}
   1080 
   1081 	ifp = ifunit(ifr->ifr_name);
   1082 	if (ifp == 0)
   1083 		return (ENXIO);
   1084 	oif_flags = ifp->if_flags;
   1085 	switch (cmd) {
   1086 
   1087 	case SIOCGIFFLAGS:
   1088 		ifr->ifr_flags = ifp->if_flags;
   1089 		break;
   1090 
   1091 	case SIOCGIFMETRIC:
   1092 		ifr->ifr_metric = ifp->if_metric;
   1093 		break;
   1094 
   1095 	case SIOCGIFMTU:
   1096 		ifr->ifr_mtu = ifp->if_mtu;
   1097 		break;
   1098 
   1099 	case SIOCSIFFLAGS:
   1100 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
   1101 			return (error);
   1102 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
   1103 			int s = splimp();
   1104 			if_down(ifp);
   1105 			splx(s);
   1106 		}
   1107 		if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
   1108 			int s = splimp();
   1109 			if_up(ifp);
   1110 			splx(s);
   1111 		}
   1112 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
   1113 			(ifr->ifr_flags &~ IFF_CANTCHANGE);
   1114 		if (ifp->if_ioctl)
   1115 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
   1116 		break;
   1117 
   1118 	case SIOCSIFMETRIC:
   1119 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
   1120 			return (error);
   1121 		ifp->if_metric = ifr->ifr_metric;
   1122 		break;
   1123 
   1124 	case SIOCSIFMTU:
   1125 	{
   1126 		u_long oldmtu = ifp->if_mtu;
   1127 
   1128 		error = suser(p->p_ucred, &p->p_acflag);
   1129 		if (error)
   1130 			return (error);
   1131 		if (ifp->if_ioctl == NULL)
   1132 			return (EOPNOTSUPP);
   1133 		error = (*ifp->if_ioctl)(ifp, cmd, data);
   1134 
   1135 		/*
   1136 		 * If the link MTU changed, do network layer specific procedure.
   1137 		 */
   1138 		if (ifp->if_mtu != oldmtu) {
   1139 #ifdef INET6
   1140 			nd6_setmtu(ifp);
   1141 #endif
   1142 		}
   1143 		break;
   1144 	}
   1145 	case SIOCSIFPHYADDR:
   1146 	case SIOCDIFPHYADDR:
   1147 #ifdef INET6
   1148 	case SIOCSIFPHYADDR_IN6:
   1149 #endif
   1150 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
   1151 			return (error);
   1152 		error = (*ifp->if_ioctl)(ifp, cmd, data);
   1153 		break;
   1154 
   1155 	case SIOCADDMULTI:
   1156 	case SIOCDELMULTI:
   1157 	case SIOCSIFMEDIA:
   1158 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
   1159 			return (error);
   1160 		/* FALLTHROUGH */
   1161 	case SIOCGIFMEDIA:
   1162 		if (ifp->if_ioctl == 0)
   1163 			return (EOPNOTSUPP);
   1164 		error = (*ifp->if_ioctl)(ifp, cmd, data);
   1165 		break;
   1166 
   1167 	case SIOCSDRVSPEC:
   1168 	case SIOCS80211NWID:
   1169 	case SIOCS80211NWKEY:
   1170 		/* XXX:  need to pass proc pointer through to driver... */
   1171 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
   1172 			return (error);
   1173 	/* FALLTHROUGH */
   1174 	default:
   1175 		if (so->so_proto == 0)
   1176 			return (EOPNOTSUPP);
   1177 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
   1178 		error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
   1179 		    (struct mbuf *)cmd, (struct mbuf *)data,
   1180 		    (struct mbuf *)ifp, p));
   1181 #else
   1182 	    {
   1183 		int ocmd = cmd;
   1184 
   1185 		switch (cmd) {
   1186 
   1187 		case SIOCSIFADDR:
   1188 		case SIOCSIFDSTADDR:
   1189 		case SIOCSIFBRDADDR:
   1190 		case SIOCSIFNETMASK:
   1191 #if BYTE_ORDER != BIG_ENDIAN
   1192 			if (ifr->ifr_addr.sa_family == 0 &&
   1193 			    ifr->ifr_addr.sa_len < 16) {
   1194 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
   1195 				ifr->ifr_addr.sa_len = 16;
   1196 			}
   1197 #else
   1198 			if (ifr->ifr_addr.sa_len == 0)
   1199 				ifr->ifr_addr.sa_len = 16;
   1200 #endif
   1201 			break;
   1202 
   1203 		case OSIOCGIFADDR:
   1204 			cmd = SIOCGIFADDR;
   1205 			break;
   1206 
   1207 		case OSIOCGIFDSTADDR:
   1208 			cmd = SIOCGIFDSTADDR;
   1209 			break;
   1210 
   1211 		case OSIOCGIFBRDADDR:
   1212 			cmd = SIOCGIFBRDADDR;
   1213 			break;
   1214 
   1215 		case OSIOCGIFNETMASK:
   1216 			cmd = SIOCGIFNETMASK;
   1217 		}
   1218 
   1219 		error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
   1220 		    (struct mbuf *)cmd, (struct mbuf *)data,
   1221 		    (struct mbuf *)ifp, p));
   1222 
   1223 		switch (ocmd) {
   1224 		case OSIOCGIFADDR:
   1225 		case OSIOCGIFDSTADDR:
   1226 		case OSIOCGIFBRDADDR:
   1227 		case OSIOCGIFNETMASK:
   1228 			*(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
   1229 		}
   1230 	    }
   1231 #endif /* COMPAT_43 */
   1232 		break;
   1233 	}
   1234 
   1235 	if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
   1236 #ifdef INET6
   1237 		if ((ifp->if_flags & IFF_UP) != 0) {
   1238 			int s = splimp();
   1239 			in6_if_up(ifp);
   1240 			splx(s);
   1241 		}
   1242 #endif
   1243 	}
   1244 
   1245 	return (error);
   1246 }
   1247 
   1248 /*
   1249  * Return interface configuration
   1250  * of system.  List may be used
   1251  * in later ioctl's (above) to get
   1252  * other information.
   1253  */
   1254 /*ARGSUSED*/
   1255 int
   1256 ifconf(cmd, data)
   1257 	u_long cmd;
   1258 	caddr_t data;
   1259 {
   1260 	struct ifconf *ifc = (struct ifconf *)data;
   1261 	struct ifnet *ifp;
   1262 	struct ifaddr *ifa;
   1263 	struct ifreq ifr, *ifrp;
   1264 	int space = ifc->ifc_len, error = 0;
   1265 
   1266 	ifrp = ifc->ifc_req;
   1267 	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) {
   1268 		bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
   1269 		if ((ifa = ifp->if_addrlist.tqh_first) == 0) {
   1270 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
   1271 			if (space >= (int)sizeof (ifr)) {
   1272 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
   1273 						sizeof(ifr));
   1274 				if (error)
   1275 					break;
   1276 			}
   1277 			space -= sizeof (ifr), ifrp++;
   1278 		} else
   1279 		    for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
   1280 			struct sockaddr *sa = ifa->ifa_addr;
   1281 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
   1282 			if (cmd == OSIOCGIFCONF) {
   1283 				struct osockaddr *osa =
   1284 					 (struct osockaddr *)&ifr.ifr_addr;
   1285 				ifr.ifr_addr = *sa;
   1286 				osa->sa_family = sa->sa_family;
   1287 				if (space >= (int)sizeof (ifr)) {
   1288 					error = copyout((caddr_t)&ifr,
   1289 							(caddr_t)ifrp,
   1290 							sizeof (ifr));
   1291 					ifrp++;
   1292 				}
   1293 			} else
   1294 #endif
   1295 			if (sa->sa_len <= sizeof(*sa)) {
   1296 				ifr.ifr_addr = *sa;
   1297 				if (space >= (int)sizeof (ifr)) {
   1298 					error = copyout((caddr_t)&ifr,
   1299 							(caddr_t)ifrp,
   1300 							sizeof (ifr));
   1301 					ifrp++;
   1302 				}
   1303 			} else {
   1304 				space -= sa->sa_len - sizeof(*sa);
   1305 				if (space >= (int)sizeof (ifr)) {
   1306 					error = copyout((caddr_t)&ifr,
   1307 							(caddr_t)ifrp,
   1308 							sizeof (ifr.ifr_name));
   1309 					if (error == 0) {
   1310 						error = copyout((caddr_t)sa,
   1311 						  (caddr_t)&ifrp->ifr_addr,
   1312 						  sa->sa_len);
   1313 					}
   1314 					ifrp = (struct ifreq *)
   1315 						(sa->sa_len +
   1316 						 (caddr_t)&ifrp->ifr_addr);
   1317 				}
   1318 			}
   1319 			if (error)
   1320 				break;
   1321 			space -= sizeof (ifr);
   1322 		}
   1323 	}
   1324 	ifc->ifc_len -= space;
   1325 	return (error);
   1326 }
   1327