|
|
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) 1982, 1989, 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_ethersubr.c 8.1 (Berkeley) 6/10/93
55: */
56:
57: #if NOTFB31
58: #include "opt_atalk.h"
59: #include "opt_inet.h"
60: #include "opt_ipx.h"
61: #include "opt_bdg.h"
62: #endif
63:
64: #include <sys/param.h>
65: #include <sys/systm.h>
66: #include <sys/kernel.h>
67: #include <sys/malloc.h>
68: #include <sys/mbuf.h>
69: #include <sys/socket.h>
70: #include <sys/sockio.h>
71: #include <sys/sysctl.h>
72:
73: #include <net/if.h>
74: #include <net/netisr.h>
75: #include <net/route.h>
76: #include <net/if_llc.h>
77: #include <net/if_dl.h>
78: #include <net/if_types.h>
79: #include <net/ndrv.h>
80:
81: #if INET
82: #include <netinet/in.h>
83: #include <netinet/in_var.h>
84: #include <netinet/if_ether.h>
85: #include <netinet/in_systm.h>
86: #include <netinet/ip.h>
87: #endif
88:
89: #if IPX
90: #include <netipx/ipx.h>
91: #include <netipx/ipx_if.h>
92: #endif
93:
94: #if NS
95: #include <netns/ns.h>
96: #include <netns/ns_if.h>
97: ushort ns_nettype;
98: int ether_outputdebug = 0;
99: int ether_inputdebug = 0;
100: #endif
101:
102: #if ISO
103: #include <netiso/argo_debug.h>
104: #include <netiso/iso.h>
105: #include <netiso/iso_var.h>
106: #include <netiso/iso_snpac.h>
107: #endif
108:
109: /*#if LLC
110: #include <netccitt/dll.h>
111: #include <netccitt/llc_var.h>
112: #endif*/
113:
114: #include <sys/socketvar.h>
115: #include <net/if_blue.h>
116:
117: struct BlueFilter RhapFilter[BFCount];
118: int BFIx; /* 0 for Atalk; 1..9 for IP */
119:
120:
121: #if LLC && CCITT
122: extern struct ifqueue pkintrq;
123: #endif
124:
125: #if BRIDGE
126: #include <net/bridge.h>
127: #endif
128:
129: /* #include "vlan.h" */
130: #if NVLAN > 0
131: #include <net/if_vlan_var.h>
132: #endif /* NVLAN > 0 */
133:
134: static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
135: struct sockaddr *));
136: extern u_char etherbroadcastaddr[];
137: #define senderr(e) do { error = (e); goto bad;} while (0)
138: #define IFP2AC(IFP) ((struct arpcom *)IFP)
139:
140: /*
141: * Perform common duties while attaching to interface list
142: */
143:
144:
145: void
146: ether_ifattach(ifp)
147: register struct ifnet *ifp;
148: {
149: register struct ifaddr *ifa;
150: register struct sockaddr_dl *sdl;
151: boolean_t funnel_state;
152:
153: funnel_state = thread_set_funneled(TRUE);
154: printf("ether_ifattach called for %s\n", ifp->if_name);
155: ether_family_init();
156:
157: ifp->if_name = "en";
158: ifp->if_family = APPLE_IF_FAM_ETHERNET;
159: ifp->if_type = IFT_ETHER;
160: ifp->if_addrlen = 6;
161: ifp->if_hdrlen = 14;
162: ifp->if_mtu = ETHERMTU;
163: ifp->if_resolvemulti = ether_resolvemulti;
164: if (ifp->if_baudrate == 0)
165: ifp->if_baudrate = 10000000;
166:
167: dlil_if_attach(ifp);
168: ifa = ifnet_addrs[ifp->if_index - 1];
169: if (ifa == 0) {
170: printf("ether_ifattach: no lladdr!\n");
171: (void) thread_set_funneled(funnel_state);
172: return;
173: }
174: sdl = (struct sockaddr_dl *)ifa->ifa_addr;
175: sdl->sdl_type = IFT_ETHER;
176: sdl->sdl_alen = ifp->if_addrlen;
177: bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
178: (void) thread_set_funneled(funnel_state);
179: }
180:
181: SYSCTL_DECL(_net_link);
182: SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
183:
184: int
185: ether_resolvemulti(ifp, llsa, sa)
186: struct ifnet *ifp;
187: struct sockaddr **llsa;
188: struct sockaddr *sa;
189: {
190: struct sockaddr_dl *sdl;
191: struct sockaddr_in *sin;
192: u_char *e_addr;
193:
194: switch(sa->sa_family) {
195: case AF_UNSPEC:
196: /* AppleTalk uses AF_UNSPEC for multicast registration.
197: * No mapping needed. Just check that it's a valid MC address.
198: */
199: e_addr = &sa->sa_data[0];
200: if ((e_addr[0] & 1) != 1)
201: return EADDRNOTAVAIL;
202: *llsa = 0;
203: return 0;
204:
205: case AF_LINK:
206: /*
207: * No mapping needed. Just check that it's a valid MC address.
208: */
209: sdl = (struct sockaddr_dl *)sa;
210: e_addr = LLADDR(sdl);
211: if ((e_addr[0] & 1) != 1)
212: return EADDRNOTAVAIL;
213: *llsa = 0;
214: return 0;
215:
216: #if INET
217: case AF_INET:
218: sin = (struct sockaddr_in *)sa;
219: if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
220: return EADDRNOTAVAIL;
221: MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
222: M_WAITOK);
223: sdl->sdl_len = sizeof *sdl;
224: sdl->sdl_family = AF_LINK;
225: sdl->sdl_index = ifp->if_index;
226: sdl->sdl_type = IFT_ETHER;
227: sdl->sdl_nlen = 0;
228: sdl->sdl_alen = ETHER_ADDR_LEN;
229: sdl->sdl_slen = 0;
230: e_addr = LLADDR(sdl);
231: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
232: *llsa = (struct sockaddr *)sdl;
233: return 0;
234: #endif
235:
236: default:
237: /*
238: * Well, the text isn't quite right, but it's the name
239: * that counts...
240: */
241: return EAFNOSUPPORT;
242: }
243: }
244:
245:
246:
247:
248:
249: u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
250: u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
251: /*
252: * Add an Ethernet multicast address or range of addresses to the list for a
253: * given interface.
254: */
255: int
256: ether_addmulti(ifr, ac)
257: struct ifreq *ifr;
258: register struct arpcom *ac;
259: {
260: register struct ether_multi *enm;
261: struct sockaddr_in *sin;
262: u_char addrlo[6];
263: u_char addrhi[6];
264: int s = splimp();
265:
266: switch (ifr->ifr_addr.sa_family) {
267:
268: case AF_UNSPEC:
269: bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
270: bcopy(addrlo, addrhi, 6);
271: break;
272:
273: #if INET
274: case AF_INET:
275: sin = (struct sockaddr_in *)&(ifr->ifr_addr);
276: if (sin->sin_addr.s_addr == INADDR_ANY) {
277: /*
278: * An IP address of INADDR_ANY means listen to all
279: * of the Ethernet multicast addresses used for IP.
280: * (This is for the sake of IP multicast routers.)
281: */
282: bcopy(ether_ipmulticast_min, addrlo, 6);
283: bcopy(ether_ipmulticast_max, addrhi, 6);
284: }
285: else {
286: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
287: bcopy(addrlo, addrhi, 6);
288: }
289: break;
290: #endif
291:
292: default:
293: splx(s);
294: return (EAFNOSUPPORT);
295: }
296:
297: /*
298: * Verify that we have valid Ethernet multicast addresses.
299: */
300: if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
301: splx(s);
302: return (EINVAL);
303: }
304: /*
305: * See if the address range is already in the list.
306: */
307: ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
308: if (enm != NULL) {
309: /*
310: * Found it; just increment the reference count.
311: */
312: ++enm->enm_refcount;
313: splx(s);
314: return (0);
315: }
316: /*
317: * New address or range; malloc a new multicast record
318: * and link it into the interface's multicast list.
319: */
320: enm = (struct ether_multi *)_MALLOC(sizeof(*enm), M_IFMADDR, M_WAITOK);
321: if (enm == NULL) {
322: splx(s);
323: return (ENOBUFS);
324: }
325: bcopy(addrlo, enm->enm_addrlo, 6);
326: bcopy(addrhi, enm->enm_addrhi, 6);
327: enm->enm_ac = ac;
328: enm->enm_refcount = 1;
329: enm->enm_next = ac->ac_multiaddrs;
330: ac->ac_multiaddrs = enm;
331: splx(s);
332: /*
333: * Return ENETRESET to inform the driver that the list has changed
334: * and its reception filter should be adjusted accordingly.
335: */
336: return (ENETRESET);
337: }
338:
339: /*
340: * Delete a multicast address record.
341: */
342: int
343: ether_delmulti(ifr, ac, ret_mca)
344: struct ifreq *ifr;
345: register struct arpcom *ac;
346: struct ether_addr * ret_mca;
347: {
348: register struct ether_multi *enm;
349: register struct ether_multi **p;
350: struct sockaddr_in *sin;
351: u_char addrlo[6];
352: u_char addrhi[6];
353: int s = splimp();
354:
355: switch (ifr->ifr_addr.sa_family) {
356:
357: case AF_UNSPEC:
358: bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
359: bcopy(addrlo, addrhi, 6);
360: break;
361:
362: #if INET
363: case AF_INET:
364: sin = (struct sockaddr_in *)&(ifr->ifr_addr);
365: if (sin->sin_addr.s_addr == INADDR_ANY) {
366: /*
367: * An IP address of INADDR_ANY means stop listening
368: * to the range of Ethernet multicast addresses used
369: * for IP.
370: */
371: bcopy(ether_ipmulticast_min, addrlo, 6);
372: bcopy(ether_ipmulticast_max, addrhi, 6);
373: }
374: else {
375: ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
376: bcopy(addrlo, addrhi, 6);
377: }
378: break;
379: #endif
380:
381: default:
382: splx(s);
383: return (EAFNOSUPPORT);
384: }
385:
386: /*
387: * Look up the address in our list.
388: */
389: ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
390: if (enm == NULL) {
391: splx(s);
392: return (ENXIO);
393: }
394: if (--enm->enm_refcount != 0) {
395: /*
396: * Still some claims to this record.
397: */
398: splx(s);
399: return (0);
400: }
401:
402: /* save the low and high address of the range before deletion */
403: if (ret_mca) {
404: *ret_mca = *((struct ether_addr *)addrlo);
405: *(ret_mca + 1) = *((struct ether_addr *)addrhi);
406: }
407:
408: /*
409: * No remaining claims to this record; unlink and free it.
410: */
411: for (p = &enm->enm_ac->ac_multiaddrs;
412: *p != enm;
413: p = &(*p)->enm_next)
414: continue;
415: *p = (*p)->enm_next;
416: FREE(enm, M_IFMADDR);
417: splx(s);
418: /*
419: * Return ENETRESET to inform the driver that the list has changed
420: * and its reception filter should be adjusted accordingly.
421: */
422: return (ENETRESET);
423: }
424:
425:
426: /*
427: * NB: need to register Atalk addresses from MacOSX
428: */
429: int
430: if_register(register struct BlueFilter *f
431: #if BF_if
432: ,
433: register struct ifnet *ifp
434: #endif
435: )
436: { register int ix;
437: register struct BlueFilter *nf;
438:
439: if (f->BF_flags & BF_VALID)
440: return(EINVAL);
441: if (f->BF_flags & BF_IP)
442: { if (BFIx == 0)
443: ix = BFIx = 1; /* Starting at 1 for IP */
444: else if (BFIx >= BFCount)
445: return(0); /* We'll just deal with it */
446: else
447: ix = ++BFIx;
448: } else if (!(f->BF_flags & BF_ATALK))
449: return(EINVAL);
450: else /* AppleTalk */
451: ix = 0;
452:
453: nf = &RhapFilter[ix];
454: *nf = *f;
455: nf->BF_flags |= BF_VALID;
456: #if BF_if
457: nf->BF_if = ifp;
458: #endif
459: return(0);
460: }
461:
462: /*
463: * Convert Ethernet address to printable (loggable) representation.
464: */
465: static u_char digits[] = "0123456789abcdef";
466: char *
467: ether_sprintf(p, ap)
468: register u_char *p;
469: register u_char *ap;
470: { register char *cp;
471: register i;
472:
473: for (cp = p, i = 0; i < 6; i++) {
474: *cp++ = digits[*ap >> 4];
475: *cp++ = digits[*ap++ & 0xf];
476: *cp++ = ':';
477: }
478: *--cp = 0;
479: return (p);
480: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.