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