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