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