]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/ether_if_module.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / bsd / net / ether_if_module.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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>
76 #include <netinet/if_ether.h>
77 #include <netinet/in.h> /* For M_LOOP */
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
95 extern 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
102 extern 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
115 static u_long lo_dlt = 0;
116
117 #define IFP2AC(IFP) ((struct arpcom *)IFP)
118
119 struct en_desc {
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 */
123 };
124
125 #define ETHER_DESC_BLK_SIZE (10)
126 #define MAX_INTERFACES 50
127
128 /*
129 * Statics for demux module
130 */
131
132 struct ether_desc_blk_str {
133 u_long n_max_used;
134 u_long n_count;
135 struct en_desc *block_ptr;
136 };
137
138
139 static struct ether_desc_blk_str ether_desc_blk[MAX_INTERFACES];
140
141
142 /*
143 * Release all descriptor entries owned by this dl_tag (there may be several).
144 * Setting the type to 0 releases the entry. Eventually we should compact-out
145 * the unused entries.
146 */
147 static
148 int ether_del_proto(struct if_proto *proto, u_long dl_tag)
149 {
150 struct en_desc* ed = ether_desc_blk[proto->ifp->family_cookie].block_ptr;
151 u_long current = 0;
152 int found = 0;
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 }
164 }
165
166 return found;
167 }
168
169
170
171 static int
172 ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
173 {
174 char *current_ptr;
175 struct dlil_demux_desc *desc;
176 struct en_desc *ed;
177 struct en_desc *last;
178 u_long *bitmask;
179 u_long *proto_id;
180 u_long i;
181 short total_length;
182 u_long block_count;
183 u_long *tmp;
184
185
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;
255 ed[i].data[0] = 0;
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;
297 bcopy(desc->native_type, pDest, 5);
298 }
299 break;
300 }
301 }
302
303 return 0;
304 }
305
306
307 static
308 int ether_shutdown()
309 {
310 return 0;
311 }
312
313
314 int 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;
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
331 if (eh->ether_dhost[0] & 1) {
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;
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 }
356 }
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
365 if (ntohs(ether_type) <= 1500) {
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
382 /*
383 * Search through the connected protocols for a match.
384 */
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;
414 }
415
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 */
428 int
429 ether_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)
455 dlil_find_dltag(APPLE_IF_FAM_LOOPBACK, 0, PF_INET, &lo_dlt);
456
457 if (lo_dlt) {
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 }
470 }
471 }
472
473
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
495 static
496 int 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++)
505 if (ether_desc_blk[i].n_count == 0)
506 break;
507
508 if (i == MAX_INTERFACES)
509 return ENOMEM;
510
511 ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE * sizeof(struct en_desc),
512 M_IFADDR, M_WAITOK);
513 if (ether_desc_blk[i].block_ptr == 0)
514 return ENOMEM;
515
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));
518
519 ifp->family_cookie = i;
520
521 return 0;
522 }
523
524 static
525 int ether_del_if(struct ifnet *ifp)
526 {
527 if ((ifp->family_cookie < MAX_INTERFACES) &&
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;
535 }
536 else
537 return ENOENT;
538 }
539
540 static
541 int 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 }
558
559
560 int
561 ether_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
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;
604 }
605 }
606
607
608 int ether_family_init()
609 {
610 int i;
611 struct dlil_ifmod_reg_str ifmod_reg;
612
613 /* ethernet family is built-in, called from bsd_init */
614 thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
615
616 bzero(&ifmod_reg, sizeof(ifmod_reg));
617 ifmod_reg.add_if = ether_add_if;
618 ifmod_reg.del_if = ether_del_if;
619 ifmod_reg.init_if = ether_init_if;
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)) {
626 printf("WARNING: ether_family_init -- Can't register if family modules\n");
627 return EIO;
628 }
629
630 for (i=0; i < MAX_INTERFACES; i++)
631 ether_desc_blk[i].n_count = 0;
632
633 thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
634
635 return 0;
636 }