|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1980, 1986, 1993
24: * The Regents of the University of California. All rights reserved.
25: *
26: * Redistribution and use in source and binary forms, with or without
27: * modification, are permitted provided that the following conditions
28: * are met:
29: * 1. Redistributions of source code must retain the above copyright
30: * notice, this list of conditions and the following disclaimer.
31: * 2. Redistributions in binary form must reproduce the above copyright
32: * notice, this list of conditions and the following disclaimer in the
33: * documentation and/or other materials provided with the distribution.
34: * 3. All advertising materials mentioning features or use of this software
35: * must display the following acknowledgement:
36: * This product includes software developed by the University of
37: * California, Berkeley and its contributors.
38: * 4. Neither the name of the University nor the names of its contributors
39: * may be used to endorse or promote products derived from this software
40: * without specific prior written permission.
41: *
42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52: * SUCH DAMAGE.
53: *
54: * @(#)if.c 8.3 (Berkeley) 1/4/94
55: */
56:
57: /*
58: #include "opt_compat.h"
59: */
60:
61: #include <sys/param.h>
62: #include <sys/malloc.h>
63: #include <sys/mbuf.h>
64: #include <sys/systm.h>
65: #include <sys/proc.h>
66: #include <sys/socket.h>
67: #include <sys/socketvar.h>
68: #include <sys/protosw.h>
69: #include <sys/kernel.h>
70: #include <sys/sockio.h>
71: #include <sys/syslog.h>
72: #include <sys/sysctl.h>
73: #include <net/if.h>
74: #include <net/if_dl.h>
75: #include <net/radix.h>
76: #include <net/if_blue.h>
77: #include <netinet/in.h>
78: #include <net/dlil.h>
79:
80: /*
81: * System initialization
82: */
83:
84: static int ifconf __P((u_long, caddr_t));
85: static void if_qflush __P((struct ifqueue *));
86: static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
87:
88: MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
89: MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
90:
91: int ifqmaxlen = IFQ_MAXLEN;
92: struct ifnethead ifnet; /* depend on static init XXX */
93:
94: /*
95: * Network interface utility routines.
96: *
97: * Routines with ifa_ifwith* names take sockaddr *'s as
98: * parameters.
99: *
100: * This routine assumes that it will be called at splimp() or higher.
101: */
102: /* ARGSUSED*/
103:
104:
105: int if_index = 0;
106: struct ifaddr **ifnet_addrs;
107:
108:
109: /*
110: * Attach an interface to the
111: * list of "active" interfaces.
112: */
113: void
114: old_if_attach(ifp)
115: struct ifnet *ifp;
116: {
117: unsigned socksize, ifasize;
118: int namelen, masklen;
119: char workbuf[64];
120: register struct sockaddr_dl *sdl;
121: register struct ifaddr *ifa;
122: static int if_indexlim = 8;
123:
124:
125: if (ifp->if_snd.ifq_maxlen == 0)
126: ifp->if_snd.ifq_maxlen = ifqmaxlen;
127:
128: TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
129: ifp->if_index = ++if_index;
130: /*
131: * XXX -
132: * The old code would work if the interface passed a pre-existing
133: * chain of ifaddrs to this code. We don't trust our callers to
134: * properly initialize the tailq, however, so we no longer allow
135: * this unlikely case.
136: */
137: TAILQ_INIT(&ifp->if_addrhead);
138: LIST_INIT(&ifp->if_multiaddrs);
139: getmicrotime(&ifp->if_lastchange);
140: if (ifnet_addrs == 0 || if_index >= if_indexlim) {
141: unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
142: struct ifaddr **q = (struct ifaddr **)
143: _MALLOC(n, M_IFADDR, M_WAITOK);
144: bzero((caddr_t)q, n);
145: if (ifnet_addrs) {
146: bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
147: FREE((caddr_t)ifnet_addrs, M_IFADDR);
148: }
149: ifnet_addrs = q;
150: }
151: /*
152: * create a Link Level name for this device
153: */
154: namelen = snprintf(workbuf, sizeof(workbuf),
155: "%s%d", ifp->if_name, ifp->if_unit);
156: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
157: masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
158: socksize = masklen + ifp->if_addrlen;
159: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
160: if (socksize < sizeof(*sdl))
161: socksize = sizeof(*sdl);
162: socksize = ROUNDUP(socksize);
163: ifasize = sizeof(*ifa) + 2 * socksize;
164: ifa = (struct ifaddr *) _MALLOC(ifasize, M_IFADDR, M_WAITOK);
165: if (ifa) {
166: bzero((caddr_t)ifa, ifasize);
167: sdl = (struct sockaddr_dl *)(ifa + 1);
168: sdl->sdl_len = socksize;
169: sdl->sdl_family = AF_LINK;
170: bcopy(workbuf, sdl->sdl_data, namelen);
171: sdl->sdl_nlen = namelen;
172: sdl->sdl_index = ifp->if_index;
173: sdl->sdl_type = ifp->if_type;
174: ifnet_addrs[if_index - 1] = ifa;
175: ifa->ifa_ifp = ifp;
176: ifa->ifa_rtrequest = link_rtrequest;
177: ifa->ifa_addr = (struct sockaddr *)sdl;
178: sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
179: ifa->ifa_netmask = (struct sockaddr *)sdl;
180: sdl->sdl_len = masklen;
181: while (namelen != 0)
182: sdl->sdl_data[--namelen] = 0xff;
183: TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
184: }
185: }
186: /*
187: * Locate an interface based on a complete address.
188: */
189: /*ARGSUSED*/
190: struct ifaddr *
191: ifa_ifwithaddr(addr)
192: register struct sockaddr *addr;
193: {
194: register struct ifnet *ifp;
195: register struct ifaddr *ifa;
196:
197: #define equal(a1, a2) \
198: (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
199: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
200: for (ifa = ifp->if_addrhead.tqh_first; ifa;
201: ifa = ifa->ifa_link.tqe_next) {
202: if (ifa->ifa_addr->sa_family != addr->sa_family)
203: continue;
204: if (equal(addr, ifa->ifa_addr))
205: return (ifa);
206: if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
207: equal(ifa->ifa_broadaddr, addr))
208: return (ifa);
209: }
210: return ((struct ifaddr *)0);
211: }
212: /*
213: * Locate the point to point interface with a given destination address.
214: */
215: /*ARGSUSED*/
216: struct ifaddr *
217: ifa_ifwithdstaddr(addr)
218: register struct sockaddr *addr;
219: {
220: register struct ifnet *ifp;
221: register struct ifaddr *ifa;
222:
223: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
224: if (ifp->if_flags & IFF_POINTOPOINT)
225: for (ifa = ifp->if_addrhead.tqh_first; ifa;
226: ifa = ifa->ifa_link.tqe_next) {
227: if (ifa->ifa_addr->sa_family != addr->sa_family)
228: continue;
229: if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
230: return (ifa);
231: }
232: return ((struct ifaddr *)0);
233: }
234:
235: /*
236: * Find an interface on a specific network. If many, choice
237: * is most specific found.
238: */
239: struct ifaddr *
240: ifa_ifwithnet(addr)
241: struct sockaddr *addr;
242: {
243: register struct ifnet *ifp;
244: register struct ifaddr *ifa;
245: struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
246: u_int af = addr->sa_family;
247: char *addr_data = addr->sa_data, *cplim;
248:
249: /*
250: * AF_LINK addresses can be looked up directly by their index number,
251: * so do that if we can.
252: */
253: if (af == AF_LINK) {
254: register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
255: if (sdl->sdl_index && sdl->sdl_index <= if_index)
256: return (ifnet_addrs[sdl->sdl_index - 1]);
257: }
258:
259: /*
260: * Scan though each interface, looking for ones that have
261: * addresses in this address family.
262: */
263: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
264: for (ifa = ifp->if_addrhead.tqh_first; ifa;
265: ifa = ifa->ifa_link.tqe_next) {
266: register char *cp, *cp2, *cp3;
267:
268: if (ifa->ifa_addr->sa_family != af)
269: next: continue;
270: if (ifp->if_flags & IFF_POINTOPOINT) {
271: /*
272: * This is a bit broken as it doesn't
273: * take into account that the remote end may
274: * be a single node in the network we are
275: * looking for.
276: * The trouble is that we don't know the
277: * netmask for the remote end.
278: */
279: if (ifa->ifa_dstaddr != 0
280: && equal(addr, ifa->ifa_dstaddr))
281: return (ifa);
282: } else {
283: /*
284: * if we have a special address handler,
285: * then use it instead of the generic one.
286: */
287: if (ifa->ifa_claim_addr) {
288: if ((*ifa->ifa_claim_addr)(ifa, addr)) {
289: return (ifa);
290: } else {
291: continue;
292: }
293: }
294:
295: /*
296: * Scan all the bits in the ifa's address.
297: * If a bit dissagrees with what we are
298: * looking for, mask it with the netmask
299: * to see if it really matters.
300: * (A byte at a time)
301: */
302: if (ifa->ifa_netmask == 0)
303: continue;
304: cp = addr_data;
305: cp2 = ifa->ifa_addr->sa_data;
306: cp3 = ifa->ifa_netmask->sa_data;
307: cplim = ifa->ifa_netmask->sa_len
308: + (char *)ifa->ifa_netmask;
309: while (cp3 < cplim)
310: if ((*cp++ ^ *cp2++) & *cp3++)
311: goto next; /* next address! */
312: /*
313: * If the netmask of what we just found
314: * is more specific than what we had before
315: * (if we had one) then remember the new one
316: * before continuing to search
317: * for an even better one.
318: */
319: if (ifa_maybe == 0 ||
320: rn_refines((caddr_t)ifa->ifa_netmask,
321: (caddr_t)ifa_maybe->ifa_netmask))
322: ifa_maybe = ifa;
323: }
324: }
325: }
326: return (ifa_maybe);
327: }
328:
329: /*
330: * Find an interface address specific to an interface best matching
331: * a given address.
332: */
333: struct ifaddr *
334: ifaof_ifpforaddr(addr, ifp)
335: struct sockaddr *addr;
336: register struct ifnet *ifp;
337: {
338: register struct ifaddr *ifa;
339: register char *cp, *cp2, *cp3;
340: register char *cplim;
341: struct ifaddr *ifa_maybe = 0;
342: u_int af = addr->sa_family;
343:
344: if (af >= AF_MAX)
345: return (0);
346: for (ifa = ifp->if_addrhead.tqh_first; ifa;
347: ifa = ifa->ifa_link.tqe_next) {
348: if (ifa->ifa_addr->sa_family != af)
349: continue;
350: if (ifa_maybe == 0)
351: ifa_maybe = ifa;
352: if (ifa->ifa_netmask == 0) {
353: if (equal(addr, ifa->ifa_addr) ||
354: (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
355: return (ifa);
356: continue;
357: }
358: if (ifp->if_flags & IFF_POINTOPOINT) {
359: if (equal(addr, ifa->ifa_dstaddr))
360: return (ifa);
361: } else {
362: cp = addr->sa_data;
363: cp2 = ifa->ifa_addr->sa_data;
364: cp3 = ifa->ifa_netmask->sa_data;
365: cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
366: for (; cp3 < cplim; cp3++)
367: if ((*cp++ ^ *cp2++) & *cp3)
368: break;
369: if (cp3 == cplim)
370: return (ifa);
371: }
372: }
373: return (ifa_maybe);
374: }
375:
376: #include <net/route.h>
377:
378: /*
379: * Default action when installing a route with a Link Level gateway.
380: * Lookup an appropriate real ifa to point to.
381: * This should be moved to /sys/net/link.c eventually.
382: */
383: static void
384: link_rtrequest(cmd, rt, sa)
385: int cmd;
386: register struct rtentry *rt;
387: struct sockaddr *sa;
388: {
389: register struct ifaddr *ifa;
390: struct sockaddr *dst;
391: struct ifnet *ifp;
392:
393: if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
394: ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
395: return;
396: ifa = ifaof_ifpforaddr(dst, ifp);
397: if (ifa) {
398: IFAFREE(rt->rt_ifa);
399: rt->rt_ifa = ifa;
400: ifa->ifa_refcnt++;
401: if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
402: ifa->ifa_rtrequest(cmd, rt, sa);
403: }
404: }
405:
406: /*
407: * Mark an interface down and notify protocols of
408: * the transition.
409: * NOTE: must be called at splnet or eqivalent.
410: */
411: void
412: if_unroute(ifp, flag, fam)
413: register struct ifnet *ifp;
414: int flag, fam;
415: {
416: register struct ifaddr *ifa;
417:
418: ifp->if_flags &= ~flag;
419: getmicrotime(&ifp->if_lastchange);
420: TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
421: if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
422: pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
423: if_qflush(&ifp->if_snd);
424: rt_ifmsg(ifp);
425: }
426:
427: /*
428: * Mark an interface up and notify protocols of
429: * the transition.
430: * NOTE: must be called at splnet or eqivalent.
431: */
432: void
433: if_route(ifp, flag, fam)
434: register struct ifnet *ifp;
435: int flag, fam;
436: {
437: register struct ifaddr *ifa;
438:
439: ifp->if_flags |= flag;
440: getmicrotime(&ifp->if_lastchange);
441: TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
442: if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
443: pfctlinput(PRC_IFUP, ifa->ifa_addr);
444: rt_ifmsg(ifp);
445: }
446:
447: /*
448: * Mark an interface down and notify protocols of
449: * the transition.
450: * NOTE: must be called at splnet or eqivalent.
451: */
452: void
453: if_down(ifp)
454: register struct ifnet *ifp;
455: {
456:
457: if_unroute(ifp, IFF_UP, AF_UNSPEC);
458: }
459:
460: /*
461: * Mark an interface up and notify protocols of
462: * the transition.
463: * NOTE: must be called at splnet or eqivalent.
464: */
465: void
466: if_up(ifp)
467: register struct ifnet *ifp;
468: {
469:
470: if_route(ifp, IFF_UP, AF_UNSPEC);
471: }
472:
473: /*
474: * Flush an interface queue.
475: */
476: static void
477: if_qflush(ifq)
478: register struct ifqueue *ifq;
479: {
480: register struct mbuf *m, *n;
481:
482: n = ifq->ifq_head;
483: while ((m = n) != 0) {
484: n = m->m_act;
485: m_freem(m);
486: }
487: ifq->ifq_head = 0;
488: ifq->ifq_tail = 0;
489: ifq->ifq_len = 0;
490: }
491:
492:
493: /*
494: * Map interface name to
495: * interface structure pointer.
496: */
497: struct ifnet *
498: ifunit(name)
499: register char *name;
500: {
501: char namebuf[IFNAMSIZ + 1];
502: register char *cp, *cp2;
503: char *end;
504: register struct ifnet *ifp;
505: int unit;
506: unsigned len;
507: register char c = '\0';
508:
509: /*
510: * Look for a non numeric part
511: */
512: end = name + IFNAMSIZ;
513: cp2 = namebuf;
514: cp = name;
515: while ((cp < end) && (c = *cp)) {
516: if (c >= '0' && c <= '9')
517: break;
518: *cp2++ = c;
519: cp++;
520: }
521: if ((cp == end) || (c == '\0') || (cp == name))
522: return ((struct ifnet *)0);
523: *cp2 = '\0';
524: /*
525: * check we have a legal number (limit to 7 digits?)
526: */
527: len = cp - name + 1;
528: for (unit = 0;
529: ((c = *cp) >= '0') && (c <= '9') && (unit < 1000000); cp++ )
530: unit = (unit * 10) + (c - '0');
531: if (*cp != '\0')
532: return 0; /* no trailing garbage allowed */
533: /*
534: * Now search all the interfaces for this name/number
535: */
536: for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
537: if (bcmp(ifp->if_name, namebuf, len))
538: continue;
539: if (unit == ifp->if_unit)
540: break;
541: }
542: return (ifp);
543: }
544:
545: /*
546: * Interface ioctls.
547: */
548: int
549: ifioctl(so, cmd, data, p)
550: struct socket *so;
551: u_long cmd;
552: caddr_t data;
553: struct proc *p;
554: {
555: register struct ifnet *ifp;
556: register struct ifreq *ifr;
557: int error;
558: extern int new_splitter(struct socket *);
559: void if_register(struct BlueFilter *);
560:
561: switch (cmd) {
562:
563: case SIOCGIFCONF:
564: case OSIOCGIFCONF:
565: return (ifconf(cmd, data));
566: }
567: ifr = (struct ifreq *)data;
568: ifp = ifunit(ifr->ifr_name);
569: if (ifp == 0)
570: return (ENXIO);
571: switch (cmd) {
572:
573: case SIOCSSPLITTER:
574: if ((error = new_splitter(so)))
575: return(error);
576: break;
577:
578: case SIOCGSPLITTER:
579: ifr->ifr_data = (caddr_t)(ifp->if_flags & IFF_SPLITTER);
580: break;
581:
582: case SIOCGIFFLAGS:
583: ifr->ifr_flags = ifp->if_flags;
584: break;
585:
586: case SIOCGIFMETRIC:
587: ifr->ifr_metric = ifp->if_metric;
588: break;
589:
590: case SIOCGIFMTU:
591: ifr->ifr_mtu = ifp->if_mtu;
592: break;
593:
594: case SIOCGIFPHYS:
595: ifr->ifr_phys = ifp->if_physical;
596: break;
597:
598: case SIOCSIFFLAGS:
599: error = suser(p->p_ucred, &p->p_acflag);
600: if (error)
601: return (error);
602: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
603: int s = splimp();
604: if_down(ifp);
605: splx(s);
606: }
607: if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
608: int s = splimp();
609: if_up(ifp);
610: splx(s);
611: }
612: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
613: (ifr->ifr_flags &~ IFF_CANTCHANGE);
614: if (ifp->if_ioctl)
615: dlil_ioctl(0, ifp, cmd, (caddr_t) data);
616: getmicrotime(&ifp->if_lastchange);
617: break;
618:
619: case SIOCSIFMETRIC:
620: error = suser(p->p_ucred, &p->p_acflag);
621: if (error)
622: return (error);
623: ifp->if_metric = ifr->ifr_metric;
624: getmicrotime(&ifp->if_lastchange);
625: break;
626:
627: case SIOCSIFPHYS:
628: error = suser(p->p_ucred, &p->p_acflag);
629: if (error)
630: return error;
631: if (!ifp->if_ioctl)
632: return EOPNOTSUPP;
633: error = dlil_ioctl(0, ifp, cmd, (caddr_t) data);
634: if (error == 0)
635: getmicrotime(&ifp->if_lastchange);
636: return(error);
637:
638: case SIOCSIFMTU:
639: error = suser(p->p_ucred, &p->p_acflag);
640: if (error)
641: return (error);
642: if (ifp->if_ioctl == NULL)
643: return (EOPNOTSUPP);
644: /*
645: * 72 was chosen below because it is the size of a TCP/IP
646: * header (40) + the minimum mss (32).
647: */
648: if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535)
649: return (EINVAL);
650: error = dlil_ioctl(0, ifp, cmd, (caddr_t) data);
651: if (error == 0)
652: getmicrotime(&ifp->if_lastchange);
653: return(error);
654:
655: case SIOCADDMULTI:
656: case SIOCDELMULTI:
657: error = suser(p->p_ucred, &p->p_acflag);
658: if (error)
659: return (error);
660:
661: /* Don't allow group membership on non-multicast interfaces. */
662: if ((ifp->if_flags & IFF_MULTICAST) == 0)
663: return EOPNOTSUPP;
664:
665: #if 0
666: /*
667: * Don't let users change protocols' entries.
668: */
669: if (ifr->ifr_addr.sa_family != AF_LINK)
670: return EINVAL;
671: #endif
672: if (cmd == SIOCADDMULTI) {
673: struct ifmultiaddr *ifma;
674: error = if_addmulti(ifp, &ifr->ifr_addr, &ifma);
675: } else {
676: error = if_delmulti(ifp, &ifr->ifr_addr);
677: }
678: if (error == 0)
679: getmicrotime(&ifp->if_lastchange);
680: return error;
681:
682: case SIOCSIFMEDIA:
683: case SIOCSIFGENERIC:
684: error = suser(p->p_ucred, &p->p_acflag);
685: if (error)
686: return (error);
687: if (ifp->if_ioctl == 0)
688: return (EOPNOTSUPP);
689: error = dlil_ioctl(0, ifp, cmd, (caddr_t) data);
690: if (error == 0)
691: getmicrotime(&ifp->if_lastchange);
692: return error;
693:
694: case SIOCGIFMEDIA:
695: case SIOCGIFGENERIC:
696: if (ifp->if_ioctl == 0)
697: return (EOPNOTSUPP);
698: return dlil_ioctl(0, ifp, cmd, (caddr_t) data);
699:
700: default:
701: if (so->so_proto == 0)
702: return (EOPNOTSUPP);
703: #if !COMPAT_43
704: return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
705: data,
706: ifp, p));
707: #else
708: {
709: int ocmd = cmd;
710:
711: switch (cmd) {
712:
713: case SIOCSIFDSTADDR:
714: case SIOCSIFADDR:
715: case SIOCSIFBRDADDR:
716: case SIOCSIFNETMASK:
717: #if BYTE_ORDER != BIG_ENDIAN
718: if (ifr->ifr_addr.sa_family == 0 &&
719: ifr->ifr_addr.sa_len < 16) {
720: ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
721: ifr->ifr_addr.sa_len = 16;
722: }
723: #else
724: if (ifr->ifr_addr.sa_len == 0)
725: ifr->ifr_addr.sa_len = 16;
726: #endif
727: #define IFR2IN(ifr) ((struct in_addr *)&(ifr->ifr_addr))->s_addr
728: if (ifr->ifr_addr.sa_family == AF_INET)
729: { /*
730: * If we have an address, and we're 'splitting',
731: * register the address. Note that this
732: * is to handle the case of addresses
733: * registered after the Blue Box starts.
734: */
735: if ((ifp->if_flags & IFF_SPLITTER) &&
736: (IFR2IN(ifr) != 0))
737: { struct BlueFilter filter;
738:
739: filter.BF_flags = (BF_ALLOC|BF_IP);
740: filter.BF_address = IFR2IN(ifr);
741: log(LOG_WARNING,
742: "[2]IP registering %x",
743: filter.BF_address);
744: if_register(&filter);
745: }
746: }
747: /* Fall through! */
748: break;
749:
750: case OSIOCGIFADDR:
751: cmd = SIOCGIFADDR;
752: break;
753:
754: case OSIOCGIFDSTADDR:
755: cmd = SIOCGIFDSTADDR;
756: break;
757:
758: case OSIOCGIFBRDADDR:
759: cmd = SIOCGIFBRDADDR;
760: break;
761:
762: case OSIOCGIFNETMASK:
763: cmd = SIOCGIFNETMASK;
764: }
765: error = ((*so->so_proto->pr_usrreqs->pru_control)(so,
766: cmd,
767: data,
768: ifp, p));
769: switch (ocmd) {
770:
771: case OSIOCGIFADDR:
772: case OSIOCGIFDSTADDR:
773: case OSIOCGIFBRDADDR:
774: case OSIOCGIFNETMASK:
775: *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
776: }
777: return (error);
778:
779: }
780: #endif
781: }
782: return (0);
783: }
784:
785: /*
786: * Set/clear promiscuous mode on interface ifp based on the truth value
787: * of pswitch. The calls are reference counted so that only the first
788: * "on" request actually has an effect, as does the final "off" request.
789: * Results are undefined if the "off" and "on" requests are not matched.
790: */
791: int
792: ifpromisc(ifp, pswitch)
793: struct ifnet *ifp;
794: int pswitch;
795: {
796: struct ifreq ifr;
797: int error;
798:
799: if (pswitch) {
800: /*
801: * If the device is not configured up, we cannot put it in
802: * promiscuous mode.
803: */
804: if ((ifp->if_flags & IFF_UP) == 0)
805: return (ENETDOWN);
806: if (ifp->if_pcount++ != 0)
807: return (0);
808: ifp->if_flags |= IFF_PROMISC;
809: log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
810: ifp->if_name, ifp->if_unit);
811: } else {
812: if (--ifp->if_pcount > 0)
813: return (0);
814: ifp->if_flags &= ~IFF_PROMISC;
815: }
816: ifr.ifr_flags = ifp->if_flags;
817: error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
818: if (error == 0)
819: rt_ifmsg(ifp);
820: return error;
821: }
822:
823: /*
824: * Return interface configuration
825: * of system. List may be used
826: * in later ioctl's (above) to get
827: * other information.
828: */
829: /*ARGSUSED*/
830: static int
831: ifconf(cmd, data)
832: u_long cmd;
833: caddr_t data;
834: {
835: register struct ifconf *ifc = (struct ifconf *)data;
836: register struct ifnet *ifp = ifnet.tqh_first;
837: register struct ifaddr *ifa;
838: struct ifreq ifr, *ifrp;
839: int space = ifc->ifc_len, error = 0;
840:
841: ifrp = ifc->ifc_req;
842: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) {
843: char workbuf[64];
844: int ifnlen;
845:
846: ifnlen = snprintf(workbuf, sizeof(workbuf),
847: "%s%d", ifp->if_name, ifp->if_unit);
848: if(ifnlen + 1 > sizeof ifr.ifr_name) {
849: error = ENAMETOOLONG;
850: } else {
851: strcpy(ifr.ifr_name, workbuf);
852: }
853:
854: if ((ifa = ifp->if_addrhead.tqh_first) == 0) {
855: bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
856: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
857: sizeof (ifr));
858: if (error)
859: break;
860: space -= sizeof (ifr), ifrp++;
861: } else
862: for ( ; space > sizeof (ifr) && ifa;
863: ifa = ifa->ifa_link.tqe_next) {
864: register struct sockaddr *sa = ifa->ifa_addr;
865: #if COMPAT_43
866: if (cmd == OSIOCGIFCONF) {
867: struct osockaddr *osa =
868: (struct osockaddr *)&ifr.ifr_addr;
869: ifr.ifr_addr = *sa;
870: osa->sa_family = sa->sa_family;
871: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
872: sizeof (ifr));
873: ifrp++;
874: } else
875: #endif
876: if (sa->sa_len <= sizeof(*sa)) {
877: ifr.ifr_addr = *sa;
878: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
879: sizeof (ifr));
880: ifrp++;
881: } else {
882: space -= sa->sa_len - sizeof(*sa);
883: if (space < sizeof (ifr))
884: break;
885: error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
886: sizeof (ifr.ifr_name));
887: if (error == 0)
888: error = copyout((caddr_t)sa,
889: (caddr_t)&ifrp->ifr_addr, sa->sa_len);
890: ifrp = (struct ifreq *)
891: (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
892: }
893: if (error)
894: break;
895: space -= sizeof (ifr);
896: }
897: }
898: ifc->ifc_len -= space;
899: return (error);
900: }
901:
902: /*
903: * Just like if_promisc(), but for all-multicast-reception mode.
904: */
905: int
906: if_allmulti(ifp, onswitch)
907: struct ifnet *ifp;
908: int onswitch;
909: {
910: int error = 0;
911: int s = splimp();
912:
913: if (onswitch) {
914: if (ifp->if_amcount++ == 0) {
915: ifp->if_flags |= IFF_ALLMULTI;
916: error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
917: }
918: } else {
919: if (ifp->if_amcount > 1) {
920: ifp->if_amcount--;
921: } else {
922: ifp->if_amcount = 0;
923: ifp->if_flags &= ~IFF_ALLMULTI;
924: error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
925: }
926: }
927: splx(s);
928:
929: if (error == 0)
930: rt_ifmsg(ifp);
931: return error;
932: }
933:
934: /*
935: * Add a multicast listenership to the interface in question.
936: * The link layer provides a routine which converts
937: */
938: int
939: if_addmulti(ifp, sa, retifma)
940: struct ifnet *ifp; /* interface to manipulate */
941: struct sockaddr *sa; /* address to add */
942: struct ifmultiaddr **retifma;
943: {
944: struct sockaddr *llsa, *dupsa;
945: int error, s;
946: struct ifmultiaddr *ifma;
947:
948: /*
949: * If the matching multicast address already exists
950: * then don't add a new one, just add a reference
951: */
952: for (ifma = ifp->if_multiaddrs.lh_first; ifma;
953: ifma = ifma->ifma_link.le_next) {
954: if (equal(sa, ifma->ifma_addr)) {
955: ifma->ifma_refcount++;
956: if (retifma)
957: *retifma = ifma;
958: return 0;
959: }
960: }
961:
962: /*
963: * Give the link layer a chance to accept/reject it, and also
964: * find out which AF_LINK address this maps to, if it isn't one
965: * already.
966: */
967: if (ifp->if_resolvemulti) {
968: error = ifp->if_resolvemulti(ifp, &llsa, sa);
969: if (error) return error;
970: } else {
971: llsa = 0;
972: }
973:
974: MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
975: MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
976: bcopy(sa, dupsa, sa->sa_len);
977:
978: ifma->ifma_addr = dupsa;
979: ifma->ifma_lladdr = llsa;
980: ifma->ifma_ifp = ifp;
981: ifma->ifma_refcount = 1;
982: ifma->ifma_protospec = 0;
983: rt_newmaddrmsg(RTM_NEWMADDR, ifma);
984:
985: /*
986: * Some network interfaces can scan the address list at
987: * interrupt time; lock them out.
988: */
989: s = splimp();
990: LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
991: splx(s);
992: if (retifma)
993: *retifma = ifma;
994:
995: if (llsa != 0) {
996: for (ifma = ifp->if_multiaddrs.lh_first; ifma;
997: ifma = ifma->ifma_link.le_next) {
998: if (equal(ifma->ifma_addr, llsa))
999: break;
1000: }
1001: if (ifma) {
1002: ifma->ifma_refcount++;
1003: } else {
1004: MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
1005: M_IFMADDR, M_WAITOK);
1006: MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
1007: M_IFMADDR, M_WAITOK);
1008: bcopy(llsa, dupsa, llsa->sa_len);
1009: ifma->ifma_addr = dupsa;
1010: ifma->ifma_ifp = ifp;
1011: ifma->ifma_refcount = 1;
1012: s = splimp();
1013: LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1014: splx(s);
1015: }
1016: }
1017: /*
1018: * We are certain we have added something, so call down to the
1019: * interface to let them know about it.
1020: */
1021: s = splimp();
1022:
1023: dlil_ioctl(0, ifp, SIOCADDMULTI, (caddr_t) 0);
1024: splx(s);
1025:
1026: return 0;
1027: }
1028:
1029: /*
1030: * Remove a reference to a multicast address on this interface. Yell
1031: * if the request does not match an existing membership.
1032: */
1033: int
1034: if_delmulti(ifp, sa)
1035: struct ifnet *ifp;
1036: struct sockaddr *sa;
1037: {
1038: struct ifmultiaddr *ifma;
1039: int s;
1040:
1041: for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1042: ifma = ifma->ifma_link.le_next)
1043: if (equal(sa, ifma->ifma_addr))
1044: break;
1045: if (ifma == 0)
1046: return ENOENT;
1047:
1048: if (ifma->ifma_refcount > 1) {
1049: ifma->ifma_refcount--;
1050: return 0;
1051: }
1052:
1053: rt_newmaddrmsg(RTM_DELMADDR, ifma);
1054: sa = ifma->ifma_lladdr;
1055: s = splimp();
1056: LIST_REMOVE(ifma, ifma_link);
1057: splx(s);
1058: FREE(ifma->ifma_addr, M_IFMADDR);
1059: FREE(ifma, M_IFMADDR);
1060: if (sa == 0)
1061: return 0;
1062:
1063: /*
1064: * Now look for the link-layer address which corresponds to
1065: * this network address. It had been squirreled away in
1066: * ifma->ifma_lladdr for this purpose (so we don't have
1067: * to call ifp->if_resolvemulti() again), and we saved that
1068: * value in sa above. If some nasty deleted the
1069: * link-layer address out from underneath us, we can deal because
1070: * the address we stored was is not the same as the one which was
1071: * in the record for the link-layer address. (So we don't complain
1072: * in that case.)
1073: */
1074: for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1075: ifma = ifma->ifma_link.le_next)
1076: if (equal(sa, ifma->ifma_addr))
1077: break;
1078: if (ifma == 0)
1079: return 0;
1080:
1081: if (ifma->ifma_refcount > 1) {
1082: ifma->ifma_refcount--;
1083: return 0;
1084: }
1085:
1086: s = splimp();
1087: LIST_REMOVE(ifma, ifma_link);
1088: dlil_ioctl(0, ifp, SIOCDELMULTI, (caddr_t) 0);
1089: splx(s);
1090: FREE(ifma->ifma_addr, M_IFMADDR);
1091: FREE(sa, M_IFMADDR);
1092: FREE(ifma, M_IFMADDR);
1093:
1094: return 0;
1095: }
1096:
1097: struct ifmultiaddr *
1098: ifmaof_ifpforaddr(sa, ifp)
1099: struct sockaddr *sa;
1100: struct ifnet *ifp;
1101: {
1102: struct ifmultiaddr *ifma;
1103:
1104: for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1105: ifma = ifma->ifma_link.le_next)
1106: if (equal(ifma->ifma_addr, sa))
1107: break;
1108:
1109: return ifma;
1110: }
1111:
1112: SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
1113: SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
1114:
1115:
1116: /*
1117: * Shutdown all network activity. Used boot() when halting
1118: * system.
1119: */
1120: int if_down_all(void)
1121: {
1122: struct ifnet *ifp;
1123: int s;
1124:
1125: s = splnet();
1126: TAILQ_FOREACH(ifp, &ifnet, if_link)
1127: if_down(ifp);
1128:
1129: splx(s);
1130: return(0); /* Sheesh */
1131: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.