xref: /netbsd-src/sys/net/if.c (revision ce63d6c20fc4ec8ddc95c84bb229e3c4ecf82b69)
1 /*
2  * Copyright (c) 1980, 1986 Regents of the University of California.
3  * 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  *	from: @(#)if.c	7.14 (Berkeley) 4/20/91
34  *	$Id: if.c,v 1.3 1993/05/22 11:42:08 cgd Exp $
35  */
36 
37 #include "param.h"
38 #include "mbuf.h"
39 #include "systm.h"
40 #include "socket.h"
41 #include "socketvar.h"
42 #include "protosw.h"
43 #include "proc.h"
44 #include "kernel.h"
45 #include "ioctl.h"
46 
47 #include "if.h"
48 #include "af.h"
49 #include "if_dl.h"
50 #include "if_types.h"
51 
52 #include "ether.h"
53 
54 int	ifqmaxlen = IFQ_MAXLEN;
55 
56 /*
57  * Network interface utility routines.
58  *
59  * Routines with ifa_ifwith* names take sockaddr *'s as
60  * parameters.
61  */
62 
63 ifinit()
64 {
65 	register struct ifnet *ifp;
66 
67 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
68 		if (ifp->if_snd.ifq_maxlen == 0)
69 			ifp->if_snd.ifq_maxlen = ifqmaxlen;
70 	if_slowtimo();
71 }
72 
73 #ifdef vax
74 /*
75  * Call each interface on a Unibus reset.
76  */
77 ifubareset(uban)
78 	int uban;
79 {
80 	register struct ifnet *ifp;
81 
82 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
83 		if (ifp->if_reset)
84 			(*ifp->if_reset)(ifp->if_unit, uban);
85 }
86 #endif
87 
88 int if_index = 0;
89 struct ifaddr **ifnet_addrs;
90 static char *sprint_d();
91 
92 /*
93  * Attach an interface to the
94  * list of "active" interfaces.
95  */
96 if_attach(ifp)
97 	struct ifnet *ifp;
98 {
99 	unsigned socksize, ifasize;
100 	int namelen, unitlen;
101 	char workbuf[12], *unitname;
102 	register struct ifnet **p = &ifnet;
103 	register struct sockaddr_dl *sdl;
104 	register struct ifaddr *ifa;
105 	static int if_indexlim = 8;
106 	extern link_rtrequest(), ether_output();
107 
108 	while (*p)
109 		p = &((*p)->if_next);
110 	*p = ifp;
111 	ifp->if_index = ++if_index;
112 	if (ifnet_addrs == 0 || if_index >= if_indexlim) {
113 		unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
114 		struct ifaddr **q = (struct ifaddr **)
115 					malloc(n, M_IFADDR, M_WAITOK);
116 		if (ifnet_addrs) {
117 			bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
118 			free((caddr_t)ifnet_addrs, M_IFADDR);
119 		}
120 		ifnet_addrs = q;
121 	}
122 	/* XXX -- Temporary fix before changing 10 ethernet drivers */
123 	if (ifp->if_output == ether_output) {
124 		ifp->if_type = IFT_ETHER;
125 		ifp->if_addrlen = 6;
126 		ifp->if_hdrlen = 14;
127 	}
128 	/*
129 	 * create a Link Level name for this device
130 	 */
131 	unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
132 	namelen = strlen(ifp->if_name);
133 	unitlen = strlen(unitname);
134 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
135 	socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
136 			       unitlen + namelen + ifp->if_addrlen;
137 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
138 	socksize = ROUNDUP(socksize);
139 	if (socksize < sizeof(*sdl))
140 		socksize = sizeof(*sdl);
141 	ifasize = sizeof(*ifa) + 2 * socksize;
142 	ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
143 	if (ifa == 0)
144 		return;
145 	ifnet_addrs[if_index - 1] = ifa;
146 	bzero((caddr_t)ifa, ifasize);
147 	sdl = (struct sockaddr_dl *)(ifa + 1);
148 	ifa->ifa_addr = (struct sockaddr *)sdl;
149 	ifa->ifa_ifp = ifp;
150 	sdl->sdl_len = socksize;
151 	sdl->sdl_family = AF_LINK;
152 	bcopy(ifp->if_name, sdl->sdl_data, namelen);
153 	bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
154 	sdl->sdl_nlen = (namelen += unitlen);
155 	sdl->sdl_index = ifp->if_index;
156 	sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
157 	ifa->ifa_netmask = (struct sockaddr *)sdl;
158 	sdl->sdl_len = socksize - ifp->if_addrlen;
159 	while (namelen != 0)
160 		sdl->sdl_data[--namelen] = 0xff;
161 	ifa->ifa_next = ifp->if_addrlist;
162 	ifa->ifa_rtrequest = link_rtrequest;
163 	ifp->if_addrlist = ifa;
164 }
165 /*
166  * Locate an interface based on a complete address.
167  */
168 /*ARGSUSED*/
169 struct ifaddr *
170 ifa_ifwithaddr(addr)
171 	register struct sockaddr *addr;
172 {
173 	register struct ifnet *ifp;
174 	register struct ifaddr *ifa;
175 
176 #define	equal(a1, a2) \
177   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
178 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
179 	    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
180 		if (ifa->ifa_addr->sa_family != addr->sa_family)
181 			continue;
182 		if (equal(addr, ifa->ifa_addr))
183 			return (ifa);
184 		if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
185 		    equal(ifa->ifa_broadaddr, addr))
186 			return (ifa);
187 	}
188 	return ((struct ifaddr *)0);
189 }
190 /*
191  * Locate the point to point interface with a given destination address.
192  */
193 /*ARGSUSED*/
194 struct ifaddr *
195 ifa_ifwithdstaddr(addr)
196 	register struct sockaddr *addr;
197 {
198 	register struct ifnet *ifp;
199 	register struct ifaddr *ifa;
200 
201 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
202 	    if (ifp->if_flags & IFF_POINTOPOINT)
203 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
204 			if (ifa->ifa_addr->sa_family != addr->sa_family)
205 				continue;
206 			if (equal(addr, ifa->ifa_dstaddr))
207 				return (ifa);
208 	}
209 	return ((struct ifaddr *)0);
210 }
211 
212 /*
213  * Find an interface on a specific network.  If many, choice
214  * is first found.
215  */
216 struct ifaddr *
217 ifa_ifwithnet(addr)
218 	struct sockaddr *addr;
219 {
220 	register struct ifnet *ifp;
221 	register struct ifaddr *ifa;
222 	u_int af = addr->sa_family;
223 
224 	if (af >= AF_MAX)
225 		return (0);
226 	if (af == AF_LINK) {
227 	    register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
228 	    if (sdl->sdl_index && sdl->sdl_index <= if_index)
229 		return (ifnet_addrs[sdl->sdl_index - 1]);
230 	}
231 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
232 	    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
233 		register char *cp, *cp2, *cp3;
234 		register char *cplim;
235 		if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
236 			continue;
237 		cp = addr->sa_data;
238 		cp2 = ifa->ifa_addr->sa_data;
239 		cp3 = ifa->ifa_netmask->sa_data;
240 		cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
241 		for (; cp3 < cplim; cp3++)
242 			if ((*cp++ ^ *cp2++) & *cp3)
243 				break;
244 		if (cp3 == cplim)
245 			return (ifa);
246 	    }
247 	return ((struct ifaddr *)0);
248 }
249 
250 /*
251  * Find an interface using a specific address family
252  */
253 struct ifaddr *
254 ifa_ifwithaf(af)
255 	register int af;
256 {
257 	register struct ifnet *ifp;
258 	register struct ifaddr *ifa;
259 
260 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
261 	    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
262 		if (ifa->ifa_addr->sa_family == af)
263 			return (ifa);
264 	return ((struct ifaddr *)0);
265 }
266 
267 /*
268  * Find an interface address specific to an interface best matching
269  * a given address.
270  */
271 struct ifaddr *
272 ifaof_ifpforaddr(addr, ifp)
273 	struct sockaddr *addr;
274 	register struct ifnet *ifp;
275 {
276 	register struct ifaddr *ifa;
277 	register char *cp, *cp2, *cp3;
278 	register char *cplim;
279 	struct ifaddr *ifa_maybe = 0;
280 	u_int af = addr->sa_family;
281 
282 	if (af >= AF_MAX)
283 		return (0);
284 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
285 		if (ifa->ifa_addr->sa_family != af)
286 			continue;
287 		ifa_maybe = ifa;
288 		if (ifa->ifa_netmask == 0) {
289 			if (equal(addr, ifa->ifa_addr) ||
290 			    (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
291 				return (ifa);
292 			continue;
293 		}
294 		cp = addr->sa_data;
295 		cp2 = ifa->ifa_addr->sa_data;
296 		cp3 = ifa->ifa_netmask->sa_data;
297 		cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
298 		for (; cp3 < cplim; cp3++)
299 			if ((*cp++ ^ *cp2++) & *cp3)
300 				break;
301 		if (cp3 == cplim)
302 			return (ifa);
303 	}
304 	return (ifa_maybe);
305 }
306 #include "route.h"
307 /*
308  * Default action when installing a route with a Link Level gateway.
309  * Lookup an appropriate real ifa to point to.
310  * This should be moved to /sys/net/link.c eventually.
311  */
312 link_rtrequest(cmd, rt, sa)
313 register struct rtentry *rt;
314 struct sockaddr *sa;
315 {
316 	register struct ifaddr *ifa;
317 	struct sockaddr *dst;
318 	struct ifnet *ifp, *oldifnet = ifnet;
319 
320 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
321 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
322 		return;
323 	if (ifa = ifaof_ifpforaddr(dst, ifp)) {
324 		rt->rt_ifa = ifa;
325 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
326 			ifa->ifa_rtrequest(cmd, rt, sa);
327 	}
328 }
329 
330 /*
331  * Mark an interface down and notify protocols of
332  * the transition.
333  * NOTE: must be called at splnet or eqivalent.
334  */
335 if_down(ifp)
336 	register struct ifnet *ifp;
337 {
338 	register struct ifaddr *ifa;
339 
340 	ifp->if_flags &= ~IFF_UP;
341 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
342 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
343 	if_qflush(&ifp->if_snd);
344 }
345 
346 /*
347  * Flush an interface queue.
348  */
349 if_qflush(ifq)
350 	register struct ifqueue *ifq;
351 {
352 	register struct mbuf *m, *n;
353 
354 	n = ifq->ifq_head;
355 	while (m = n) {
356 		n = m->m_act;
357 		m_freem(m);
358 	}
359 	ifq->ifq_head = 0;
360 	ifq->ifq_tail = 0;
361 	ifq->ifq_len = 0;
362 }
363 
364 /*
365  * Handle interface watchdog timer routines.  Called
366  * from softclock, we decrement timers (if set) and
367  * call the appropriate interface routine on expiration.
368  */
369 if_slowtimo()
370 {
371 	register struct ifnet *ifp;
372 	int s = splimp();
373 
374 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
375 		if (ifp->if_timer == 0 || --ifp->if_timer)
376 			continue;
377 		if (ifp->if_watchdog)
378 			(*ifp->if_watchdog)(ifp->if_unit);
379 	}
380 	splx(s);
381 	timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
382 }
383 
384 /*
385  * Map interface name to
386  * interface structure pointer.
387  */
388 struct ifnet *
389 ifunit(name)
390 	register char *name;
391 {
392 	register char *cp;
393 	register struct ifnet *ifp;
394 	int unit;
395 	unsigned len;
396 	char *ep, c;
397 
398 	for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
399 		if (*cp >= '0' && *cp <= '9')
400 			break;
401 	if (*cp == '\0' || cp == name + IFNAMSIZ)
402 		return ((struct ifnet *)0);
403 	/*
404 	 * Save first char of unit, and pointer to it,
405 	 * so we can put a null there to avoid matching
406 	 * initial substrings of interface names.
407 	 */
408 	len = cp - name + 1;
409 	c = *cp;
410 	ep = cp;
411 	for (unit = 0; *cp >= '0' && *cp <= '9'; )
412 		unit = unit * 10 + *cp++ - '0';
413 	*ep = 0;
414 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
415 		if (bcmp(ifp->if_name, name, len))
416 			continue;
417 		if (unit == ifp->if_unit)
418 			break;
419 	}
420 	*ep = c;
421 	return (ifp);
422 }
423 
424 /*
425  * Interface ioctls.
426  */
427 ifioctl(so, cmd, data, p)
428 	struct socket *so;
429 	int cmd;
430 	caddr_t data;
431 	struct proc *p;
432 {
433 	register struct ifnet *ifp;
434 	register struct ifreq *ifr;
435 	int error;
436 
437 	switch (cmd) {
438 
439 	case SIOCGIFCONF:
440 	case OSIOCGIFCONF:
441 		return (ifconf(cmd, data));
442 
443 #if defined(INET) && NETHER > 0
444 	case SIOCSARP:
445 	case SIOCDARP:
446 		if (error = suser(p->p_ucred, &p->p_acflag))
447 			return (error);
448 		/* FALL THROUGH */
449 	case SIOCGARP:
450 	case OSIOCGARP:
451 		return (arpioctl(cmd, data));
452 #endif
453 	}
454 	ifr = (struct ifreq *)data;
455 	ifp = ifunit(ifr->ifr_name);
456 	if (ifp == 0)
457 		return (ENXIO);
458 	switch (cmd) {
459 
460 	case SIOCGIFFLAGS:
461 		ifr->ifr_flags = ifp->if_flags;
462 		break;
463 
464 	case SIOCGIFMETRIC:
465 		ifr->ifr_metric = ifp->if_metric;
466 		break;
467 
468 	case SIOCSIFFLAGS:
469 		if (error = suser(p->p_ucred, &p->p_acflag))
470 			return (error);
471 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
472 			int s = splimp();
473 			if_down(ifp);
474 			splx(s);
475 		}
476 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
477 			(ifr->ifr_flags &~ IFF_CANTCHANGE);
478 		if (ifp->if_ioctl)
479 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
480 		break;
481 
482 	case SIOCSIFMETRIC:
483 		if (error = suser(p->p_ucred, &p->p_acflag))
484 			return (error);
485 		ifp->if_metric = ifr->ifr_metric;
486 		break;
487 
488 	default:
489 		if (so->so_proto == 0)
490 			return (EOPNOTSUPP);
491 #ifndef COMPAT_43
492 		return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
493 			cmd, data, ifp));
494 #else
495 	    {
496 		int ocmd = cmd;
497 
498 		switch (cmd) {
499 
500 		case SIOCSIFDSTADDR:
501 		case SIOCSIFADDR:
502 		case SIOCSIFBRDADDR:
503 		case SIOCSIFNETMASK:
504 #if BYTE_ORDER != BIG_ENDIAN
505 			if (ifr->ifr_addr.sa_family == 0 &&
506 			    ifr->ifr_addr.sa_len < 16) {
507 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
508 				ifr->ifr_addr.sa_len = 16;
509 			}
510 #else
511 			if (ifr->ifr_addr.sa_len == 0)
512 				ifr->ifr_addr.sa_len = 16;
513 #endif
514 			break;
515 
516 		case OSIOCGIFADDR:
517 			cmd = SIOCGIFADDR;
518 			break;
519 
520 		case OSIOCGIFDSTADDR:
521 			cmd = SIOCGIFDSTADDR;
522 			break;
523 
524 		case OSIOCGIFBRDADDR:
525 			cmd = SIOCGIFBRDADDR;
526 			break;
527 
528 		case OSIOCGIFNETMASK:
529 			cmd = SIOCGIFNETMASK;
530 		}
531 		error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
532 							    cmd, data, ifp));
533 		switch (ocmd) {
534 
535 		case OSIOCGIFADDR:
536 		case OSIOCGIFDSTADDR:
537 		case OSIOCGIFBRDADDR:
538 		case OSIOCGIFNETMASK:
539 			*(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
540 		}
541 		return (error);
542 
543 	    }
544 #endif
545 	}
546 	return (0);
547 }
548 
549 /*
550  * Return interface configuration
551  * of system.  List may be used
552  * in later ioctl's (above) to get
553  * other information.
554  */
555 /*ARGSUSED*/
556 ifconf(cmd, data)
557 	int cmd;
558 	caddr_t data;
559 {
560 	register struct ifconf *ifc = (struct ifconf *)data;
561 	register struct ifnet *ifp = ifnet;
562 	register struct ifaddr *ifa;
563 	register char *cp, *ep;
564 	struct ifreq ifr, *ifrp;
565 	int space = ifc->ifc_len, error = 0;
566 
567 	ifrp = ifc->ifc_req;
568 	ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
569 	for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
570 		bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
571 		for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
572 			;
573 		*cp++ = '0' + ifp->if_unit; *cp = '\0';
574 		if ((ifa = ifp->if_addrlist) == 0) {
575 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
576 			error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
577 			if (error)
578 				break;
579 			space -= sizeof (ifr), ifrp++;
580 		} else
581 		    for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
582 			register struct sockaddr *sa = ifa->ifa_addr;
583 #ifdef COMPAT_43
584 			if (cmd == OSIOCGIFCONF) {
585 				struct osockaddr *osa =
586 					 (struct osockaddr *)&ifr.ifr_addr;
587 				ifr.ifr_addr = *sa;
588 				osa->sa_family = sa->sa_family;
589 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
590 						sizeof (ifr));
591 				ifrp++;
592 			} else
593 #endif
594 			if (sa->sa_len <= sizeof(*sa)) {
595 				ifr.ifr_addr = *sa;
596 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
597 						sizeof (ifr));
598 				ifrp++;
599 			} else {
600 				space -= sa->sa_len - sizeof(*sa);
601 				if (space < sizeof (ifr))
602 					break;
603 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
604 						sizeof (ifr.ifr_name));
605 				if (error == 0)
606 				    error = copyout((caddr_t)sa,
607 				      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
608 				ifrp = (struct ifreq *)
609 					(sa->sa_len + (caddr_t)&ifrp->ifr_addr);
610 			}
611 			if (error)
612 				break;
613 			space -= sizeof (ifr);
614 		}
615 	}
616 	ifc->ifc_len -= space;
617 	return (error);
618 }
619 
620 static char *
621 sprint_d(n, buf, buflen)
622 	u_int n;
623 	char *buf;
624 	int buflen;
625 {
626 	register char *cp = buf + buflen - 1;
627 
628 	*cp = 0;
629 	do {
630 		cp--;
631 		*cp = "0123456789"[n % 10];
632 		n /= 10;
633 	} while (n != 0);
634 	return (cp);
635 }
636