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