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