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