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