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