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