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