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