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