xref: /original-bsd/sys/net/if.c (revision e59fb703)
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.14 (Berkeley) 04/20/91
8  */
9 
10 #include "param.h"
11 #include "mbuf.h"
12 #include "systm.h"
13 #include "socket.h"
14 #include "socketvar.h"
15 #include "protosw.h"
16 #include "proc.h"
17 #include "kernel.h"
18 #include "ioctl.h"
19 
20 #include "if.h"
21 #include "af.h"
22 #include "if_dl.h"
23 #include "if_types.h"
24 
25 #include "ether.h"
26 
27 int	ifqmaxlen = IFQ_MAXLEN;
28 
29 /*
30  * Network interface utility routines.
31  *
32  * Routines with ifa_ifwith* names take sockaddr *'s as
33  * parameters.
34  */
35 
36 ifinit()
37 {
38 	register struct ifnet *ifp;
39 
40 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
41 		if (ifp->if_snd.ifq_maxlen == 0)
42 			ifp->if_snd.ifq_maxlen = ifqmaxlen;
43 	if_slowtimo();
44 }
45 
46 #ifdef vax
47 /*
48  * Call each interface on a Unibus reset.
49  */
50 ifubareset(uban)
51 	int uban;
52 {
53 	register struct ifnet *ifp;
54 
55 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
56 		if (ifp->if_reset)
57 			(*ifp->if_reset)(ifp->if_unit, uban);
58 }
59 #endif
60 
61 int if_index = 0;
62 struct ifaddr **ifnet_addrs;
63 static char *sprint_d();
64 
65 /*
66  * Attach an interface to the
67  * list of "active" interfaces.
68  */
69 if_attach(ifp)
70 	struct ifnet *ifp;
71 {
72 	unsigned socksize, ifasize;
73 	int namelen, unitlen;
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 link_rtrequest(), ether_output();
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 	/* XXX -- Temporary fix before changing 10 ethernet drivers */
96 	if (ifp->if_output == ether_output) {
97 		ifp->if_type = IFT_ETHER;
98 		ifp->if_addrlen = 6;
99 		ifp->if_hdrlen = 14;
100 	}
101 	/*
102 	 * create a Link Level name for this device
103 	 */
104 	unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
105 	namelen = strlen(ifp->if_name);
106 	unitlen = strlen(unitname);
107 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
108 	socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
109 			       unitlen + namelen + ifp->if_addrlen;
110 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
111 	socksize = ROUNDUP(socksize);
112 	if (socksize < sizeof(*sdl))
113 		socksize = sizeof(*sdl);
114 	ifasize = sizeof(*ifa) + 2 * socksize;
115 	ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
116 	if (ifa == 0)
117 		return;
118 	ifnet_addrs[if_index - 1] = ifa;
119 	bzero((caddr_t)ifa, ifasize);
120 	sdl = (struct sockaddr_dl *)(ifa + 1);
121 	ifa->ifa_addr = (struct sockaddr *)sdl;
122 	ifa->ifa_ifp = ifp;
123 	sdl->sdl_len = socksize;
124 	sdl->sdl_family = AF_LINK;
125 	bcopy(ifp->if_name, sdl->sdl_data, namelen);
126 	bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
127 	sdl->sdl_nlen = (namelen += unitlen);
128 	sdl->sdl_index = ifp->if_index;
129 	sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
130 	ifa->ifa_netmask = (struct sockaddr *)sdl;
131 	sdl->sdl_len = socksize - ifp->if_addrlen;
132 	while (namelen != 0)
133 		sdl->sdl_data[--namelen] = 0xff;
134 	ifa->ifa_next = ifp->if_addrlist;
135 	ifa->ifa_rtrequest = link_rtrequest;
136 	ifp->if_addrlist = ifa;
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 first 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 	u_int af = addr->sa_family;
196 
197 	if (af >= AF_MAX)
198 		return (0);
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 		register char *cplim;
208 		if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
209 			continue;
210 		cp = addr->sa_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 		for (; cp3 < cplim; cp3++)
215 			if ((*cp++ ^ *cp2++) & *cp3)
216 				break;
217 		if (cp3 == cplim)
218 			return (ifa);
219 	    }
220 	return ((struct ifaddr *)0);
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 #include "route.h"
280 /*
281  * Default action when installing a route with a Link Level gateway.
282  * Lookup an appropriate real ifa to point to.
283  * This should be moved to /sys/net/link.c eventually.
284  */
285 link_rtrequest(cmd, rt, sa)
286 register struct rtentry *rt;
287 struct sockaddr *sa;
288 {
289 	register struct ifaddr *ifa;
290 	struct sockaddr *dst;
291 	struct ifnet *ifp, *oldifnet = ifnet;
292 
293 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
294 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
295 		return;
296 	if (ifa = ifaof_ifpforaddr(dst, ifp)) {
297 		rt->rt_ifa = ifa;
298 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
299 			ifa->ifa_rtrequest(cmd, rt, sa);
300 	}
301 }
302 
303 /*
304  * Mark an interface down and notify protocols of
305  * the transition.
306  * NOTE: must be called at splnet or eqivalent.
307  */
308 if_down(ifp)
309 	register struct ifnet *ifp;
310 {
311 	register struct ifaddr *ifa;
312 
313 	ifp->if_flags &= ~IFF_UP;
314 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
315 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
316 	if_qflush(&ifp->if_snd);
317 }
318 
319 /*
320  * Flush an interface queue.
321  */
322 if_qflush(ifq)
323 	register struct ifqueue *ifq;
324 {
325 	register struct mbuf *m, *n;
326 
327 	n = ifq->ifq_head;
328 	while (m = n) {
329 		n = m->m_act;
330 		m_freem(m);
331 	}
332 	ifq->ifq_head = 0;
333 	ifq->ifq_tail = 0;
334 	ifq->ifq_len = 0;
335 }
336 
337 /*
338  * Handle interface watchdog timer routines.  Called
339  * from softclock, we decrement timers (if set) and
340  * call the appropriate interface routine on expiration.
341  */
342 if_slowtimo()
343 {
344 	register struct ifnet *ifp;
345 	int s = splimp();
346 
347 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
348 		if (ifp->if_timer == 0 || --ifp->if_timer)
349 			continue;
350 		if (ifp->if_watchdog)
351 			(*ifp->if_watchdog)(ifp->if_unit);
352 	}
353 	splx(s);
354 	timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
355 }
356 
357 /*
358  * Map interface name to
359  * interface structure pointer.
360  */
361 struct ifnet *
362 ifunit(name)
363 	register char *name;
364 {
365 	register char *cp;
366 	register struct ifnet *ifp;
367 	int unit;
368 	unsigned len;
369 	char *ep, c;
370 
371 	for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
372 		if (*cp >= '0' && *cp <= '9')
373 			break;
374 	if (*cp == '\0' || cp == name + IFNAMSIZ)
375 		return ((struct ifnet *)0);
376 	/*
377 	 * Save first char of unit, and pointer to it,
378 	 * so we can put a null there to avoid matching
379 	 * initial substrings of interface names.
380 	 */
381 	len = cp - name + 1;
382 	c = *cp;
383 	ep = cp;
384 	for (unit = 0; *cp >= '0' && *cp <= '9'; )
385 		unit = unit * 10 + *cp++ - '0';
386 	*ep = 0;
387 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
388 		if (bcmp(ifp->if_name, name, len))
389 			continue;
390 		if (unit == ifp->if_unit)
391 			break;
392 	}
393 	*ep = c;
394 	return (ifp);
395 }
396 
397 /*
398  * Interface ioctls.
399  */
400 ifioctl(so, cmd, data, p)
401 	struct socket *so;
402 	int cmd;
403 	caddr_t data;
404 	struct proc *p;
405 {
406 	register struct ifnet *ifp;
407 	register struct ifreq *ifr;
408 	int error;
409 
410 	switch (cmd) {
411 
412 	case SIOCGIFCONF:
413 	case OSIOCGIFCONF:
414 		return (ifconf(cmd, data));
415 
416 #if defined(INET) && NETHER > 0
417 	case SIOCSARP:
418 	case SIOCDARP:
419 		if (error = suser(p->p_ucred, &p->p_acflag))
420 			return (error);
421 		/* FALL THROUGH */
422 	case SIOCGARP:
423 	case OSIOCGARP:
424 		return (arpioctl(cmd, data));
425 #endif
426 	}
427 	ifr = (struct ifreq *)data;
428 	ifp = ifunit(ifr->ifr_name);
429 	if (ifp == 0)
430 		return (ENXIO);
431 	switch (cmd) {
432 
433 	case SIOCGIFFLAGS:
434 		ifr->ifr_flags = ifp->if_flags;
435 		break;
436 
437 	case SIOCGIFMETRIC:
438 		ifr->ifr_metric = ifp->if_metric;
439 		break;
440 
441 	case SIOCSIFFLAGS:
442 		if (error = suser(p->p_ucred, &p->p_acflag))
443 			return (error);
444 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
445 			int s = splimp();
446 			if_down(ifp);
447 			splx(s);
448 		}
449 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
450 			(ifr->ifr_flags &~ IFF_CANTCHANGE);
451 		if (ifp->if_ioctl)
452 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
453 		break;
454 
455 	case SIOCSIFMETRIC:
456 		if (error = suser(p->p_ucred, &p->p_acflag))
457 			return (error);
458 		ifp->if_metric = ifr->ifr_metric;
459 		break;
460 
461 	default:
462 		if (so->so_proto == 0)
463 			return (EOPNOTSUPP);
464 #ifndef COMPAT_43
465 		return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
466 			cmd, data, ifp));
467 #else
468 	    {
469 		int ocmd = cmd;
470 
471 		switch (cmd) {
472 
473 		case SIOCSIFDSTADDR:
474 		case SIOCSIFADDR:
475 		case SIOCSIFBRDADDR:
476 		case SIOCSIFNETMASK:
477 #if BYTE_ORDER != BIG_ENDIAN
478 			if (ifr->ifr_addr.sa_family == 0 &&
479 			    ifr->ifr_addr.sa_len < 16) {
480 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
481 				ifr->ifr_addr.sa_len = 16;
482 			}
483 #else
484 			if (ifr->ifr_addr.sa_len == 0)
485 				ifr->ifr_addr.sa_len = 16;
486 #endif
487 			break;
488 
489 		case OSIOCGIFADDR:
490 			cmd = SIOCGIFADDR;
491 			break;
492 
493 		case OSIOCGIFDSTADDR:
494 			cmd = SIOCGIFDSTADDR;
495 			break;
496 
497 		case OSIOCGIFBRDADDR:
498 			cmd = SIOCGIFBRDADDR;
499 			break;
500 
501 		case OSIOCGIFNETMASK:
502 			cmd = SIOCGIFNETMASK;
503 		}
504 		error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
505 							    cmd, data, ifp));
506 		switch (ocmd) {
507 
508 		case OSIOCGIFADDR:
509 		case OSIOCGIFDSTADDR:
510 		case OSIOCGIFBRDADDR:
511 		case OSIOCGIFNETMASK:
512 			*(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
513 		}
514 		return (error);
515 
516 	    }
517 #endif
518 	}
519 	return (0);
520 }
521 
522 /*
523  * Return interface configuration
524  * of system.  List may be used
525  * in later ioctl's (above) to get
526  * other information.
527  */
528 /*ARGSUSED*/
529 ifconf(cmd, data)
530 	int cmd;
531 	caddr_t data;
532 {
533 	register struct ifconf *ifc = (struct ifconf *)data;
534 	register struct ifnet *ifp = ifnet;
535 	register struct ifaddr *ifa;
536 	register char *cp, *ep;
537 	struct ifreq ifr, *ifrp;
538 	int space = ifc->ifc_len, error = 0;
539 
540 	ifrp = ifc->ifc_req;
541 	ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
542 	for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
543 		bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
544 		for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
545 			;
546 		*cp++ = '0' + ifp->if_unit; *cp = '\0';
547 		if ((ifa = ifp->if_addrlist) == 0) {
548 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
549 			error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
550 			if (error)
551 				break;
552 			space -= sizeof (ifr), ifrp++;
553 		} else
554 		    for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
555 			register struct sockaddr *sa = ifa->ifa_addr;
556 #ifdef COMPAT_43
557 			if (cmd == OSIOCGIFCONF) {
558 				struct osockaddr *osa =
559 					 (struct osockaddr *)&ifr.ifr_addr;
560 				ifr.ifr_addr = *sa;
561 				osa->sa_family = sa->sa_family;
562 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
563 						sizeof (ifr));
564 				ifrp++;
565 			} else
566 #endif
567 			if (sa->sa_len <= sizeof(*sa)) {
568 				ifr.ifr_addr = *sa;
569 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
570 						sizeof (ifr));
571 				ifrp++;
572 			} else {
573 				space -= sa->sa_len - sizeof(*sa);
574 				if (space < sizeof (ifr))
575 					break;
576 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
577 						sizeof (ifr.ifr_name));
578 				if (error == 0)
579 				    error = copyout((caddr_t)sa,
580 				      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
581 				ifrp = (struct ifreq *)
582 					(sa->sa_len + (caddr_t)&ifrp->ifr_addr);
583 			}
584 			if (error)
585 				break;
586 			space -= sizeof (ifr);
587 		}
588 	}
589 	ifc->ifc_len -= space;
590 	return (error);
591 }
592 
593 static char *
594 sprint_d(n, buf, buflen)
595 	u_int n;
596 	char *buf;
597 	int buflen;
598 {
599 	register char *cp = buf + buflen - 1;
600 
601 	*cp = 0;
602 	do {
603 		cp--;
604 		*cp = "0123456789"[n % 10];
605 		n /= 10;
606 	} while (n != 0);
607 	return (cp);
608 }
609