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