xref: /openbsd/sys/net/if.c (revision 78b63d65)
1 /*	$OpenBSD: if.c,v 1.50 2001/12/09 12:57:26 jason Exp $	*/
2 /*	$NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1980, 1986, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *	This product includes software developed by the University of
48  *	California, Berkeley and its contributors.
49  * 4. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  *	@(#)if.c	8.3 (Berkeley) 1/4/94
66  */
67 
68 #include "bpfilter.h"
69 #include "bridge.h"
70 
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/mbuf.h>
74 #include <sys/proc.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/protosw.h>
78 #include <sys/kernel.h>
79 #include <sys/ioctl.h>
80 
81 #include <net/if.h>
82 #include <net/if_dl.h>
83 #include <net/route.h>
84 
85 #ifdef INET
86 #include <netinet/in.h>
87 #include <netinet/in_var.h>
88 #include <netinet/if_ether.h>
89 #include <netinet/igmp.h>
90 #ifdef MROUTING
91 #include <netinet/ip_mroute.h>
92 #endif
93 #endif
94 
95 #ifdef INET6
96 #ifndef INET
97 #include <netinet/in.h>
98 #endif
99 #include <netinet6/in6_ifattach.h>
100 #endif
101 
102 #if NBPFILTER > 0
103 #include <net/bpf.h>
104 #endif
105 
106 #if NBRIDGE > 0
107 #include <net/if_bridge.h>
108 #endif
109 
110 void	if_attachsetup __P((struct ifnet *));
111 int	if_detach_rtdelete __P((struct radix_node *, void *));
112 int	if_mark_ignore __P((struct radix_node *, void *));
113 int	if_mark_unignore __P((struct radix_node *, void *));
114 
115 int	ifqmaxlen = IFQ_MAXLEN;
116 
117 void	if_detached_start __P((struct ifnet *));
118 int	if_detached_ioctl __P((struct ifnet *, u_long, caddr_t));
119 void	if_detached_watchdog __P((struct ifnet *));
120 
121 #ifdef INET6
122 /*
123  * XXX: declare here to avoid to include many inet6 related files..
124  * should be more generalized?
125  */
126 extern void nd6_setmtu __P((struct ifnet *));
127 #endif
128 
129 /*
130  * Network interface utility routines.
131  *
132  * Routines with ifa_ifwith* names take sockaddr *'s as
133  * parameters.
134  */
135 void
136 ifinit()
137 {
138 	static struct timeout if_slowtim;
139 
140 	timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);
141 
142 	if_slowtimo(&if_slowtim);
143 }
144 
145 int if_index = 0;
146 struct ifaddr **ifnet_addrs = NULL;
147 struct ifnet **ifindex2ifnet = NULL;
148 
149 /*
150  * Attach an interface to the
151  * list of "active" interfaces.
152  */
153 void
154 if_attachsetup(ifp)
155 	struct ifnet *ifp;
156 {
157 	unsigned int socksize, ifasize;
158 	int namelen, masklen;
159 	register struct sockaddr_dl *sdl;
160 	register struct ifaddr *ifa;
161 	static int if_indexlim = 8;
162 
163 	ifp->if_index = ++if_index;
164 
165 	/*
166 	 * We have some arrays that should be indexed by if_index.
167 	 * since if_index will grow dynamically, they should grow too.
168 	 *	struct ifadd **ifnet_addrs
169 	 *	struct ifnet **ifindex2ifnet
170 	 */
171 	if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
172 		size_t n;
173 		caddr_t q;
174 
175 		while (if_index >= if_indexlim)
176 			if_indexlim <<= 1;
177 
178 		/* grow ifnet_addrs */
179 		n = if_indexlim * sizeof(ifa);
180 		q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
181 		bzero(q, n);
182 		if (ifnet_addrs) {
183 			bcopy((caddr_t)ifnet_addrs, q, n/2);
184 			free((caddr_t)ifnet_addrs, M_IFADDR);
185 		}
186 		ifnet_addrs = (struct ifaddr **)q;
187 
188 		/* grow ifindex2ifnet */
189 		n = if_indexlim * sizeof(struct ifnet *);
190 		q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
191 		bzero(q, n);
192 		if (ifindex2ifnet) {
193 			bcopy((caddr_t)ifindex2ifnet, q, n/2);
194 			free((caddr_t)ifindex2ifnet, M_IFADDR);
195 		}
196 		ifindex2ifnet = (struct ifnet **)q;
197 	}
198 
199 	ifindex2ifnet[if_index] = ifp;
200 
201 	if (ifp->if_snd.ifq_maxlen == 0)
202 		ifp->if_snd.ifq_maxlen = ifqmaxlen;
203 
204 	/*
205 	 * create a Link Level name for this device
206 	 */
207 	namelen = strlen(ifp->if_xname);
208 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
209 	masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
210 	socksize = masklen + ifp->if_addrlen;
211 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
212 	if (socksize < sizeof(*sdl))
213 		socksize = sizeof(*sdl);
214 	socksize = ROUNDUP(socksize);
215 	ifasize = sizeof(*ifa) + 2 * socksize;
216 	ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
217 	bzero((caddr_t)ifa, ifasize);
218 	sdl = (struct sockaddr_dl *)(ifa + 1);
219 	sdl->sdl_len = socksize;
220 	sdl->sdl_family = AF_LINK;
221 	bcopy(ifp->if_xname, sdl->sdl_data, namelen);
222 	sdl->sdl_nlen = namelen;
223 	sdl->sdl_index = ifp->if_index;
224 	sdl->sdl_type = ifp->if_type;
225 	ifnet_addrs[if_index] = ifa;
226 	ifa->ifa_ifp = ifp;
227 	ifa->ifa_rtrequest = link_rtrequest;
228 	TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
229 	ifa->ifa_addr = (struct sockaddr *)sdl;
230 	sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
231 	ifa->ifa_netmask = (struct sockaddr *)sdl;
232 	sdl->sdl_len = masklen;
233 	while (namelen != 0)
234 		sdl->sdl_data[--namelen] = 0xff;
235 #ifdef ALTQ
236 	ifp->if_snd.altq_type = 0;
237 	ifp->if_snd.altq_disc = NULL;
238 	ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
239 	ifp->if_snd.altq_tbr  = NULL;
240 	ifp->if_snd.altq_ifp  = ifp;
241 #endif
242 }
243 
244 void
245 if_attachhead(ifp)
246 	struct ifnet *ifp;
247 {
248 	if (if_index == 0)
249 		TAILQ_INIT(&ifnet);
250 	TAILQ_INIT(&ifp->if_addrlist);
251 	TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
252 	if_attachsetup(ifp);
253 }
254 
255 void
256 if_attach(ifp)
257 	struct ifnet *ifp;
258 {
259 	if (if_index == 0)
260 		TAILQ_INIT(&ifnet);
261 	TAILQ_INIT(&ifp->if_addrlist);
262 	TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
263 	if_attachsetup(ifp);
264 }
265 
266 /*
267  * Delete a route if it has a specific interface for output.
268  * This function complies to the rn_walktree callback API.
269  */
270 int
271 if_detach_rtdelete(rn, vifp)
272 	struct radix_node *rn;
273 	void *vifp;
274 {
275 	struct ifnet *ifp = vifp;
276 	struct rtentry *rt = (struct rtentry *)rn;
277 
278 	if (rt->rt_ifp == ifp)
279 		rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
280 		    0, NULL);
281 
282 	/*
283 	 * XXX There should be no need to check for rt_ifa belonging to this
284 	 * interface, because then rt_ifp is set, right?
285 	 */
286 
287 	return (0);
288 }
289 
290 int
291 if_mark_ignore(rn, vifp)
292 	struct radix_node *rn;
293 	void *vifp;
294 {
295 	struct ifnet *ifp = vifp;
296 	struct rtentry *rt = (struct rtentry *)rn;
297 
298 	if (rt->rt_ifp == ifp)
299 		rn->rn_flags |= RNF_IGNORE;
300 
301 	return (0);
302 }
303 
304 int
305 if_mark_unignore(rn, vifp)
306 	struct radix_node *rn;
307 	void *vifp;
308 {
309 	struct ifnet *ifp = vifp;
310 	struct rtentry *rt = (struct rtentry *)rn;
311 
312 	if (rt->rt_ifp == ifp)
313 		rn->rn_flags &= ~RNF_IGNORE;
314 
315 	return (0);
316 }
317 
318 /*
319  * Detach an interface from everything in the kernel.  Also deallocate
320  * private resources.
321  * XXX So far only the INET protocol family has been looked over
322  * wrt resource usage that needs to be decoupled.
323  */
324 void
325 if_detach(ifp)
326 	struct ifnet *ifp;
327 {
328 	struct ifaddr *ifa;
329 	int i, s = splimp();
330 	struct radix_node_head *rnh;
331 
332 	ifp->if_flags &= ~IFF_OACTIVE;
333 	ifp->if_start = if_detached_start;
334 	ifp->if_ioctl = if_detached_ioctl;
335 	ifp->if_watchdog = if_detached_watchdog;
336 
337 #if NBRIDGE > 0
338 	/* Remove the interface from any bridge it is part of.  */
339 	if (ifp->if_bridge)
340 		bridge_ifdetach(ifp);
341 #endif
342 
343 #if NBPFILTER > 0
344 	/* If there is a bpf device attached, detach from it.  */
345 	if (ifp->if_bpf)
346 		bpfdetach(ifp);
347 #endif
348 #ifdef ALTQ
349 	if (ALTQ_IS_ENABLED(&ifp->if_snd))
350 		altq_disable(&ifp->if_snd);
351 	if (ALTQ_IS_ATTACHED(&ifp->if_snd))
352 		altq_detach(&ifp->if_snd);
353 #endif
354 
355 	/*
356 	 * Find and remove all routes which is using this interface.
357 	 * XXX Factor out into a route.c function?
358 	 */
359 	for (i = 1; i <= AF_MAX; i++) {
360 		rnh = rt_tables[i];
361 		if (rnh)
362 			(*rnh->rnh_walktree)(rnh, if_detach_rtdelete, ifp);
363 	}
364 
365 #ifdef INET
366 	rti_delete(ifp);
367 #if NETHER > 0
368 	myip_ifp = NULL;
369 #endif
370 #ifdef MROUTING
371 	vif_delete(ifp);
372 #endif
373 #endif
374 #ifdef INET6
375 	in6_ifdetach(ifp);
376 #endif
377 	/*
378 	 * XXX transient ifp refs?  inpcb.ip_moptions.imo_multicast_ifp?
379 	 * Other network stacks than INET?
380 	 */
381 
382 	/* Remove the interface from the list of all interfaces.  */
383 	TAILQ_REMOVE(&ifnet, ifp, if_list);
384 
385 	/* Deallocate private resources.  */
386 	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa;
387 	    ifa = TAILQ_FIRST(&ifp->if_addrlist)) {
388 		TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
389 #ifdef INET
390 		if (ifa->ifa_addr->sa_family == AF_INET)
391 			TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa,
392 			    ia_list);
393 #endif
394 		free(ifa, M_IFADDR);
395 	}
396 	splx(s);
397 }
398 
399 /*
400  * Locate an interface based on a complete address.
401  */
402 /*ARGSUSED*/
403 struct ifaddr *
404 ifa_ifwithaddr(addr)
405 	register struct sockaddr *addr;
406 {
407 	register struct ifnet *ifp;
408 	register struct ifaddr *ifa;
409 
410 #define	equal(a1, a2) \
411   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
412 	TAILQ_FOREACH(ifp, &ifnet, if_list) {
413 	    TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
414 		if (ifa->ifa_addr->sa_family != addr->sa_family)
415 			continue;
416 		if (equal(addr, ifa->ifa_addr))
417 			return (ifa);
418 		if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
419 		    /* IP6 doesn't have broadcast */
420 		    ifa->ifa_broadaddr->sa_len != 0 &&
421 		    equal(ifa->ifa_broadaddr, addr))
422 			return (ifa);
423 	    }
424 	}
425 	return (NULL);
426 }
427 /*
428  * Locate the point to point interface with a given destination address.
429  */
430 /*ARGSUSED*/
431 struct ifaddr *
432 ifa_ifwithdstaddr(addr)
433 	register struct sockaddr *addr;
434 {
435 	register struct ifnet *ifp;
436 	register struct ifaddr *ifa;
437 
438 	TAILQ_FOREACH(ifp, &ifnet, if_list) {
439 	    if (ifp->if_flags & IFF_POINTOPOINT)
440 	        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
441 			if (ifa->ifa_addr->sa_family != addr->sa_family ||
442 			    ifa->ifa_dstaddr == NULL)
443 				continue;
444 			if (equal(addr, ifa->ifa_dstaddr))
445 				return (ifa);
446 		}
447 	}
448 	return (NULL);
449 }
450 
451 /*
452  * Find an interface on a specific network.  If many, choice
453  * is most specific found.
454  */
455 struct ifaddr *
456 ifa_ifwithnet(addr)
457 	struct sockaddr *addr;
458 {
459 	register struct ifnet *ifp;
460 	register struct ifaddr *ifa;
461 	struct ifaddr *ifa_maybe = 0;
462 	u_int af = addr->sa_family;
463 	char *addr_data = addr->sa_data, *cplim;
464 
465 	if (af == AF_LINK) {
466 	    register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
467 	    if (sdl->sdl_index && sdl->sdl_index <= if_index)
468 		return (ifnet_addrs[sdl->sdl_index]);
469 	}
470 	TAILQ_FOREACH(ifp, &ifnet, if_list) {
471 		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
472 			register char *cp, *cp2, *cp3;
473 
474 			if (ifa->ifa_addr->sa_family != af ||
475 			    ifa->ifa_netmask == 0)
476 				next: continue;
477 			cp = addr_data;
478 			cp2 = ifa->ifa_addr->sa_data;
479 			cp3 = ifa->ifa_netmask->sa_data;
480 			cplim = (char *)ifa->ifa_netmask +
481 				ifa->ifa_netmask->sa_len;
482 			while (cp3 < cplim)
483 				if ((*cp++ ^ *cp2++) & *cp3++)
484 				    /* want to continue for() loop */
485 					goto next;
486 			if (ifa_maybe == 0 ||
487 			    rn_refines((caddr_t)ifa->ifa_netmask,
488 			    (caddr_t)ifa_maybe->ifa_netmask))
489 				ifa_maybe = ifa;
490 		}
491 	}
492 	return (ifa_maybe);
493 }
494 
495 /*
496  * Find an interface using a specific address family
497  */
498 struct ifaddr *
499 ifa_ifwithaf(af)
500 	register int af;
501 {
502 	register struct ifnet *ifp;
503 	register struct ifaddr *ifa;
504 
505 	TAILQ_FOREACH(ifp, &ifnet, if_list) {
506 		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
507 			if (ifa->ifa_addr->sa_family == af)
508 				return (ifa);
509 		}
510 	}
511 	return (NULL);
512 }
513 
514 /*
515  * Find an interface address specific to an interface best matching
516  * a given address.
517  */
518 struct ifaddr *
519 ifaof_ifpforaddr(addr, ifp)
520 	struct sockaddr *addr;
521 	register struct ifnet *ifp;
522 {
523 	register struct ifaddr *ifa;
524 	register char *cp, *cp2, *cp3;
525 	register char *cplim;
526 	struct ifaddr *ifa_maybe = 0;
527 	u_int af = addr->sa_family;
528 
529 	if (af >= AF_MAX)
530 		return (NULL);
531 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
532 		if (ifa->ifa_addr->sa_family != af)
533 			continue;
534 		ifa_maybe = ifa;
535 		if (ifa->ifa_netmask == 0) {
536 			if (equal(addr, ifa->ifa_addr) ||
537 			    (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
538 				return (ifa);
539 			continue;
540 		}
541 		cp = addr->sa_data;
542 		cp2 = ifa->ifa_addr->sa_data;
543 		cp3 = ifa->ifa_netmask->sa_data;
544 		cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
545 		for (; cp3 < cplim; cp3++)
546 			if ((*cp++ ^ *cp2++) & *cp3)
547 				break;
548 		if (cp3 == cplim)
549 			return (ifa);
550 	}
551 	return (ifa_maybe);
552 }
553 
554 /*
555  * Default action when installing a route with a Link Level gateway.
556  * Lookup an appropriate real ifa to point to.
557  * This should be moved to /sys/net/link.c eventually.
558  */
559 void
560 link_rtrequest(cmd, rt, info)
561 	int cmd;
562 	register struct rtentry *rt;
563 	struct rt_addrinfo *info;
564 {
565 	register struct ifaddr *ifa;
566 	struct sockaddr *dst;
567 	struct ifnet *ifp;
568 
569 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
570 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
571 		return;
572 	if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
573 		IFAFREE(rt->rt_ifa);
574 		rt->rt_ifa = ifa;
575 		ifa->ifa_refcnt++;
576 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
577 			ifa->ifa_rtrequest(cmd, rt, info);
578 	}
579 }
580 
581 /*
582  * Mark an interface down and notify protocols of
583  * the transition.
584  * NOTE: must be called at splsoftnet or equivalent.
585  */
586 void
587 if_down(ifp)
588 	register struct ifnet *ifp;
589 {
590 	register struct ifaddr *ifa;
591 	struct radix_node_head *rnh;
592 	int i;
593 
594 	ifp->if_flags &= ~IFF_UP;
595 	microtime(&ifp->if_lastchange);
596 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
597 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
598 	}
599 	IFQ_PURGE(&ifp->if_snd);
600 	rt_ifmsg(ifp);
601 
602 	/*
603 	 * Find and mark as ignore all routes which are using this interface.
604 	 * XXX Factor out into a route.c function?
605 	 */
606 	for (i = 1; i <= AF_MAX; i++) {
607 		rnh = rt_tables[i];
608 		if (rnh)
609 			(*rnh->rnh_walktree)(rnh, if_mark_ignore, ifp);
610 	}
611 }
612 
613 /*
614  * Mark an interface up and notify protocols of
615  * the transition.
616  * NOTE: must be called at splsoftnet or equivalent.
617  */
618 void
619 if_up(ifp)
620 	register struct ifnet *ifp;
621 {
622 #ifdef notyet
623 	register struct ifaddr *ifa;
624 #endif
625 	struct radix_node_head *rnh;
626 	int i;
627 
628 	ifp->if_flags |= IFF_UP;
629 	microtime(&ifp->if_lastchange);
630 #ifdef notyet
631 	/* this has no effect on IP, and will kill all ISO connections XXX */
632 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
633 		pfctlinput(PRC_IFUP, ifa->ifa_addr);
634 	}
635 #endif
636 	rt_ifmsg(ifp);
637 #ifdef INET6
638 	in6_if_up(ifp);
639 #endif
640 
641 	/*
642 	 * Find and unignore all routes which are using this interface.
643 	 * XXX Factor out into a route.c function?
644 	 */
645 	for (i = 1; i <= AF_MAX; i++) {
646 		rnh = rt_tables[i];
647 		if (rnh)
648 			(*rnh->rnh_walktree)(rnh, if_mark_unignore, ifp);
649 	}
650 }
651 
652 /*
653  * Flush an interface queue.
654  */
655 void
656 if_qflush(ifq)
657 	register struct ifqueue *ifq;
658 {
659 	register struct mbuf *m, *n;
660 
661 	n = ifq->ifq_head;
662 	while ((m = n) != NULL) {
663 		n = m->m_act;
664 		m_freem(m);
665 	}
666 	ifq->ifq_head = 0;
667 	ifq->ifq_tail = 0;
668 	ifq->ifq_len = 0;
669 }
670 
671 /*
672  * Handle interface watchdog timer routines.  Called
673  * from softclock, we decrement timers (if set) and
674  * call the appropriate interface routine on expiration.
675  */
676 void
677 if_slowtimo(arg)
678 	void *arg;
679 {
680 	struct timeout *to = (struct timeout *)arg;
681 	struct ifnet *ifp;
682 	int s = splimp();
683 
684 	TAILQ_FOREACH(ifp, &ifnet, if_list) {
685 		if (ifp->if_timer == 0 || --ifp->if_timer)
686 			continue;
687 		if (ifp->if_watchdog)
688 			(*ifp->if_watchdog)(ifp);
689 	}
690 	splx(s);
691 	timeout_add(to, hz / IFNET_SLOWHZ);
692 }
693 
694 /*
695  * Map interface name to
696  * interface structure pointer.
697  */
698 struct ifnet *
699 ifunit(name)
700 	register char *name;
701 {
702 	register struct ifnet *ifp;
703 
704 	TAILQ_FOREACH(ifp, &ifnet, if_list) {
705 		if (strcmp(ifp->if_xname, name) == 0)
706 			return (ifp);
707 	}
708 	return (NULL);
709 }
710 
711 /*
712  * Interface ioctls.
713  */
714 int
715 ifioctl(so, cmd, data, p)
716 	struct socket *so;
717 	u_long cmd;
718 	caddr_t data;
719 	struct proc *p;
720 {
721 	register struct ifnet *ifp;
722 	register struct ifreq *ifr;
723 	int error = 0;
724 	short oif_flags;
725 
726 	switch (cmd) {
727 
728 	case SIOCGIFCONF:
729 	case OSIOCGIFCONF:
730 		return (ifconf(cmd, data));
731 	}
732 	ifr = (struct ifreq *)data;
733 	ifp = ifunit(ifr->ifr_name);
734 	if (ifp == 0)
735 		return (ENXIO);
736 	oif_flags = ifp->if_flags;
737 	switch (cmd) {
738 
739 	case SIOCGIFFLAGS:
740 		ifr->ifr_flags = ifp->if_flags;
741 		break;
742 
743 	case SIOCGIFMETRIC:
744 		ifr->ifr_metric = ifp->if_metric;
745 		break;
746 
747 	case SIOCGIFMTU:
748 		ifr->ifr_mtu = ifp->if_mtu;
749 		break;
750 
751 	case SIOCGIFDATA:
752 		error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data,
753 		    sizeof(ifp->if_data));
754 		break;
755 
756 	case SIOCSIFFLAGS:
757 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
758 			return (error);
759 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
760 			int s = splimp();
761 			if_down(ifp);
762 			splx(s);
763 		}
764 		if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
765 			int s = splimp();
766 			if_up(ifp);
767 			splx(s);
768 		}
769 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
770 			(ifr->ifr_flags &~ IFF_CANTCHANGE);
771 		if (ifp->if_ioctl)
772 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
773 		break;
774 
775 	case SIOCSIFMETRIC:
776 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
777 			return (error);
778 		ifp->if_metric = ifr->ifr_metric;
779 		break;
780 
781 	case SIOCSIFMTU:
782 	{
783 #ifdef INET6
784 		int oldmtu = ifp->if_mtu;
785 #endif
786 
787 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
788 			return (error);
789 		if (ifp->if_ioctl == NULL)
790 			return (EOPNOTSUPP);
791 		error = (*ifp->if_ioctl)(ifp, cmd, data);
792 
793 		/*
794 		 * If the link MTU changed, do network layer specific procedure.
795 		 */
796 #ifdef INET6
797 		if (ifp->if_mtu != oldmtu)
798 			nd6_setmtu(ifp);
799 #endif
800 		break;
801 	}
802 
803 	case SIOCSIFPHYADDR:
804 	case SIOCDIFPHYADDR:
805 #ifdef INET6
806 	case SIOCSIFPHYADDR_IN6:
807 #endif
808 	case SIOCSLIFPHYADDR:
809 	case SIOCADDMULTI:
810 	case SIOCDELMULTI:
811 	case SIOCSIFMEDIA:
812 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
813 			return (error);
814 		/* FALLTHROUGH */
815 	case SIOCGIFPSRCADDR:
816 	case SIOCGIFPDSTADDR:
817 	case SIOCGLIFPHYADDR:
818 	case SIOCGIFMEDIA:
819 		if (ifp->if_ioctl == 0)
820 			return (EOPNOTSUPP);
821 		error = (*ifp->if_ioctl)(ifp, cmd, data);
822 		break;
823 
824 	default:
825 		if (so->so_proto == 0)
826 			return (EOPNOTSUPP);
827 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
828 		error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
829 			(struct mbuf *) cmd, (struct mbuf *) data,
830 			(struct mbuf *) ifp));
831 #else
832 	    {
833 		u_long ocmd = cmd;
834 
835 		switch (cmd) {
836 
837 		case SIOCSIFADDR:
838 		case SIOCSIFDSTADDR:
839 		case SIOCSIFBRDADDR:
840 		case SIOCSIFNETMASK:
841 #if BYTE_ORDER != BIG_ENDIAN
842 			if (ifr->ifr_addr.sa_family == 0 &&
843 			    ifr->ifr_addr.sa_len < 16) {
844 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
845 				ifr->ifr_addr.sa_len = 16;
846 			}
847 #else
848 			if (ifr->ifr_addr.sa_len == 0)
849 				ifr->ifr_addr.sa_len = 16;
850 #endif
851 			break;
852 
853 		case OSIOCGIFADDR:
854 			cmd = SIOCGIFADDR;
855 			break;
856 
857 		case OSIOCGIFDSTADDR:
858 			cmd = SIOCGIFDSTADDR;
859 			break;
860 
861 		case OSIOCGIFBRDADDR:
862 			cmd = SIOCGIFBRDADDR;
863 			break;
864 
865 		case OSIOCGIFNETMASK:
866 			cmd = SIOCGIFNETMASK;
867 		}
868 		error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
869 		    (struct mbuf *) cmd, (struct mbuf *) data,
870 		    (struct mbuf *) ifp));
871 		switch (ocmd) {
872 
873 		case OSIOCGIFADDR:
874 		case OSIOCGIFDSTADDR:
875 		case OSIOCGIFBRDADDR:
876 		case OSIOCGIFNETMASK:
877 			*(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
878 		}
879 
880 	    }
881 #endif
882 		break;
883 	}
884 
885 	if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
886 #ifdef INET6
887 		if ((ifp->if_flags & IFF_UP) != 0) {
888 			int s = splsoftnet();
889 			in6_if_up(ifp);
890 			splx(s);
891 		}
892 #endif
893   	}
894 	return (error);
895 }
896 
897 /*
898  * Return interface configuration
899  * of system.  List may be used
900  * in later ioctl's (above) to get
901  * other information.
902  */
903 /*ARGSUSED*/
904 int
905 ifconf(cmd, data)
906 	u_long cmd;
907 	caddr_t data;
908 {
909 	register struct ifconf *ifc = (struct ifconf *)data;
910 	register struct ifnet *ifp;
911 	register struct ifaddr *ifa;
912 	struct ifreq ifr, *ifrp;
913 	int space = ifc->ifc_len, error = 0;
914 
915 	/* If ifc->ifc_len is 0, fill it in with the needed size and return. */
916 	if (space == 0) {
917 		TAILQ_FOREACH(ifp, &ifnet, if_list) {
918 			register struct sockaddr *sa;
919 
920 			if (TAILQ_EMPTY(&ifp->if_addrlist))
921 				space += sizeof (ifr);
922 			else
923 				TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
924 					sa = ifa->ifa_addr;
925 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
926 					if (cmd != OSIOCGIFCONF)
927 #endif
928 					if (sa->sa_len > sizeof(*sa))
929 						space += sa->sa_len -
930 						    sizeof (*sa);
931 					space += sizeof (ifr);
932 				}
933 		}
934 		ifc->ifc_len = space;
935 		return(0);
936 	}
937 
938 	ifrp = ifc->ifc_req;
939 	for (ifp = TAILQ_FIRST(&ifnet); space >= sizeof(ifr) &&
940 	    ifp != TAILQ_END(&ifnet); ifp = TAILQ_NEXT(ifp, if_list)) {
941 		bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
942 		if (TAILQ_EMPTY(&ifp->if_addrlist)) {
943 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
944 			error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
945 			    sizeof(ifr));
946 			if (error)
947 				break;
948 			space -= sizeof (ifr), ifrp++;
949 		} else
950 			for (ifa = TAILQ_FIRST(&ifp->if_addrlist);
951 			    space >= sizeof (ifr) &&
952 			    ifa != TAILQ_END(&ifp->if_addrlist);
953 			    ifa = TAILQ_NEXT(ifa, ifa_list)) {
954 				register struct sockaddr *sa = ifa->ifa_addr;
955 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
956 				if (cmd == OSIOCGIFCONF) {
957 					struct osockaddr *osa =
958 					    (struct osockaddr *)&ifr.ifr_addr;
959 					ifr.ifr_addr = *sa;
960 					osa->sa_family = sa->sa_family;
961 					error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
962 					    sizeof (ifr));
963 					ifrp++;
964 				} else
965 #endif
966 				if (sa->sa_len <= sizeof(*sa)) {
967 					ifr.ifr_addr = *sa;
968 					error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
969 					    sizeof (ifr));
970 					ifrp++;
971 				} else {
972 					space -= sa->sa_len - sizeof(*sa);
973 					if (space < sizeof (ifr))
974 						break;
975 					error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
976 					    sizeof (ifr.ifr_name));
977 					if (error == 0)
978 						error = copyout((caddr_t)sa,
979 						    (caddr_t)&ifrp->ifr_addr,
980 						    sa->sa_len);
981 					ifrp = (struct ifreq *)(sa->sa_len +
982 					    (caddr_t)&ifrp->ifr_addr);
983 				}
984 				if (error)
985 					break;
986 				space -= sizeof (ifr);
987 			}
988 	}
989 	ifc->ifc_len -= space;
990 	return (error);
991 }
992 
993 /*
994  * Dummy functions replaced in ifnet during detach (if protocols decide to
995  * fiddle with the if during detach.
996  */
997 void
998 if_detached_start(struct ifnet *ifp)
999 {
1000 	struct mbuf *m;
1001 
1002 	while (1) {
1003 		IF_DEQUEUE(&ifp->if_snd, m);
1004 
1005 		if (m == NULL)
1006 			return;
1007 		m_freem(m);
1008 	}
1009 }
1010 
1011 int
1012 if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
1013 {
1014 	return ENODEV;
1015 }
1016 
1017 void
1018 if_detached_watchdog(struct ifnet *ifp)
1019 {
1020 	/* nothing */
1021 }
1022 
1023 /*
1024  * Set/clear promiscuous mode on interface ifp based on the truth value
1025  * of pswitch.  The calls are reference counted so that only the first
1026  * "on" request actually has an effect, as does the final "off" request.
1027  * Results are undefined if the "off" and "on" requests are not matched.
1028  */
1029 int
1030 ifpromisc(ifp, pswitch)
1031 	struct ifnet *ifp;
1032 	int pswitch;
1033 {
1034 	struct ifreq ifr;
1035 
1036 	if (pswitch) {
1037 		/*
1038 		 * If the device is not configured up, we cannot put it in
1039 		 * promiscuous mode.
1040 		 */
1041 		if ((ifp->if_flags & IFF_UP) == 0)
1042 			return (ENETDOWN);
1043 		if (ifp->if_pcount++ != 0)
1044 			return (0);
1045 		ifp->if_flags |= IFF_PROMISC;
1046 	} else {
1047 		if (--ifp->if_pcount > 0)
1048 			return (0);
1049 		ifp->if_flags &= ~IFF_PROMISC;
1050 		/*
1051 		 * If the device is not configured up, we should not need to
1052 		 * turn off promiscuous mode (device should have turned it
1053 		 * off when interface went down; and will look at IFF_PROMISC
1054 		 * again next time interface comes up).
1055 		 */
1056 		if ((ifp->if_flags & IFF_UP) == 0)
1057 			return (0);
1058 	}
1059 	ifr.ifr_flags = ifp->if_flags;
1060 	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
1061 }
1062