]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/ether_if_module.c
xnu-344.49.tar.gz
[apple/xnu.git] / bsd / net / ether_if_module.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * Copyright (c) 1982, 1989, 1993
27 * The Regents of the University of California. All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 */
58
59
60
61#include <sys/param.h>
62#include <sys/systm.h>
63#include <sys/kernel.h>
64#include <sys/malloc.h>
65#include <sys/mbuf.h>
66#include <sys/socket.h>
67#include <sys/sockio.h>
68#include <sys/sysctl.h>
69
70#include <net/if.h>
71#include <net/netisr.h>
72#include <net/route.h>
73#include <net/if_llc.h>
74#include <net/if_dl.h>
75#include <net/if_types.h>
1c79356b 76#include <netinet/if_ether.h>
9bccf70c 77#include <netinet/in.h> /* For M_LOOP */
1c79356b
A
78
79/*
80#if INET
81#include <netinet/in.h>
82#include <netinet/in_var.h>
83
84#include <netinet/in_systm.h>
85#include <netinet/ip.h>
86#endif
87*/
88
89#include <sys/socketvar.h>
90
91#include <net/dlil.h>
92
93
94#if LLC && CCITT
95extern struct ifqueue pkintrq;
96#endif
97
98/* General stuff from if_ethersubr.c - may not need some of it */
99
100#include <netat/at_pat.h>
101#if NETAT
102extern struct ifqueue atalkintrq;
103#endif
104
105
106#if BRIDGE
107#include <net/bridge.h>
108#endif
109
110/* #include "vlan.h" */
111#if NVLAN > 0
112#include <net/if_vlan_var.h>
113#endif /* NVLAN > 0 */
114
115static u_long lo_dlt = 0;
1c79356b
A
116
117#define IFP2AC(IFP) ((struct arpcom *)IFP)
118
1c79356b 119struct en_desc {
7b1edb79
A
120 u_int16_t type; /* Type of protocol stored in data */
121 struct if_proto *proto; /* Protocol structure */
122 u_long data[2]; /* Protocol data */
1c79356b 123};
7b1edb79
A
124
125#define ETHER_DESC_BLK_SIZE (10)
1c79356b
A
126#define MAX_INTERFACES 50
127
128/*
129 * Statics for demux module
130 */
131
132struct ether_desc_blk_str {
7b1edb79
A
133 u_long n_max_used;
134 u_long n_count;
135 struct en_desc *block_ptr;
1c79356b
A
136};
137
138
139static struct ether_desc_blk_str ether_desc_blk[MAX_INTERFACES];
1c79356b
A
140
141
142/*
143 * Release all descriptor entries owned by this dl_tag (there may be several).
7b1edb79 144 * Setting the type to 0 releases the entry. Eventually we should compact-out
1c79356b
A
145 * the unused entries.
146 */
147static
148int ether_del_proto(struct if_proto *proto, u_long dl_tag)
149{
7b1edb79
A
150 struct en_desc* ed = ether_desc_blk[proto->ifp->family_cookie].block_ptr;
151 u_long current = 0;
1c79356b 152 int found = 0;
7b1edb79
A
153
154 for (current = ether_desc_blk[proto->ifp->family_cookie].n_max_used;
155 current > 0; current--) {
156 if (ed[current - 1].proto == proto) {
157 found = 1;
158 ed[current - 1].type = 0;
159
160 if (current == ether_desc_blk[proto->ifp->family_cookie].n_max_used) {
161 ether_desc_blk[proto->ifp->family_cookie].n_max_used--;
162 }
163 }
1c79356b 164 }
7b1edb79
A
165
166 return found;
1c79356b
A
167 }
168
169
170
7b1edb79
A
171static int
172ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
1c79356b
A
173{
174 char *current_ptr;
175 struct dlil_demux_desc *desc;
1c79356b 176 struct en_desc *ed;
7b1edb79 177 struct en_desc *last;
1c79356b
A
178 u_long *bitmask;
179 u_long *proto_id;
7b1edb79 180 u_long i;
1c79356b
A
181 short total_length;
182 u_long block_count;
183 u_long *tmp;
184
185
7b1edb79
A
186 TAILQ_FOREACH(desc, desc_head, next) {
187 switch (desc->type) {
188 /* These types are supported */
189 /* Top three are preferred */
190 case DLIL_DESC_ETYPE2:
191 if (desc->variants.native_type_length != 2)
192 return EINVAL;
193 break;
194
195 case DLIL_DESC_SAP:
196 if (desc->variants.native_type_length != 3)
197 return EINVAL;
198 break;
199
200 case DLIL_DESC_SNAP:
201 if (desc->variants.native_type_length != 5)
202 return EINVAL;
203 break;
204
205 case DLIL_DESC_802_2:
206 case DLIL_DESC_802_2_SNAP:
207 break;
208
209 case DLIL_DESC_RAW:
210 if (desc->variants.bitmask.proto_id_length == 0)
211 break;
212 /* else fall through, bitmask variant not supported */
213
214 default:
215 ether_del_proto(proto, dl_tag);
216 return EINVAL;
217 }
218
219 restart:
220 ed = ether_desc_blk[proto->ifp->family_cookie].block_ptr;
221
222 /* Find a free entry */
223 for (i = 0; i < ether_desc_blk[proto->ifp->family_cookie].n_count; i++) {
224 if (ed[i].type == 0) {
225 break;
226 }
227 }
228
229 if (i >= ether_desc_blk[proto->ifp->family_cookie].n_count) {
230 u_long new_count = ETHER_DESC_BLK_SIZE +
231 ether_desc_blk[proto->ifp->family_cookie].n_count;
232 tmp = _MALLOC((new_count * (sizeof(*ed))), M_IFADDR, M_WAITOK);
233 if (tmp == 0) {
234 /*
235 * Remove any previous descriptors set in the call.
236 */
237 ether_del_proto(proto, dl_tag);
238 return ENOMEM;
239 }
240
241 bzero(tmp, new_count * sizeof(*ed));
242 bcopy(ether_desc_blk[proto->ifp->family_cookie].block_ptr,
243 tmp, ether_desc_blk[proto->ifp->family_cookie].n_count * sizeof(*ed));
244 FREE(ether_desc_blk[proto->ifp->family_cookie].block_ptr, M_IFADDR);
245 ether_desc_blk[proto->ifp->family_cookie].n_count = new_count;
246 ether_desc_blk[proto->ifp->family_cookie].block_ptr = (struct en_desc*)tmp;
247 }
248
249 /* Bump n_max_used if appropriate */
250 if (i + 1 > ether_desc_blk[proto->ifp->family_cookie].n_max_used) {
251 ether_desc_blk[proto->ifp->family_cookie].n_max_used = i + 1;
252 }
253
254 ed[i].proto = proto;
9bccf70c 255 ed[i].data[0] = 0;
7b1edb79
A
256 ed[i].data[1] = 0;
257
258 switch (desc->type) {
259 case DLIL_DESC_RAW:
260 /* 2 byte ethernet raw protocol type is at native_type */
261 /* protocol is not in network byte order */
262 ed[i].type = DLIL_DESC_ETYPE2;
263 ed[i].data[0] = htons(*(u_int16_t*)desc->native_type);
264 break;
265
266 case DLIL_DESC_ETYPE2:
267 /* 2 byte ethernet raw protocol type is at native_type */
268 /* prtocol must be in network byte order */
269 ed[i].type = DLIL_DESC_ETYPE2;
270 ed[i].data[0] = *(u_int16_t*)desc->native_type;
271 break;
272
273 case DLIL_DESC_802_2:
274 ed[i].type = DLIL_DESC_SAP;
275 ed[i].data[0] = *(u_int32_t*)&desc->variants.desc_802_2;
276 ed[i].data[0] &= htonl(0xFFFFFF00);
277 break;
278
279 case DLIL_DESC_SAP:
280 ed[i].type = DLIL_DESC_SAP;
281 bcopy(desc->native_type, &ed[i].data[0], 3);
282 break;
283
284 case DLIL_DESC_802_2_SNAP:
285 ed[i].type = DLIL_DESC_SNAP;
286 desc->variants.desc_802_2_SNAP.protocol_type =
287 htons(desc->variants.desc_802_2_SNAP.protocol_type);
288 bcopy(&desc->variants.desc_802_2_SNAP, &ed[i].data[0], 8);
289 ed[i].data[0] &= htonl(0x000000FF);
290 desc->variants.desc_802_2_SNAP.protocol_type =
291 ntohs(desc->variants.desc_802_2_SNAP.protocol_type);
292 break;
293
294 case DLIL_DESC_SNAP: {
295 u_int8_t* pDest = ((u_int8_t*)&ed[i].data[0]) + 3;
296 ed[i].type = DLIL_DESC_SNAP;
9bccf70c 297 bcopy(desc->native_type, pDest, 5);
7b1edb79
A
298 }
299 break;
300 }
301 }
302
303 return 0;
1c79356b
A
304}
305
306
307static
308int ether_shutdown()
309{
310 return 0;
311}
312
313
1c79356b
A
314int ether_demux(ifp, m, frame_header, proto)
315 struct ifnet *ifp;
316 struct mbuf *m;
317 char *frame_header;
318 struct if_proto **proto;
319
320{
321 register struct ether_header *eh = (struct ether_header *)frame_header;
7b1edb79
A
322 u_short ether_type = eh->ether_type;
323 u_int16_t type;
324 u_int8_t *data;
325 u_long i = 0;
326 u_long max = ether_desc_blk[ifp->family_cookie].n_max_used;
327 struct en_desc *ed = ether_desc_blk[ifp->family_cookie].block_ptr;
328 u_int32_t extProto1 = 0;
329 u_int32_t extProto2 = 0;
330
1c79356b 331 if (eh->ether_dhost[0] & 1) {
7b1edb79
A
332 /* Check for broadcast */
333 if (*(u_int32_t*)eh->ether_dhost == 0xFFFFFFFF &&
334 *(u_int16_t*)(eh->ether_dhost + sizeof(u_int32_t)) == 0xFFFF)
335 m->m_flags |= M_BCAST;
336 else
337 m->m_flags |= M_MCAST;
90556fb8
A
338 } else {
339 /*
340 * When the driver is put into promiscuous mode we may receive unicast
341 * frames that are not intended for our interfaces. They are filtered
342 * here to keep them from traveling further up the stack to code that
343 * is not expecting them or prepared to deal with them. In the near
344 * future, the filtering done here will be moved even further down the
345 * stack into the IONetworkingFamily, preventing even interface
346 * filter NKE's from receiving promiscuous packets. Please use BPF.
347 */
348 #define ETHER_CMP(x, y) ( ((u_int16_t *) x)[0] != ((u_int16_t *) y)[0] || \
349 ((u_int16_t *) x)[1] != ((u_int16_t *) y)[1] || \
350 ((u_int16_t *) x)[2] != ((u_int16_t *) y)[2] )
351
352 if (ETHER_CMP(eh->ether_dhost, ((struct arpcom *) ifp)->ac_enaddr)) {
353 m_freem(m);
354 return EJUSTRETURN;
355 }
1c79356b 356 }
7b1edb79
A
357
358 data = mtod(m, u_int8_t*);
359
360 /*
361 * Determine the packet's protocol type and stuff the protocol into
362 * longs for quick compares.
363 */
364
9bccf70c 365 if (ntohs(ether_type) <= 1500) {
7b1edb79
A
366 extProto1 = *(u_int32_t*)data;
367
368 // SAP or SNAP
369 if ((extProto1 & htonl(0xFFFFFF00)) == htonl(0xAAAA0300)) {
370 // SNAP
371 type = DLIL_DESC_SNAP;
372 extProto2 = *(u_int32_t*)(data + sizeof(u_int32_t));
373 extProto1 &= htonl(0x000000FF);
374 } else {
375 type = DLIL_DESC_SAP;
376 extProto1 &= htonl(0xFFFFFF00);
377 }
378 } else {
379 type = DLIL_DESC_ETYPE2;
380 }
381
1c79356b
A
382 /*
383 * Search through the connected protocols for a match.
384 */
7b1edb79
A
385
386 switch (type) {
387 case DLIL_DESC_ETYPE2:
388 for (i = 0; i < max; i++) {
389 if ((ed[i].type == type) && (ed[i].data[0] == ether_type)) {
390 *proto = ed[i].proto;
391 return 0;
392 }
393 }
394 break;
395
396 case DLIL_DESC_SAP:
397 for (i = 0; i < max; i++) {
398 if ((ed[i].type == type) && (ed[i].data[0] == extProto1)) {
399 *proto = ed[i].proto;
400 return 0;
401 }
402 }
403 break;
404
405 case DLIL_DESC_SNAP:
406 for (i = 0; i < max; i++) {
407 if ((ed[i].type == type) && (ed[i].data[0] == extProto1) &&
408 (ed[i].data[1] == extProto2)) {
409 *proto = ed[i].proto;
410 return 0;
411 }
412 }
413 break;
1c79356b 414 }
7b1edb79 415
1c79356b
A
416 return ENOENT;
417}
418
419
420
421/*
422 * Ethernet output routine.
423 * Encapsulate a packet of type family for the local net.
424 * Use trailer local net encapsulation if enough data in first
425 * packet leaves a multiple of 512 bytes of data in remainder.
426 * Assumes that ifp is actually pointer to arpcom structure.
427 */
428int
429ether_frameout(ifp, m, ndest, edst, ether_type)
430 register struct ifnet *ifp;
431 struct mbuf **m;
432 struct sockaddr *ndest;
433 char *edst;
434 char *ether_type;
435{
436 register struct ether_header *eh;
437 int hlen; /* link layer header lenght */
438 struct arpcom *ac = IFP2AC(ifp);
439
440
441 hlen = ETHER_HDR_LEN;
442
443 /*
444 * If a simplex interface, and the packet is being sent to our
445 * Ethernet address or a broadcast address, loopback a copy.
446 * XXX To make a simplex device behave exactly like a duplex
447 * device, we should copy in the case of sending to our own
448 * ethernet address (thus letting the original actually appear
449 * on the wire). However, we don't do that here for security
450 * reasons and compatibility with the original behavior.
451 */
452 if ((ifp->if_flags & IFF_SIMPLEX) &&
453 ((*m)->m_flags & M_LOOP)) {
454 if (lo_dlt == 0)
7b1edb79 455 dlil_find_dltag(APPLE_IF_FAM_LOOPBACK, 0, PF_INET, &lo_dlt);
1c79356b
A
456
457 if (lo_dlt) {
7b1edb79
A
458 if ((*m)->m_flags & M_BCAST) {
459 struct mbuf *n = m_copy(*m, 0, (int)M_COPYALL);
460 if (n != NULL)
461 dlil_output(lo_dlt, n, 0, ndest, 0);
462 }
463 else
464 {
465 if (bcmp(edst, ac->ac_enaddr, ETHER_ADDR_LEN) == 0) {
466 dlil_output(lo_dlt, *m, 0, ndest, 0);
467 return EJUSTRETURN;
468 }
469 }
1c79356b
A
470 }
471 }
7b1edb79
A
472
473
1c79356b
A
474 /*
475 * Add local net header. If no space in first mbuf,
476 * allocate another.
477 */
478 M_PREPEND(*m, sizeof (struct ether_header), M_DONTWAIT);
479 if (*m == 0) {
480 return (EJUSTRETURN);
481 }
482
483
484 eh = mtod(*m, struct ether_header *);
485 (void)memcpy(&eh->ether_type, ether_type,
486 sizeof(eh->ether_type));
487 (void)memcpy(eh->ether_dhost, edst, 6);
488 (void)memcpy(eh->ether_shost, ac->ac_enaddr,
489 sizeof(eh->ether_shost));
490
491 return 0;
492}
493
494
495static
496int ether_add_if(struct ifnet *ifp)
497{
498 u_long i;
499
500 ifp->if_framer = ether_frameout;
501 ifp->if_demux = ether_demux;
502 ifp->if_event = 0;
503
504 for (i=0; i < MAX_INTERFACES; i++)
7b1edb79
A
505 if (ether_desc_blk[i].n_count == 0)
506 break;
1c79356b
A
507
508 if (i == MAX_INTERFACES)
7b1edb79 509 return ENOMEM;
1c79356b 510
7b1edb79
A
511 ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE * sizeof(struct en_desc),
512 M_IFADDR, M_WAITOK);
1c79356b 513 if (ether_desc_blk[i].block_ptr == 0)
7b1edb79 514 return ENOMEM;
1c79356b 515
7b1edb79
A
516 ether_desc_blk[i].n_count = ETHER_DESC_BLK_SIZE;
517 bzero(ether_desc_blk[i].block_ptr, ETHER_DESC_BLK_SIZE * sizeof(struct en_desc));
1c79356b
A
518
519 ifp->family_cookie = i;
520
521 return 0;
522}
523
524static
525int ether_del_if(struct ifnet *ifp)
526{
527 if ((ifp->family_cookie < MAX_INTERFACES) &&
7b1edb79
A
528 (ether_desc_blk[ifp->family_cookie].n_count))
529 {
530 FREE(ether_desc_blk[ifp->family_cookie].block_ptr, M_IFADDR);
531 ether_desc_blk[ifp->family_cookie].block_ptr = NULL;
532 ether_desc_blk[ifp->family_cookie].n_count = 0;
533 ether_desc_blk[ifp->family_cookie].n_max_used = 0;
534 return 0;
1c79356b
A
535 }
536 else
7b1edb79 537 return ENOENT;
1c79356b
A
538}
539
9bccf70c
A
540static
541int ether_init_if(struct ifnet *ifp)
542{
543 register struct ifaddr *ifa;
544 register struct sockaddr_dl *sdl;
545
546 ifa = ifnet_addrs[ifp->if_index - 1];
547 if (ifa == 0) {
548 printf("ether_ifattach: no lladdr!\n");
549 return;
550 }
551 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
552 sdl->sdl_type = IFT_ETHER;
553 sdl->sdl_alen = ifp->if_addrlen;
554 bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
555
556 return 0;
557}
1c79356b
A
558
559
560int
561ether_ifmod_ioctl(ifp, command, data)
562 struct ifnet *ifp;
563 u_long command;
564 caddr_t data;
565{
566 struct rslvmulti_req *rsreq = (struct rslvmulti_req *) data;
567 int error = 0;
568 struct sockaddr_dl *sdl;
569 struct sockaddr_in *sin;
570 u_char *e_addr;
571
572
7b1edb79
A
573 switch (command) {
574 case SIOCRSLVMULTI:
575 switch(rsreq->sa->sa_family) {
576 case AF_UNSPEC:
577 /* AppleTalk uses AF_UNSPEC for multicast registration.
578 * No mapping needed. Just check that it's a valid MC address.
579 */
580 e_addr = &rsreq->sa->sa_data[0];
581 if ((e_addr[0] & 1) != 1)
582 return EADDRNOTAVAIL;
583 *rsreq->llsa = 0;
584 return EJUSTRETURN;
585
586
587 case AF_LINK:
588 /*
589 * No mapping needed. Just check that it's a valid MC address.
590 */
591 sdl = (struct sockaddr_dl *)rsreq->sa;
592 e_addr = LLADDR(sdl);
593 if ((e_addr[0] & 1) != 1)
594 return EADDRNOTAVAIL;
595 *rsreq->llsa = 0;
596 return EJUSTRETURN;
597
598 default:
599 return EAFNOSUPPORT;
600 }
601
602 default:
603 return EOPNOTSUPP;
1c79356b
A
604 }
605}
606
607
608int ether_family_init()
609{
610 int i;
611 struct dlil_ifmod_reg_str ifmod_reg;
612
9bccf70c
A
613 /* ethernet family is built-in, called from bsd_init */
614 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
1c79356b 615
9bccf70c 616 bzero(&ifmod_reg, sizeof(ifmod_reg));
1c79356b
A
617 ifmod_reg.add_if = ether_add_if;
618 ifmod_reg.del_if = ether_del_if;
9bccf70c 619 ifmod_reg.init_if = ether_init_if;
1c79356b
A
620 ifmod_reg.add_proto = ether_add_proto;
621 ifmod_reg.del_proto = ether_del_proto;
622 ifmod_reg.ifmod_ioctl = ether_ifmod_ioctl;
623 ifmod_reg.shutdown = ether_shutdown;
624
625 if (dlil_reg_if_modules(APPLE_IF_FAM_ETHERNET, &ifmod_reg)) {
7b1edb79
A
626 printf("WARNING: ether_family_init -- Can't register if family modules\n");
627 return EIO;
1c79356b
A
628 }
629
1c79356b 630 for (i=0; i < MAX_INTERFACES; i++)
7b1edb79 631 ether_desc_blk[i].n_count = 0;
1c79356b 632
9bccf70c
A
633 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
634
1c79356b
A
635 return 0;
636}