xref: /freebsd/sys/net/if.c (revision 05c7a37afb48ddd5ee1bd921a5d46fe59cc70b15)
1 /*
2  * Copyright (c) 1980, 1986, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)if.c	8.3 (Berkeley) 1/4/94
34  * $Id: if.c,v 1.28 1996/02/08 21:34:56 wollman Exp $
35  */
36 
37 #include <sys/param.h>
38 #include <sys/queue.h>
39 #include <sys/mbuf.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/protosw.h>
45 #include <sys/kernel.h>
46 #include <sys/ioctl.h>
47 #include <sys/errno.h>
48 #include <sys/syslog.h>
49 #include <sys/sysctl.h>
50 
51 #include <net/if.h>
52 #include <net/if_dl.h>
53 #include <net/if_types.h>
54 #include <net/radix.h>
55 
56 /*
57  * System initialization
58  */
59 
60 static int ifconf __P((int, caddr_t));
61 static void ifinit __P((void *));
62 static void if_qflush __P((struct ifqueue *));
63 static void if_slowtimo __P((void *));
64 static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
65 
66 SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)
67 
68 
69 int	ifqmaxlen = IFQ_MAXLEN;
70 struct	ifnet *ifnet;
71 
72 /*
73  * Network interface utility routines.
74  *
75  * Routines with ifa_ifwith* names take sockaddr *'s as
76  * parameters.
77  *
78  * This routine assumes that it will be called at splimp() or higher.
79  */
80 /* ARGSUSED*/
81 void
82 ifinit(dummy)
83 	void *dummy;
84 {
85 	register struct ifnet *ifp;
86 
87 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
88 		if (ifp->if_snd.ifq_maxlen == 0)
89 			ifp->if_snd.ifq_maxlen = ifqmaxlen;
90 	if_slowtimo(0);
91 }
92 
93 static int if_index = 0;
94 static struct ifaddr **ifnet_addrs;
95 
96 
97 /*
98  * Attach an interface to the
99  * list of "active" interfaces.
100  */
101 void
102 if_attach(ifp)
103 	struct ifnet *ifp;
104 {
105 	unsigned socksize, ifasize;
106 	int namelen, masklen;
107 	char workbuf[64];
108 	register struct ifnet **p = &ifnet;
109 	register struct sockaddr_dl *sdl;
110 	register struct ifaddr *ifa;
111 	static int if_indexlim = 8;
112 
113 
114 	while (*p)
115 		p = &((*p)->if_next);
116 	*p = ifp;
117 	ifp->if_index = ++if_index;
118 	if (ifnet_addrs == 0 || if_index >= if_indexlim) {
119 		unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
120 		struct ifaddr **q = (struct ifaddr **)
121 					malloc(n, M_IFADDR, M_WAITOK);
122 		bzero((caddr_t)q, n);
123 		if (ifnet_addrs) {
124 			bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
125 			free((caddr_t)ifnet_addrs, M_IFADDR);
126 		}
127 		ifnet_addrs = q;
128 	}
129 	/*
130 	 * create a Link Level name for this device
131 	 */
132 	namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
133 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
134 	masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
135 	socksize = masklen + ifp->if_addrlen;
136 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
137 	socksize = ROUNDUP(socksize);
138 	if (socksize < sizeof(*sdl))
139 		socksize = sizeof(*sdl);
140 	ifasize = sizeof(*ifa) + 2 * socksize;
141 	ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
142 	if (ifa) {
143 		bzero((caddr_t)ifa, ifasize);
144 		sdl = (struct sockaddr_dl *)(ifa + 1);
145 		sdl->sdl_len = socksize;
146 		sdl->sdl_family = AF_LINK;
147 		bcopy(workbuf, sdl->sdl_data, namelen);
148 		sdl->sdl_nlen = namelen;
149 		sdl->sdl_index = ifp->if_index;
150 		sdl->sdl_type = ifp->if_type;
151 		ifnet_addrs[if_index - 1] = ifa;
152 		ifa->ifa_ifp = ifp;
153 		ifa->ifa_next = ifp->if_addrlist;
154 		ifa->ifa_rtrequest = link_rtrequest;
155 		ifp->if_addrlist = ifa;
156 		ifa->ifa_addr = (struct sockaddr *)sdl;
157 
158 		sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
159 		ifa->ifa_netmask = (struct sockaddr *)sdl;
160 		sdl->sdl_len = masklen;
161 		while (namelen != 0)
162 			sdl->sdl_data[--namelen] = 0xff;
163 	}
164 	/*
165 	 * If they provided a slow input queue, initialize it.
166 	 */
167 	if (ifp->if_poll_slowq) {
168 		struct ifqueue *ifq = ifp->if_poll_slowq;
169 
170 		bzero(ifq, sizeof *ifq);
171 		ifq->ifq_maxlen = ifqmaxlen;
172 #ifdef POLLING
173 		ifq->if_poll_recv = if_poll_recv_slow;
174 #endif
175 	}
176 }
177 /*
178  * Locate an interface based on a complete address.
179  */
180 /*ARGSUSED*/
181 struct ifaddr *
182 ifa_ifwithaddr(addr)
183 	register struct sockaddr *addr;
184 {
185 	register struct ifnet *ifp;
186 	register struct ifaddr *ifa;
187 
188 #define	equal(a1, a2) \
189   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
190 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
191 	    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
192 		if (ifa->ifa_addr->sa_family != addr->sa_family)
193 			continue;
194 		if (equal(addr, ifa->ifa_addr))
195 			return (ifa);
196 		if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
197 		    equal(ifa->ifa_broadaddr, addr))
198 			return (ifa);
199 	}
200 	return ((struct ifaddr *)0);
201 }
202 /*
203  * Locate the point to point interface with a given destination address.
204  */
205 /*ARGSUSED*/
206 struct ifaddr *
207 ifa_ifwithdstaddr(addr)
208 	register struct sockaddr *addr;
209 {
210 	register struct ifnet *ifp;
211 	register struct ifaddr *ifa;
212 
213 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
214 	    if (ifp->if_flags & IFF_POINTOPOINT)
215 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
216 			if (ifa->ifa_addr->sa_family != addr->sa_family)
217 				continue;
218 			if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
219 				return (ifa);
220 	}
221 	return ((struct ifaddr *)0);
222 }
223 
224 /*
225  * Find an interface on a specific network.  If many, choice
226  * is most specific found.
227  */
228 struct ifaddr *
229 ifa_ifwithnet(addr)
230 	struct sockaddr *addr;
231 {
232 	register struct ifnet *ifp;
233 	register struct ifaddr *ifa;
234 	struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
235 	u_int af = addr->sa_family;
236 	char *addr_data = addr->sa_data, *cplim;
237 
238 	if (af == AF_LINK) {
239 	    register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
240 	    if (sdl->sdl_index && sdl->sdl_index <= if_index)
241 		return (ifnet_addrs[sdl->sdl_index - 1]);
242 	}
243 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
244 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
245 			register char *cp, *cp2, *cp3;
246 
247 			if (ifa->ifa_addr->sa_family != af)
248 				next: continue;
249 			if (ifp->if_flags & IFF_POINTOPOINT) {
250 				if (equal(addr, ifa->ifa_dstaddr))
251  					return (ifa);
252 			} else {
253 				if (ifa->ifa_netmask == 0)
254 					continue;
255 				cp = addr_data;
256 				cp2 = ifa->ifa_addr->sa_data;
257 				cp3 = ifa->ifa_netmask->sa_data;
258 				cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
259 				while (cp3 < cplim)
260 					if ((*cp++ ^ *cp2++) & *cp3++)
261 						goto next;
262 				if (ifa_maybe == 0 ||
263 				    rn_refines((caddr_t)ifa->ifa_netmask,
264 				    (caddr_t)ifa_maybe->ifa_netmask))
265 					ifa_maybe = ifa;
266 			}
267 		}
268 	}
269 	return (ifa_maybe);
270 }
271 
272 /*
273  * Find an interface address specific to an interface best matching
274  * a given address.
275  */
276 struct ifaddr *
277 ifaof_ifpforaddr(addr, ifp)
278 	struct sockaddr *addr;
279 	register struct ifnet *ifp;
280 {
281 	register struct ifaddr *ifa;
282 	register char *cp, *cp2, *cp3;
283 	register char *cplim;
284 	struct ifaddr *ifa_maybe = 0;
285 	u_int af = addr->sa_family;
286 
287 	if (af >= AF_MAX)
288 		return (0);
289 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
290 		if (ifa->ifa_addr->sa_family != af)
291 			continue;
292 		ifa_maybe = ifa;
293 		if (ifa->ifa_netmask == 0) {
294 			if (equal(addr, ifa->ifa_addr) ||
295 			    (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
296 				return (ifa);
297 			continue;
298 		}
299 		if (ifp->if_flags & IFF_POINTOPOINT) {
300 			if (equal(addr, ifa->ifa_dstaddr))
301 				return (ifa);
302 		} else {
303 			cp = addr->sa_data;
304 			cp2 = ifa->ifa_addr->sa_data;
305 			cp3 = ifa->ifa_netmask->sa_data;
306 			cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
307 			for (; cp3 < cplim; cp3++)
308 				if ((*cp++ ^ *cp2++) & *cp3)
309 					break;
310 			if (cp3 == cplim)
311 				return (ifa);
312 		}
313 	}
314 	return (ifa_maybe);
315 }
316 
317 #include <net/route.h>
318 
319 /*
320  * Default action when installing a route with a Link Level gateway.
321  * Lookup an appropriate real ifa to point to.
322  * This should be moved to /sys/net/link.c eventually.
323  */
324 static void
325 link_rtrequest(cmd, rt, sa)
326 	int cmd;
327 	register struct rtentry *rt;
328 	struct sockaddr *sa;
329 {
330 	register struct ifaddr *ifa;
331 	struct sockaddr *dst;
332 	struct ifnet *ifp;
333 
334 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
335 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
336 		return;
337 	ifa = ifaof_ifpforaddr(dst, ifp);
338 	if (ifa) {
339 		IFAFREE(rt->rt_ifa);
340 		rt->rt_ifa = ifa;
341 		ifa->ifa_refcnt++;
342 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
343 			ifa->ifa_rtrequest(cmd, rt, sa);
344 	}
345 }
346 
347 /*
348  * Mark an interface down and notify protocols of
349  * the transition.
350  * NOTE: must be called at splnet or eqivalent.
351  */
352 void
353 if_down(ifp)
354 	register struct ifnet *ifp;
355 {
356 	register struct ifaddr *ifa;
357 
358 	ifp->if_flags &= ~IFF_UP;
359 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
360 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
361 	if_qflush(&ifp->if_snd);
362 	rt_ifmsg(ifp);
363 }
364 
365 /*
366  * Mark an interface up and notify protocols of
367  * the transition.
368  * NOTE: must be called at splnet or eqivalent.
369  */
370 void
371 if_up(ifp)
372 	register struct ifnet *ifp;
373 {
374 
375 	ifp->if_flags |= IFF_UP;
376 #ifdef notyet
377 	register struct ifaddr *ifa;
378 	/* this has no effect on IP, and will kill all iso connections XXX */
379 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
380 		pfctlinput(PRC_IFUP, ifa->ifa_addr);
381 #endif
382 	rt_ifmsg(ifp);
383 }
384 
385 /*
386  * Flush an interface queue.
387  */
388 static void
389 if_qflush(ifq)
390 	register struct ifqueue *ifq;
391 {
392 	register struct mbuf *m, *n;
393 
394 	n = ifq->ifq_head;
395 	while ((m = n) != 0) {
396 		n = m->m_act;
397 		m_freem(m);
398 	}
399 	ifq->ifq_head = 0;
400 	ifq->ifq_tail = 0;
401 	ifq->ifq_len = 0;
402 }
403 
404 /*
405  * Handle interface watchdog timer routines.  Called
406  * from softclock, we decrement timers (if set) and
407  * call the appropriate interface routine on expiration.
408  */
409 static void
410 if_slowtimo(arg)
411 	void *arg;
412 {
413 	register struct ifnet *ifp;
414 	int s = splimp();
415 
416 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
417 		if (ifp->if_timer == 0 || --ifp->if_timer)
418 			continue;
419 		if (ifp->if_watchdog)
420 			(*ifp->if_watchdog)(ifp);
421 	}
422 	splx(s);
423 	timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
424 }
425 
426 /*
427  * Map interface name to
428  * interface structure pointer.
429  */
430 struct ifnet *
431 ifunit(name)
432 	register char *name;
433 {
434 	register char *cp;
435 	register struct ifnet *ifp;
436 	int unit;
437 	unsigned len;
438 	char *ep, c;
439 
440 	for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
441 		if (*cp >= '0' && *cp <= '9')
442 			break;
443 	if (*cp == '\0' || cp == name + IFNAMSIZ)
444 		return ((struct ifnet *)0);
445 	/*
446 	 * Save first char of unit, and pointer to it,
447 	 * so we can put a null there to avoid matching
448 	 * initial substrings of interface names.
449 	 */
450 	len = cp - name + 1;
451 	c = *cp;
452 	ep = cp;
453 	for (unit = 0; *cp >= '0' && *cp <= '9'; )
454 		unit = unit * 10 + *cp++ - '0';
455 	*ep = 0;
456 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
457 		if (bcmp(ifp->if_name, name, len))
458 			continue;
459 		if (unit == ifp->if_unit)
460 			break;
461 	}
462 	*ep = c;
463 	return (ifp);
464 }
465 
466 /*
467  * Interface ioctls.
468  */
469 int
470 ifioctl(so, cmd, data, p)
471 	struct socket *so;
472 	int cmd;
473 	caddr_t data;
474 	struct proc *p;
475 {
476 	register struct ifnet *ifp;
477 	register struct ifreq *ifr;
478 	int error;
479 
480 	switch (cmd) {
481 
482 	case SIOCGIFCONF:
483 	case OSIOCGIFCONF:
484 		return (ifconf(cmd, data));
485 	}
486 	ifr = (struct ifreq *)data;
487 	ifp = ifunit(ifr->ifr_name);
488 	if (ifp == 0)
489 		return (ENXIO);
490 	switch (cmd) {
491 
492 	case SIOCGIFFLAGS:
493 		ifr->ifr_flags = ifp->if_flags;
494 		break;
495 
496 	case SIOCGIFMETRIC:
497 		ifr->ifr_metric = ifp->if_metric;
498 		break;
499 
500 	case SIOCGIFMTU:
501 		ifr->ifr_mtu = ifp->if_mtu;
502 		break;
503 
504 	case SIOCGIFPHYS:
505 		ifr->ifr_phys = ifp->if_physical;
506 		break;
507 
508 	case SIOCSIFFLAGS:
509 		error = suser(p->p_ucred, &p->p_acflag);
510 		if (error)
511 			return (error);
512 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
513 			int s = splimp();
514 			if_down(ifp);
515 			splx(s);
516 		}
517 		if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
518 			int s = splimp();
519 			if_up(ifp);
520 			splx(s);
521 		}
522 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
523 			(ifr->ifr_flags &~ IFF_CANTCHANGE);
524 		if (ifp->if_ioctl)
525 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
526 		break;
527 
528 	case SIOCSIFMETRIC:
529 		error = suser(p->p_ucred, &p->p_acflag);
530 		if (error)
531 			return (error);
532 		ifp->if_metric = ifr->ifr_metric;
533 		break;
534 
535 	case SIOCSIFPHYS:
536 		error = suser(p->p_ucred, &p->p_acflag);
537 		if (error) return error;
538 
539 		if (!ifp->if_ioctl) return EOPNOTSUPP;
540 		return ifp->if_ioctl(ifp, cmd, data);
541 
542 	case SIOCSIFMTU:
543 		error = suser(p->p_ucred, &p->p_acflag);
544 		if (error)
545 			return (error);
546 		if (ifp->if_ioctl == NULL)
547 			return (EOPNOTSUPP);
548 		/*
549 		 * 72 was chosen below because it is the size of a TCP/IP
550 		 * header (40) + the minimum mss (32).
551 		 */
552 		if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535)
553 			return (EINVAL);
554 		return ((*ifp->if_ioctl)(ifp, cmd, data));
555 
556 	case SIOCADDMULTI:
557 	case SIOCDELMULTI:
558 		error = suser(p->p_ucred, &p->p_acflag);
559 		if (error)
560 			return (error);
561 		if (ifp->if_ioctl == NULL)
562 			return (EOPNOTSUPP);
563 		return ((*ifp->if_ioctl)(ifp, cmd, data));
564 
565 	default:
566 		if (so->so_proto == 0)
567 			return (EOPNOTSUPP);
568 #ifndef COMPAT_43
569 		return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
570 			(struct mbuf *)cmd, (struct mbuf *)data,
571 			(struct mbuf *)ifp));
572 #else
573 	    {
574 		int ocmd = cmd;
575 
576 		switch (cmd) {
577 
578 		case SIOCSIFDSTADDR:
579 		case SIOCSIFADDR:
580 		case SIOCSIFBRDADDR:
581 		case SIOCSIFNETMASK:
582 #if BYTE_ORDER != BIG_ENDIAN
583 			if (ifr->ifr_addr.sa_family == 0 &&
584 			    ifr->ifr_addr.sa_len < 16) {
585 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
586 				ifr->ifr_addr.sa_len = 16;
587 			}
588 #else
589 			if (ifr->ifr_addr.sa_len == 0)
590 				ifr->ifr_addr.sa_len = 16;
591 #endif
592 			break;
593 
594 		case OSIOCGIFADDR:
595 			cmd = SIOCGIFADDR;
596 			break;
597 
598 		case OSIOCGIFDSTADDR:
599 			cmd = SIOCGIFDSTADDR;
600 			break;
601 
602 		case OSIOCGIFBRDADDR:
603 			cmd = SIOCGIFBRDADDR;
604 			break;
605 
606 		case OSIOCGIFNETMASK:
607 			cmd = SIOCGIFNETMASK;
608 		}
609 		error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
610 			  /*
611 			   * XXX callees reverse the following bogus casts,
612 			   * but it would be easier to use a separate
613 			   * interface that is guaranteed to work.
614 			   */
615 			  (struct mbuf *)cmd, (struct mbuf *)data,
616 			  (struct mbuf *)ifp));
617 		switch (ocmd) {
618 
619 		case OSIOCGIFADDR:
620 		case OSIOCGIFDSTADDR:
621 		case OSIOCGIFBRDADDR:
622 		case OSIOCGIFNETMASK:
623 			*(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
624 		}
625 		return (error);
626 
627 	    }
628 #endif
629 	}
630 	return (0);
631 }
632 
633 /*
634  * Set/clear promiscuous mode on interface ifp based on the truth value
635  * of pswitch.  The calls are reference counted so that only the first
636  * "on" request actually has an effect, as does the final "off" request.
637  * Results are undefined if the "off" and "on" requests are not matched.
638  */
639 int
640 ifpromisc(ifp, pswitch)
641 	struct ifnet *ifp;
642 	int pswitch;
643 {
644 	struct ifreq ifr;
645 
646 	if (pswitch) {
647 		/*
648 		 * If the device is not configured up, we cannot put it in
649 		 * promiscuous mode.
650 		 */
651 		if ((ifp->if_flags & IFF_UP) == 0)
652 			return (ENETDOWN);
653 		if (ifp->if_pcount++ != 0)
654 			return (0);
655 		ifp->if_flags |= IFF_PROMISC;
656 		log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
657 		    ifp->if_name, ifp->if_unit);
658 	} else {
659 		if (--ifp->if_pcount > 0)
660 			return (0);
661 		ifp->if_flags &= ~IFF_PROMISC;
662 	}
663 	ifr.ifr_flags = ifp->if_flags;
664 	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
665 }
666 
667 /*
668  * Return interface configuration
669  * of system.  List may be used
670  * in later ioctl's (above) to get
671  * other information.
672  */
673 /*ARGSUSED*/
674 static int
675 ifconf(cmd, data)
676 	int cmd;
677 	caddr_t data;
678 {
679 	register struct ifconf *ifc = (struct ifconf *)data;
680 	register struct ifnet *ifp = ifnet;
681 	register struct ifaddr *ifa;
682 	struct ifreq ifr, *ifrp;
683 	int space = ifc->ifc_len, error = 0;
684 
685 	ifrp = ifc->ifc_req;
686 	for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
687 		char workbuf[64];
688 		int ifnlen;
689 
690 		ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
691 		if(ifnlen + 1 > sizeof ifr.ifr_name) {
692 			error = ENAMETOOLONG;
693 		} else {
694 			strcpy(ifr.ifr_name, workbuf);
695 		}
696 
697 		if ((ifa = ifp->if_addrlist) == 0) {
698 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
699 			error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
700 			    sizeof (ifr));
701 			if (error)
702 				break;
703 			space -= sizeof (ifr), ifrp++;
704 		} else
705 		    for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
706 			register struct sockaddr *sa = ifa->ifa_addr;
707 #ifdef COMPAT_43
708 			if (cmd == OSIOCGIFCONF) {
709 				struct osockaddr *osa =
710 					 (struct osockaddr *)&ifr.ifr_addr;
711 				ifr.ifr_addr = *sa;
712 				osa->sa_family = sa->sa_family;
713 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
714 						sizeof (ifr));
715 				ifrp++;
716 			} else
717 #endif
718 			if (sa->sa_len <= sizeof(*sa)) {
719 				ifr.ifr_addr = *sa;
720 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
721 						sizeof (ifr));
722 				ifrp++;
723 			} else {
724 				space -= sa->sa_len - sizeof(*sa);
725 				if (space < sizeof (ifr))
726 					break;
727 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
728 						sizeof (ifr.ifr_name));
729 				if (error == 0)
730 				    error = copyout((caddr_t)sa,
731 				      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
732 				ifrp = (struct ifreq *)
733 					(sa->sa_len + (caddr_t)&ifrp->ifr_addr);
734 			}
735 			if (error)
736 				break;
737 			space -= sizeof (ifr);
738 		}
739 	}
740 	ifc->ifc_len -= space;
741 	return (error);
742 }
743 
744 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
745