xref: /openbsd-src/sys/net/if.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: if.c,v 1.49 2001/06/29 22:46:05 fgsch 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 	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
413 	    for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
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 	return (NULL);
425 }
426 /*
427  * Locate the point to point interface with a given destination address.
428  */
429 /*ARGSUSED*/
430 struct ifaddr *
431 ifa_ifwithdstaddr(addr)
432 	register struct sockaddr *addr;
433 {
434 	register struct ifnet *ifp;
435 	register struct ifaddr *ifa;
436 
437 	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
438 	    if (ifp->if_flags & IFF_POINTOPOINT)
439 		for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
440 			if (ifa->ifa_addr->sa_family != addr->sa_family ||
441 			    ifa->ifa_dstaddr == NULL)
442 				continue;
443 			if (equal(addr, ifa->ifa_dstaddr))
444 				return (ifa);
445 	}
446 	return (NULL);
447 }
448 
449 /*
450  * Find an interface on a specific network.  If many, choice
451  * is most specific found.
452  */
453 struct ifaddr *
454 ifa_ifwithnet(addr)
455 	struct sockaddr *addr;
456 {
457 	register struct ifnet *ifp;
458 	register struct ifaddr *ifa;
459 	struct ifaddr *ifa_maybe = 0;
460 	u_int af = addr->sa_family;
461 	char *addr_data = addr->sa_data, *cplim;
462 
463 	if (af == AF_LINK) {
464 	    register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
465 	    if (sdl->sdl_index && sdl->sdl_index <= if_index)
466 		return (ifnet_addrs[sdl->sdl_index]);
467 	}
468 	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
469 		for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
470 			register char *cp, *cp2, *cp3;
471 
472 			if (ifa->ifa_addr->sa_family != af ||
473 			    ifa->ifa_netmask == 0)
474 				next: continue;
475 			cp = addr_data;
476 			cp2 = ifa->ifa_addr->sa_data;
477 			cp3 = ifa->ifa_netmask->sa_data;
478 			cplim = (char *)ifa->ifa_netmask +
479 				ifa->ifa_netmask->sa_len;
480 			while (cp3 < cplim)
481 				if ((*cp++ ^ *cp2++) & *cp3++)
482 				    /* want to continue for() loop */
483 					goto next;
484 			if (ifa_maybe == 0 ||
485 			    rn_refines((caddr_t)ifa->ifa_netmask,
486 			    (caddr_t)ifa_maybe->ifa_netmask))
487 				ifa_maybe = ifa;
488 		}
489 	return (ifa_maybe);
490 }
491 
492 /*
493  * Find an interface using a specific address family
494  */
495 struct ifaddr *
496 ifa_ifwithaf(af)
497 	register int af;
498 {
499 	register struct ifnet *ifp;
500 	register struct ifaddr *ifa;
501 
502 	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
503 		for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
504 			if (ifa->ifa_addr->sa_family == af)
505 				return (ifa);
506 	return (NULL);
507 }
508 
509 /*
510  * Find an interface address specific to an interface best matching
511  * a given address.
512  */
513 struct ifaddr *
514 ifaof_ifpforaddr(addr, ifp)
515 	struct sockaddr *addr;
516 	register struct ifnet *ifp;
517 {
518 	register struct ifaddr *ifa;
519 	register char *cp, *cp2, *cp3;
520 	register char *cplim;
521 	struct ifaddr *ifa_maybe = 0;
522 	u_int af = addr->sa_family;
523 
524 	if (af >= AF_MAX)
525 		return (NULL);
526 	for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
527 		if (ifa->ifa_addr->sa_family != af)
528 			continue;
529 		ifa_maybe = ifa;
530 		if (ifa->ifa_netmask == 0) {
531 			if (equal(addr, ifa->ifa_addr) ||
532 			    (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
533 				return (ifa);
534 			continue;
535 		}
536 		cp = addr->sa_data;
537 		cp2 = ifa->ifa_addr->sa_data;
538 		cp3 = ifa->ifa_netmask->sa_data;
539 		cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
540 		for (; cp3 < cplim; cp3++)
541 			if ((*cp++ ^ *cp2++) & *cp3)
542 				break;
543 		if (cp3 == cplim)
544 			return (ifa);
545 	}
546 	return (ifa_maybe);
547 }
548 
549 /*
550  * Default action when installing a route with a Link Level gateway.
551  * Lookup an appropriate real ifa to point to.
552  * This should be moved to /sys/net/link.c eventually.
553  */
554 void
555 link_rtrequest(cmd, rt, info)
556 	int cmd;
557 	register struct rtentry *rt;
558 	struct rt_addrinfo *info;
559 {
560 	register struct ifaddr *ifa;
561 	struct sockaddr *dst;
562 	struct ifnet *ifp;
563 
564 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
565 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
566 		return;
567 	if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
568 		IFAFREE(rt->rt_ifa);
569 		rt->rt_ifa = ifa;
570 		ifa->ifa_refcnt++;
571 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
572 			ifa->ifa_rtrequest(cmd, rt, info);
573 	}
574 }
575 
576 /*
577  * Mark an interface down and notify protocols of
578  * the transition.
579  * NOTE: must be called at splsoftnet or equivalent.
580  */
581 void
582 if_down(ifp)
583 	register struct ifnet *ifp;
584 {
585 	register struct ifaddr *ifa;
586 	struct radix_node_head *rnh;
587 	int i;
588 
589 	ifp->if_flags &= ~IFF_UP;
590 	microtime(&ifp->if_lastchange);
591 	for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
592 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
593 	IFQ_PURGE(&ifp->if_snd);
594 	rt_ifmsg(ifp);
595 
596 	/*
597 	 * Find and mark as ignore all routes which are using this interface.
598 	 * XXX Factor out into a route.c function?
599 	 */
600 	for (i = 1; i <= AF_MAX; i++) {
601 		rnh = rt_tables[i];
602 		if (rnh)
603 			(*rnh->rnh_walktree)(rnh, if_mark_ignore, ifp);
604 	}
605 }
606 
607 /*
608  * Mark an interface up and notify protocols of
609  * the transition.
610  * NOTE: must be called at splsoftnet or equivalent.
611  */
612 void
613 if_up(ifp)
614 	register struct ifnet *ifp;
615 {
616 #ifdef notyet
617 	register struct ifaddr *ifa;
618 #endif
619 	struct radix_node_head *rnh;
620 	int i;
621 
622 	ifp->if_flags |= IFF_UP;
623 	microtime(&ifp->if_lastchange);
624 #ifdef notyet
625 	/* this has no effect on IP, and will kill all ISO connections XXX */
626 	for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
627 	    ifa = ifa->ifa_list.tqe_next)
628 		pfctlinput(PRC_IFUP, ifa->ifa_addr);
629 #endif
630 	rt_ifmsg(ifp);
631 #ifdef INET6
632 	in6_if_up(ifp);
633 #endif
634 
635 	/*
636 	 * Find and unignore all routes which are using this interface.
637 	 * XXX Factor out into a route.c function?
638 	 */
639 	for (i = 1; i <= AF_MAX; i++) {
640 		rnh = rt_tables[i];
641 		if (rnh)
642 			(*rnh->rnh_walktree)(rnh, if_mark_unignore, ifp);
643 	}
644 }
645 
646 /*
647  * Flush an interface queue.
648  */
649 void
650 if_qflush(ifq)
651 	register struct ifqueue *ifq;
652 {
653 	register struct mbuf *m, *n;
654 
655 	n = ifq->ifq_head;
656 	while ((m = n) != NULL) {
657 		n = m->m_act;
658 		m_freem(m);
659 	}
660 	ifq->ifq_head = 0;
661 	ifq->ifq_tail = 0;
662 	ifq->ifq_len = 0;
663 }
664 
665 /*
666  * Handle interface watchdog timer routines.  Called
667  * from softclock, we decrement timers (if set) and
668  * call the appropriate interface routine on expiration.
669  */
670 void
671 if_slowtimo(arg)
672 	void *arg;
673 {
674 	struct timeout *to = (struct timeout *)arg;
675 	struct ifnet *ifp;
676 	int s = splimp();
677 
678 	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) {
679 		if (ifp->if_timer == 0 || --ifp->if_timer)
680 			continue;
681 		if (ifp->if_watchdog)
682 			(*ifp->if_watchdog)(ifp);
683 	}
684 	splx(s);
685 	timeout_add(to, hz / IFNET_SLOWHZ);
686 }
687 
688 /*
689  * Map interface name to
690  * interface structure pointer.
691  */
692 struct ifnet *
693 ifunit(name)
694 	register char *name;
695 {
696 	register struct ifnet *ifp;
697 
698 	for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
699 		if (strcmp(ifp->if_xname, name) == 0)
700 			return (ifp);
701 
702 	return (NULL);
703 }
704 
705 /*
706  * Interface ioctls.
707  */
708 int
709 ifioctl(so, cmd, data, p)
710 	struct socket *so;
711 	u_long cmd;
712 	caddr_t data;
713 	struct proc *p;
714 {
715 	register struct ifnet *ifp;
716 	register struct ifreq *ifr;
717 	int error = 0;
718 	short oif_flags;
719 
720 	switch (cmd) {
721 
722 	case SIOCGIFCONF:
723 	case OSIOCGIFCONF:
724 		return (ifconf(cmd, data));
725 	}
726 	ifr = (struct ifreq *)data;
727 	ifp = ifunit(ifr->ifr_name);
728 	if (ifp == 0)
729 		return (ENXIO);
730 	oif_flags = ifp->if_flags;
731 	switch (cmd) {
732 
733 	case SIOCGIFFLAGS:
734 		ifr->ifr_flags = ifp->if_flags;
735 		break;
736 
737 	case SIOCGIFMETRIC:
738 		ifr->ifr_metric = ifp->if_metric;
739 		break;
740 
741 	case SIOCGIFMTU:
742 		ifr->ifr_mtu = ifp->if_mtu;
743 		break;
744 
745 	case SIOCGIFDATA:
746 		error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data,
747 		    sizeof(ifp->if_data));
748 		break;
749 
750 	case SIOCSIFFLAGS:
751 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
752 			return (error);
753 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
754 			int s = splimp();
755 			if_down(ifp);
756 			splx(s);
757 		}
758 		if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
759 			int s = splimp();
760 			if_up(ifp);
761 			splx(s);
762 		}
763 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
764 			(ifr->ifr_flags &~ IFF_CANTCHANGE);
765 		if (ifp->if_ioctl)
766 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
767 		break;
768 
769 	case SIOCSIFMETRIC:
770 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
771 			return (error);
772 		ifp->if_metric = ifr->ifr_metric;
773 		break;
774 
775 	case SIOCSIFMTU:
776 	{
777 #ifdef INET6
778 		int oldmtu = ifp->if_mtu;
779 #endif
780 
781 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
782 			return (error);
783 		if (ifp->if_ioctl == NULL)
784 			return (EOPNOTSUPP);
785 		error = (*ifp->if_ioctl)(ifp, cmd, data);
786 
787 		/*
788 		 * If the link MTU changed, do network layer specific procedure.
789 		 */
790 #ifdef INET6
791 		if (ifp->if_mtu != oldmtu)
792 			nd6_setmtu(ifp);
793 #endif
794 		break;
795 	}
796 
797 	case SIOCSIFPHYADDR:
798 	case SIOCDIFPHYADDR:
799 #ifdef INET6
800 	case SIOCSIFPHYADDR_IN6:
801 #endif
802 	case SIOCSLIFPHYADDR:
803 	case SIOCADDMULTI:
804 	case SIOCDELMULTI:
805 	case SIOCSIFMEDIA:
806 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
807 			return (error);
808 		/* FALLTHROUGH */
809 	case SIOCGIFPSRCADDR:
810 	case SIOCGIFPDSTADDR:
811 	case SIOCGLIFPHYADDR:
812 	case SIOCGIFMEDIA:
813 		if (ifp->if_ioctl == 0)
814 			return (EOPNOTSUPP);
815 		error = (*ifp->if_ioctl)(ifp, cmd, data);
816 		break;
817 
818 	default:
819 		if (so->so_proto == 0)
820 			return (EOPNOTSUPP);
821 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
822 		error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
823 			(struct mbuf *) cmd, (struct mbuf *) data,
824 			(struct mbuf *) ifp));
825 #else
826 	    {
827 		u_long ocmd = cmd;
828 
829 		switch (cmd) {
830 
831 		case SIOCSIFADDR:
832 		case SIOCSIFDSTADDR:
833 		case SIOCSIFBRDADDR:
834 		case SIOCSIFNETMASK:
835 #if BYTE_ORDER != BIG_ENDIAN
836 			if (ifr->ifr_addr.sa_family == 0 &&
837 			    ifr->ifr_addr.sa_len < 16) {
838 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
839 				ifr->ifr_addr.sa_len = 16;
840 			}
841 #else
842 			if (ifr->ifr_addr.sa_len == 0)
843 				ifr->ifr_addr.sa_len = 16;
844 #endif
845 			break;
846 
847 		case OSIOCGIFADDR:
848 			cmd = SIOCGIFADDR;
849 			break;
850 
851 		case OSIOCGIFDSTADDR:
852 			cmd = SIOCGIFDSTADDR;
853 			break;
854 
855 		case OSIOCGIFBRDADDR:
856 			cmd = SIOCGIFBRDADDR;
857 			break;
858 
859 		case OSIOCGIFNETMASK:
860 			cmd = SIOCGIFNETMASK;
861 		}
862 		error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
863 		    (struct mbuf *) cmd, (struct mbuf *) data,
864 		    (struct mbuf *) ifp));
865 		switch (ocmd) {
866 
867 		case OSIOCGIFADDR:
868 		case OSIOCGIFDSTADDR:
869 		case OSIOCGIFBRDADDR:
870 		case OSIOCGIFNETMASK:
871 			*(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
872 		}
873 
874 	    }
875 #endif
876 		break;
877 	}
878 
879 	if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
880 #ifdef INET6
881 		if ((ifp->if_flags & IFF_UP) != 0) {
882 			int s = splsoftnet();
883 			in6_if_up(ifp);
884 			splx(s);
885 		}
886 #endif
887   	}
888 	return (error);
889 }
890 
891 /*
892  * Return interface configuration
893  * of system.  List may be used
894  * in later ioctl's (above) to get
895  * other information.
896  */
897 /*ARGSUSED*/
898 int
899 ifconf(cmd, data)
900 	u_long cmd;
901 	caddr_t data;
902 {
903 	register struct ifconf *ifc = (struct ifconf *)data;
904 	register struct ifnet *ifp;
905 	register struct ifaddr *ifa;
906 	struct ifreq ifr, *ifrp;
907 	int space = ifc->ifc_len, error = 0;
908 
909 	/* If ifc->ifc_len is 0, fill it in with the needed size and return. */
910 	if (space == 0) {
911 		for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
912 			register struct sockaddr *sa;
913 
914 			if ((ifa = ifp->if_addrlist.tqh_first) == 0)
915 				space += sizeof (ifr);
916 			else
917 				for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
918 					sa = ifa->ifa_addr;
919 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
920 					if (cmd != OSIOCGIFCONF)
921 #endif
922 					if (sa->sa_len > sizeof(*sa))
923 						space += sa->sa_len -
924 						    sizeof (*sa);
925 					space += sizeof (ifr);
926 				}
927 		}
928 		ifc->ifc_len = space;
929 		return(0);
930 	}
931 
932 	ifrp = ifc->ifc_req;
933 	for (ifp = ifnet.tqh_first; space >= sizeof (ifr) && ifp != 0;
934 	    ifp = ifp->if_list.tqe_next) {
935 		bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
936 		if ((ifa = ifp->if_addrlist.tqh_first) == 0) {
937 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
938 			error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
939 			    sizeof(ifr));
940 			if (error)
941 				break;
942 			space -= sizeof (ifr), ifrp++;
943 		} else
944 			for (; space >= sizeof (ifr) && ifa != 0;
945 			    ifa = ifa->ifa_list.tqe_next) {
946 				register struct sockaddr *sa = ifa->ifa_addr;
947 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
948 				if (cmd == OSIOCGIFCONF) {
949 					struct osockaddr *osa =
950 					    (struct osockaddr *)&ifr.ifr_addr;
951 					ifr.ifr_addr = *sa;
952 					osa->sa_family = sa->sa_family;
953 					error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
954 					    sizeof (ifr));
955 					ifrp++;
956 				} else
957 #endif
958 				if (sa->sa_len <= sizeof(*sa)) {
959 					ifr.ifr_addr = *sa;
960 					error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
961 					    sizeof (ifr));
962 					ifrp++;
963 				} else {
964 					space -= sa->sa_len - sizeof(*sa);
965 					if (space < sizeof (ifr))
966 						break;
967 					error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
968 					    sizeof (ifr.ifr_name));
969 					if (error == 0)
970 						error = copyout((caddr_t)sa,
971 						    (caddr_t)&ifrp->ifr_addr,
972 						    sa->sa_len);
973 					ifrp = (struct ifreq *)(sa->sa_len +
974 					    (caddr_t)&ifrp->ifr_addr);
975 				}
976 				if (error)
977 					break;
978 				space -= sizeof (ifr);
979 			}
980 	}
981 	ifc->ifc_len -= space;
982 	return (error);
983 }
984 
985 /*
986  * Dummy functions replaced in ifnet during detach (if protocols decide to
987  * fiddle with the if during detach.
988  */
989 void
990 if_detached_start(struct ifnet *ifp)
991 {
992 	struct mbuf *m;
993 
994 	while (1) {
995 		IF_DEQUEUE(&ifp->if_snd, m);
996 
997 		if (m == NULL)
998 			return;
999 		m_freem(m);
1000 	}
1001 }
1002 
1003 int
1004 if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
1005 {
1006 	return ENODEV;
1007 }
1008 
1009 void
1010 if_detached_watchdog(struct ifnet *ifp)
1011 {
1012 	/* nothing */
1013 }
1014 
1015 /*
1016  * Set/clear promiscuous mode on interface ifp based on the truth value
1017  * of pswitch.  The calls are reference counted so that only the first
1018  * "on" request actually has an effect, as does the final "off" request.
1019  * Results are undefined if the "off" and "on" requests are not matched.
1020  */
1021 int
1022 ifpromisc(ifp, pswitch)
1023 	struct ifnet *ifp;
1024 	int pswitch;
1025 {
1026 	struct ifreq ifr;
1027 
1028 	if (pswitch) {
1029 		/*
1030 		 * If the device is not configured up, we cannot put it in
1031 		 * promiscuous mode.
1032 		 */
1033 		if ((ifp->if_flags & IFF_UP) == 0)
1034 			return (ENETDOWN);
1035 		if (ifp->if_pcount++ != 0)
1036 			return (0);
1037 		ifp->if_flags |= IFF_PROMISC;
1038 	} else {
1039 		if (--ifp->if_pcount > 0)
1040 			return (0);
1041 		ifp->if_flags &= ~IFF_PROMISC;
1042 		/*
1043 		 * If the device is not configured up, we should not need to
1044 		 * turn off promiscuous mode (device should have turned it
1045 		 * off when interface went down; and will look at IFF_PROMISC
1046 		 * again next time interface comes up).
1047 		 */
1048 		if ((ifp->if_flags & IFF_UP) == 0)
1049 			return (0);
1050 	}
1051 	ifr.ifr_flags = ifp->if_flags;
1052 	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
1053 }
1054