]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/dlil_ethersubr.c
xnu-201.14.tar.gz
[apple/xnu.git] / bsd / net / dlil_ethersubr.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 <net/ndrv.h>
74
75 #if INET
76 #include <netinet/in.h>
77 #include <netinet/in_var.h>
78 #include <netinet/if_ether.h>
79 #include <netinet/in_systm.h>
80 #include <netinet/ip.h>
81 #endif
82 #if INET6
83 #include <netinet6/nd6.h>
84 #include <netinet6/in6_ifattach.h>
85 #endif
86
87
88 #include <sys/socketvar.h>
89 #include <net/if_blue.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
116 extern struct ifnet_blue *blue_if;
117 extern struct mbuf *splitter_input(struct mbuf *, struct ifnet *);
118
119 static u_long lo_dlt = 0;
120 static ivedonethis = 0;
121 static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
122 struct sockaddr *));
123 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
124
125 #define IFP2AC(IFP) ((struct arpcom *)IFP)
126
127 /* This stuff is new */
128
129 #define DB_HEADER_SIZE 20
130 struct en_desc {
131 short total_len;
132 u_short ethertype;
133 u_long dl_tag;
134 struct ifnet *ifp;
135 struct if_proto *proto;
136 u_long proto_id_length;
137 u_long proto_id_data[8]; /* probably less - proto-id and bitmasks */
138 };
139
140 #define LITMUS_SIZE 16
141 #define ETHER_DESC_BLK_SIZE 50
142 #define MAX_INTERFACES 50
143
144 /*
145 * Statics for demux module
146 */
147
148 struct ether_desc_blk_str {
149 u_long n_blocks;
150 u_long *block_ptr;
151 };
152
153 struct dl_es_at_entry
154 {
155 struct ifnet *ifp;
156 u_long dl_tag;
157 int ref_count;
158 };
159
160
161 static struct ether_desc_blk_str ether_desc_blk[MAX_INTERFACES];
162 static u_long litmus_mask[LITMUS_SIZE];
163 static u_long litmus_length = 0;
164
165
166 /*
167 * Temp static for protocol registration XXX
168 */
169
170 #define MAX_EN_COUNT 30
171
172 static struct dl_es_at_entry en_at_array[MAX_EN_COUNT];
173
174 /*
175 * This could be done below in-line with heavy casting, but the pointer arithmetic is
176 * prone to error.
177 */
178
179 static
180 int desc_in_bounds(block, current_ptr, offset_length)
181 u_int block;
182 char *current_ptr;
183 u_long offset_length;
184 {
185 u_long end_of_block;
186 u_long current_ptr_tmp;
187
188 current_ptr_tmp = (u_long) current_ptr;
189 end_of_block = (u_long) ether_desc_blk[block].block_ptr;
190 end_of_block += (ETHER_DESC_BLK_SIZE * ether_desc_blk[block].n_blocks);
191 if ((current_ptr_tmp + offset_length) < end_of_block)
192 return 1;
193 else
194 return 0;
195 }
196
197
198 /*
199 * Release all descriptor entries owned by this dl_tag (there may be several).
200 * Setting the dl_tag to 0 releases the entry. Eventually we should compact-out
201 * the unused entries.
202 */
203 static
204 int ether_del_proto(struct if_proto *proto, u_long dl_tag)
205 {
206 char *current_ptr = (char *) ether_desc_blk[proto->ifp->family_cookie].block_ptr;
207 struct en_desc *ed;
208 int i;
209 int found = 0;
210
211 ed = (struct en_desc *) current_ptr;
212
213 while(ed->total_len) {
214 if (ed->dl_tag == dl_tag) {
215 found = 1;
216 ed->dl_tag = 0;
217 }
218
219 current_ptr += ed->total_len;
220 ed = (struct en_desc *) current_ptr;
221 }
222 }
223
224
225
226 static
227 int ether_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
228 {
229 char *current_ptr;
230 struct dlil_demux_desc *desc;
231 u_long id_length; /* IN LONGWORDS!!! */
232 struct en_desc *ed;
233 u_long *bitmask;
234 u_long *proto_id;
235 int i;
236 short total_length;
237 u_long block_count;
238 u_long *tmp;
239
240
241 TAILQ_FOREACH(desc, desc_head, next) {
242 switch (desc->type)
243 {
244 case DLIL_DESC_RAW:
245 id_length = desc->variants.bitmask.proto_id_length;
246 break;
247
248 case DLIL_DESC_802_2:
249 id_length = 1;
250 break;
251
252 case DLIL_DESC_802_2_SNAP:
253 id_length = 2;
254 break;
255
256 default:
257 return EINVAL;
258 }
259
260 restart:
261 block_count = ether_desc_blk[proto->ifp->family_cookie].n_blocks;
262 current_ptr = (char *) ether_desc_blk[proto->ifp->family_cookie].block_ptr;
263 ed = (struct en_desc *) current_ptr;
264 total_length = ((id_length << 2) * 2) + DB_HEADER_SIZE;
265
266 while ((ed->total_len) && (desc_in_bounds(proto->ifp->family_cookie,
267 current_ptr, total_length))) {
268 if ((ed->dl_tag == 0) && (total_length <= ed->total_len))
269 break;
270 else
271 current_ptr += *(short *)current_ptr;
272
273 ed = (struct en_desc *) current_ptr;
274 }
275
276 if (!desc_in_bounds(proto->ifp->family_cookie, current_ptr, total_length)) {
277
278 tmp = _MALLOC((ETHER_DESC_BLK_SIZE * (block_count + 1)),
279 M_IFADDR, M_WAITOK);
280 if (tmp == 0) {
281 /*
282 * Remove any previous descriptors set in the call.
283 */
284 ether_del_proto(proto, dl_tag);
285 return ENOMEM;
286 }
287
288 bzero(tmp, ETHER_DESC_BLK_SIZE * (block_count + 1));
289 bcopy(ether_desc_blk[proto->ifp->family_cookie].block_ptr,
290 tmp, (ETHER_DESC_BLK_SIZE * block_count));
291 FREE(ether_desc_blk[proto->ifp->family_cookie].block_ptr, M_IFADDR);
292 ether_desc_blk[proto->ifp->family_cookie].n_blocks = block_count + 1;
293 ether_desc_blk[proto->ifp->family_cookie].block_ptr = tmp;
294 goto restart;
295 }
296
297 if (ed->total_len == 0)
298 ed->total_len = total_length;
299 ed->ethertype = *((u_short *) desc->native_type);
300
301 ed->dl_tag = dl_tag;
302 ed->proto = proto;
303 ed->proto_id_length = id_length;
304 ed->ifp = proto->ifp;
305
306 switch (desc->type)
307 {
308 case DLIL_DESC_RAW:
309 bcopy(desc->variants.bitmask.proto_id, &ed->proto_id_data[0], (id_length << 2) );
310 bcopy(desc->variants.bitmask.proto_id_mask, &ed->proto_id_data[id_length],
311 (id_length << 2));
312 break;
313
314 case DLIL_DESC_802_2:
315 ed->proto_id_data[0] = 0;
316 bcopy(&desc->variants.desc_802_2, &ed->proto_id_data[0], 3);
317 ed->proto_id_data[1] = 0xffffff00;
318 break;
319
320 case DLIL_DESC_802_2_SNAP:
321 /* XXX Add verification of fixed values here */
322
323 ed->proto_id_data[0] = 0;
324 ed->proto_id_data[1] = 0;
325 bcopy(&desc->variants.desc_802_2_SNAP, &ed->proto_id_data[0], 8);
326 ed->proto_id_data[2] = 0xffffffff;
327 ed->proto_id_data[3] = 0xffffffff;;
328 break;
329 }
330
331 if (id_length) {
332 proto_id = (u_long *) &ed->proto_id_data[0];
333 bitmask = (u_long *) &ed->proto_id_data[id_length];
334 for (i=0; i < (id_length); i++) {
335 litmus_mask[i] &= bitmask[i];
336 litmus_mask[i] &= proto_id[i];
337 }
338 if (id_length > litmus_length)
339 litmus_length = id_length;
340 }
341 }
342
343 return 0;
344 }
345
346
347 static
348 int ether_shutdown()
349 {
350 return 0;
351 }
352
353
354
355
356 /*
357 * Process a received Ethernet packet;
358 * the packet is in the mbuf chain m without
359 * the ether header, which is provided separately.
360 */
361 int
362 new_ether_input(m, frame_header, ifp, dl_tag, sync_ok)
363 struct mbuf *m;
364 char *frame_header;
365 struct ifnet *ifp;
366 u_long dl_tag;
367 int sync_ok;
368
369 {
370 register struct ether_header *eh = (struct ether_header *) frame_header;
371 register struct ifqueue *inq=0;
372 u_short ether_type;
373 int s;
374 u_int16_t ptype = -1;
375 unsigned char buf[18];
376
377 #if ISO || LLC || NETAT
378 register struct llc *l;
379 #endif
380
381
382 #if DLIL_BLUEBOX
383
384 /*
385 * Y-adapter input processing:
386 * - Don't split if coming from a dummy if
387 * - If coming from a real if, if splitting enabled,
388 * then filter the incoming packet
389 */
390 if (ifp != (struct ifnet *)blue_if)
391 { /* Is splitter turned on? */
392 if (ifp->if_flags&IFF_SPLITTER)
393 { m->m_data -= sizeof(struct ether_header);
394 m->m_len += sizeof (struct ether_header);
395 m->m_pkthdr.len += sizeof(struct ether_header);
396 /*
397 * Check to see if destined for BlueBox or Rhapsody
398 * If NULL return, mbuf's been consumed by the BlueBox.
399 * Otherwise, send on to Rhapsody
400 */
401 if ((m = splitter_input(m, ifp)) == NULL)
402 return EJUSTRETURN;
403 m->m_data += sizeof(struct ether_header);
404 m->m_len -= sizeof (struct ether_header);
405 m->m_pkthdr.len -= sizeof(struct ether_header);
406 }
407 } else
408 { /* Get the "real" IF */
409 ifp = ((struct ndrv_cb *)(blue_if->ifb_so->so_pcb))->nd_if;
410 m->m_pkthdr.rcvif = ifp;
411 blue_if->pkts_looped_b2r++;
412 }
413
414 #endif
415 if ((ifp->if_flags & IFF_UP) == 0) {
416 m_freem(m);
417 return EJUSTRETURN;
418 }
419
420 ifp->if_lastchange = time;
421
422 if (eh->ether_dhost[0] & 1) {
423 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
424 sizeof(etherbroadcastaddr)) == 0)
425 m->m_flags |= M_BCAST;
426 else
427 m->m_flags |= M_MCAST;
428 }
429 if (m->m_flags & (M_BCAST|M_MCAST))
430 ifp->if_imcasts++;
431
432 ether_type = ntohs(eh->ether_type);
433
434 #if NVLAN > 0
435 if (ether_type == vlan_proto) {
436 if (vlan_input(eh, m) < 0)
437 ifp->if_data.ifi_noproto++;
438 return EJUSTRETURN;
439 }
440 #endif /* NVLAN > 0 */
441
442 switch (ether_type) {
443 #if INET
444 case ETHERTYPE_IP:
445 if (ipflow_fastforward(m))
446 return EJUSTRETURN;
447 ptype = mtod(m, struct ip *)->ip_p;
448 if ((sync_ok == 0) ||
449 (ptype != IPPROTO_TCP && ptype != IPPROTO_UDP)) {
450 schednetisr(NETISR_IP);
451 }
452
453 inq = &ipintrq;
454 break;
455
456 case ETHERTYPE_ARP:
457 schednetisr(NETISR_ARP);
458 inq = &arpintrq;
459 break;
460 #endif
461 #if INET6
462 case ETHERTYPE_IPV6:
463 schednetisr(NETISR_IPV6);
464 inq = &ip6intrq;
465 break;
466 #endif
467
468
469 default: {
470 #if NETAT
471 if (ether_type > ETHERMTU)
472 return ENOENT;
473 l = mtod(m, struct llc *);
474 switch (l->llc_dsap) {
475 case LLC_SNAP_LSAP:
476
477 /* Temporary hack: check for AppleTalk and AARP packets */
478 /* WARNING we're checking only on the "ether_type" (the 2 bytes
479 * of the SNAP header. This shouldn't be a big deal,
480 * AppleTalk pat_input is making sure we have the right packets
481 * because it needs to discrimante AARP from EtherTalk packets.
482 */
483
484 if (l->llc_ssap == LLC_SNAP_LSAP &&
485 l->llc_un.type_snap.control == 0x03) {
486
487 #ifdef APPLETALK_DEBUG
488 printf("new_ether_input: SNAP Cntrol type=0x%x Src=%s\n",
489 l->llc_un.type_snap.ether_type,
490 ether_sprintf(buf, &eh->ether_shost));
491 printf(" Dst=%s\n",
492 ether_sprintf(buf, &eh->ether_dhost));
493 #endif /* APPLETALK_DEBUG */
494
495 if ((l->llc_un.type_snap.ether_type == 0x809B) ||
496 (l->llc_un.type_snap.ether_type == 0x80F3)) {
497
498
499 /*
500 * note: for AppleTalk we need to pass the enet header of the
501 * packet up stack. To do so, we made sure in that the FULL packet
502 * is copied in the mbuf by the mace driver, and only the m_data and
503 * length have been shifted to make IP and the other guys happy.
504 */
505
506 m->m_data -= sizeof(*eh);
507 m->m_len += sizeof(*eh);
508 m->m_pkthdr.len += sizeof(*eh);
509 #ifdef APPLETALK_DEBUG
510 l == (struct llc *)(eh+1);
511 if (l->llc_un.type_snap.ether_type == 0x80F3) {
512 kprintf("new_ether_input: RCV AppleTalk type=0x%x Src=%s\n",
513 l->llc_un.type_snap.ether_type,
514 ether_sprintf(buf, &eh->ether_shost));
515 kprintf(" Dst=%s\n",
516 ether_sprintf(buf, &eh->ether_dhost));
517 }
518 #endif /* APPLETALK_DEBUG */
519 schednetisr(NETISR_APPLETALK);
520 inq = &atalkintrq ;
521
522 break;
523 }
524 }
525
526 break;
527
528
529 default:
530 return ENOENT;
531 }
532
533 #else /*NETAT*/
534 return ENOENT;
535 #endif /* NETAT */
536
537 }
538 }
539
540 if (inq == 0)
541 return ENOENT;
542
543 s = splimp();
544 if (IF_QFULL(inq)) {
545 IF_DROP(inq);
546 m_freem(m);
547 splx(s);
548 return EJUSTRETURN;
549 } else
550 IF_ENQUEUE(inq, m);
551 splx(s);
552
553 if ((sync_ok) &&
554 (ptype == IPPROTO_TCP || ptype == IPPROTO_UDP)) {
555 extern void ipintr(void);
556
557 s = splnet();
558 ipintr();
559 splx(s);
560 }
561
562 return 0;
563 }
564
565
566
567
568 int ether_demux(ifp, m, frame_header, proto)
569 struct ifnet *ifp;
570 struct mbuf *m;
571 char *frame_header;
572 struct if_proto **proto;
573
574 {
575 register struct ether_header *eh = (struct ether_header *)frame_header;
576 u_short ether_type;
577 char *current_ptr = (char *) ether_desc_blk[ifp->family_cookie].block_ptr;
578 struct dlil_demux_desc *desc;
579 register u_long temp;
580 u_long *data;
581 register struct if_proto *ifproto;
582 u_long i;
583 struct en_desc *ed;
584
585
586 if (eh->ether_dhost[0] & 1) {
587 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
588 sizeof(etherbroadcastaddr)) == 0)
589 m->m_flags |= M_BCAST;
590 else
591 m->m_flags |= M_MCAST;
592 }
593
594 ether_type = ntohs(eh->ether_type);
595
596 /*
597 * Search through the connected protocols for a match.
598 */
599
600
601 data = mtod(m, u_long *);
602 ed = (struct en_desc *) current_ptr;
603 while (desc_in_bounds(ifp->family_cookie, current_ptr, DB_HEADER_SIZE)) {
604 if (ed->total_len == 0)
605 break;
606
607 if ((ed->dl_tag != 0) && (ed->ifp == ifp) &&
608 ((ed->ethertype == ntohs(eh->ether_type)) || (ed->ethertype == 0))) {
609 if (ed->proto_id_length) {
610 for (i=0; i < (ed->proto_id_length); i++) {
611 temp = ntohs(data[i]) & ed->proto_id_data[ed->proto_id_length + i];
612 if ((temp ^ ed->proto_id_data[i]))
613 break;
614 }
615
616 if (i >= (ed->proto_id_length)) {
617 *proto = ed->proto;
618 return 0;
619 }
620 }
621 else {
622 *proto = ed->proto;
623 return 0;
624 }
625 }
626 current_ptr += ed->total_len;
627 ed = (struct en_desc *) current_ptr;
628 }
629
630 /*
631 kprintf("ether_demux - No match for <%x><%x><%x><%x><%x><%x><%x<%x>\n",
632 eh->ether_type,data[0], data[1], data[2], data[3], data[4],data[5],data[6]);
633 */
634
635 return ENOENT;
636 }
637
638
639
640 /*
641 * Ethernet output routine.
642 * Encapsulate a packet of type family for the local net.
643 * Use trailer local net encapsulation if enough data in first
644 * packet leaves a multiple of 512 bytes of data in remainder.
645 * Assumes that ifp is actually pointer to arpcom structure.
646 */
647 int
648 ether_frameout(ifp, m, ndest, edst, ether_type)
649 register struct ifnet *ifp;
650 struct mbuf **m;
651 struct sockaddr *ndest;
652 char *edst;
653 char *ether_type;
654 {
655 register struct ether_header *eh;
656 int hlen; /* link layer header lenght */
657 struct arpcom *ac = IFP2AC(ifp);
658
659
660 hlen = ETHER_HDR_LEN;
661
662 /*
663 * If a simplex interface, and the packet is being sent to our
664 * Ethernet address or a broadcast address, loopback a copy.
665 * XXX To make a simplex device behave exactly like a duplex
666 * device, we should copy in the case of sending to our own
667 * ethernet address (thus letting the original actually appear
668 * on the wire). However, we don't do that here for security
669 * reasons and compatibility with the original behavior.
670 */
671 if ((ifp->if_flags & IFF_SIMPLEX) &&
672 ((*m)->m_flags & M_LOOP)) {
673 if (lo_dlt == 0)
674 dlil_find_dltag(APPLE_IF_FAM_LOOPBACK, 0, PF_INET, &lo_dlt);
675
676 if (lo_dlt) {
677 if ((*m)->m_flags & M_BCAST) {
678 struct mbuf *n = m_copy(*m, 0, (int)M_COPYALL);
679 dlil_output(lo_dlt, n, 0, ndest, 0);
680 }
681 else
682 {
683 if (bcmp(edst, ac->ac_enaddr, ETHER_ADDR_LEN) == 0) {
684 dlil_output(lo_dlt, *m, 0, ndest, 0);
685 return EJUSTRETURN;
686 }
687 }
688 }
689 }
690
691
692 /*
693 * Add local net header. If no space in first mbuf,
694 * allocate another.
695 */
696 M_PREPEND(*m, sizeof (struct ether_header), M_DONTWAIT);
697 if (*m == 0) {
698 return (EJUSTRETURN);
699 }
700
701
702 eh = mtod(*m, struct ether_header *);
703 (void)memcpy(&eh->ether_type, ether_type,
704 sizeof(eh->ether_type));
705 (void)memcpy(eh->ether_dhost, edst, 6);
706 (void)memcpy(eh->ether_shost, ac->ac_enaddr,
707 sizeof(eh->ether_shost));
708
709 #if DLIL_BLUEBOX
710 /*
711 * We're already to send. Let's check for the blue box...
712 */
713 if (ifp->if_flags&IFF_SPLITTER)
714 {
715 (*m)->m_flags |= 0x10;
716 if ((*m = splitter_input(*m, ifp)) == NULL)
717 return EJUSTRETURN;
718 else
719 return (0);
720 }
721 else
722 #endif
723 return 0;
724 }
725
726
727 static
728 int ether_add_if(struct ifnet *ifp)
729 {
730 u_long i;
731
732 ifp->if_framer = ether_frameout;
733 ifp->if_demux = ether_demux;
734
735 for (i=0; i < MAX_INTERFACES; i++)
736 if (ether_desc_blk[i].n_blocks == 0)
737 break;
738
739 if (i == MAX_INTERFACES)
740 return EOVERFLOW;
741
742 ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE, M_IFADDR, M_WAITOK);
743 if (ether_desc_blk[i].block_ptr == 0)
744 return ENOMEM;
745
746 ether_desc_blk[i].n_blocks = 1;
747 bzero(ether_desc_blk[i].block_ptr, ETHER_DESC_BLK_SIZE);
748
749 ifp->family_cookie = i;
750
751 return 0;
752 }
753
754 static
755 int ether_del_if(struct ifnet *ifp)
756 {
757 if ((ifp->family_cookie < MAX_INTERFACES) &&
758 (ether_desc_blk[ifp->family_cookie].n_blocks)) {
759 FREE(ether_desc_blk[ifp->family_cookie].block_ptr, M_IFADDR);
760 ether_desc_blk[ifp->family_cookie].n_blocks = 0;
761 return 0;
762 }
763 else
764 return ENOENT;
765 }
766
767
768
769
770 int
771 ether_pre_output(ifp, m0, dst_netaddr, route, type, edst, dl_tag )
772 struct ifnet *ifp;
773 struct mbuf **m0;
774 struct sockaddr *dst_netaddr;
775 caddr_t route;
776 char *type;
777 char *edst;
778 u_long dl_tag;
779 {
780 struct rtentry *rt0 = (struct rtentry *) route;
781 int s;
782 register struct mbuf *m = *m0;
783 register struct rtentry *rt;
784 register struct ether_header *eh;
785 int off, len = m->m_pkthdr.len;
786 int hlen; /* link layer header lenght */
787 struct arpcom *ac = IFP2AC(ifp);
788
789
790
791 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
792 return ENETDOWN;
793
794 rt = rt0;
795 if (rt) {
796 if ((rt->rt_flags & RTF_UP) == 0) {
797 rt0 = rt = rtalloc1(dst_netaddr, 1, 0UL);
798 if (rt0)
799 rt->rt_refcnt--;
800 else
801 return EHOSTUNREACH;
802 }
803
804 if (rt->rt_flags & RTF_GATEWAY) {
805 if (rt->rt_gwroute == 0)
806 goto lookup;
807 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
808 rtfree(rt); rt = rt0;
809 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
810 0UL);
811 if ((rt = rt->rt_gwroute) == 0)
812 return (EHOSTUNREACH);
813 }
814 }
815
816
817 if (rt->rt_flags & RTF_REJECT)
818 if (rt->rt_rmx.rmx_expire == 0 ||
819 time_second < rt->rt_rmx.rmx_expire)
820 return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
821 }
822
823 hlen = ETHER_HDR_LEN;
824
825 /*
826 * Tell ether_frameout it's ok to loop packet unless negated below.
827 */
828 m->m_flags |= M_LOOP;
829
830 switch (dst_netaddr->sa_family) {
831
832 #if INET
833 case AF_INET:
834 if (!arpresolve(ac, rt, m, dst_netaddr, edst, rt0))
835 return (EJUSTRETURN); /* if not yet resolved */
836 off = m->m_pkthdr.len - m->m_len;
837 *(u_short *)type = htons(ETHERTYPE_IP);
838 break;
839 #endif
840
841 #if INET6
842 case AF_INET6:
843 if (!nd6_storelladdr(&ac->ac_if, rt, m, dst_netaddr, (u_char *)edst)) {
844 /* this must be impossible, so we bark */
845 kprintf("nd6_storelladdr failed\n");
846 return(0);
847 }
848 off = m->m_pkthdr.len - m->m_len;
849 *(u_short *)type = htons(ETHERTYPE_IPV6);
850 break;
851 #endif
852
853
854 case AF_UNSPEC:
855 m->m_flags &= ~M_LOOP;
856 eh = (struct ether_header *)dst_netaddr->sa_data;
857 (void)memcpy(edst, eh->ether_dhost, 6);
858 *(u_short *)type = eh->ether_type;
859 break;
860
861 #if NETAT
862 case AF_APPLETALK:
863 {
864 eh = (struct ether_header *)dst_netaddr->sa_data;
865 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, 6);
866
867 *(u_short *)type = m->m_pkthdr.len;
868 }
869 break;
870
871 #endif /* NETAT */
872
873 default:
874 kprintf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
875 dst_netaddr->sa_family);
876
877 return EAFNOSUPPORT;
878 }
879
880 return (0);
881 }
882
883
884
885
886
887 int
888 ether_ioctl(dl_tag, ifp, command, data)
889 u_long dl_tag;
890 struct ifnet *ifp;
891 int command;
892 caddr_t data;
893 {
894 struct ifaddr *ifa = (struct ifaddr *) data;
895 struct ifreq *ifr = (struct ifreq *) data;
896 int error = 0;
897 boolean_t funnel_state;
898
899 funnel_state = thread_funnel_set(TRUE);
900
901 switch (command) {
902 case SIOCSIFADDR:
903 ifp->if_flags |= IFF_UP;
904
905 switch (ifa->ifa_addr->sa_family) {
906
907 case AF_INET:
908
909 if (ifp->if_init)
910 ifp->if_init(ifp->if_softc); /* before arpwhohas */
911
912
913 arp_ifinit(IFP2AC(ifp), ifa);
914
915 break;
916
917 default:
918 break;
919 }
920
921 break;
922
923 case SIOCGIFADDR:
924 {
925 struct sockaddr *sa;
926
927 sa = (struct sockaddr *) & ifr->ifr_data;
928 bcopy(IFP2AC(ifp)->ac_enaddr,
929 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
930 }
931 break;
932
933 case SIOCSIFMTU:
934 /*
935 * Set the interface MTU.
936 */
937 if (ifr->ifr_mtu > ETHERMTU) {
938 error = EINVAL;
939 } else {
940 ifp->if_mtu = ifr->ifr_mtu;
941 }
942 break;
943 }
944
945 (void) thread_funnel_set(funnel_state);
946
947 return (error);
948 }
949
950
951
952
953 /*
954 * Y-adapter filter check
955 * The rules here:
956 * For Rhap: return 1
957 * For Both: return 0
958 * Not for Rhap: return -1
959 * Multicast/Broadcast => For Both
960 * Atalk address registered
961 * filter matches => For Rhap else Not For Rhap
962 * IP address registered
963 * filter matches => For Rhap else Not For Rhap
964 * For Rhap
965 * Note this is *not* a general filter mechanism in that we know
966 * what we *could* be looking for.
967 * WARNING: this is a big-endian routine.
968 * Note: ARP and AARP packets are implicitly accepted for "both"
969 */
970 int
971 Filter_check(struct mbuf **m0)
972 { register struct BlueFilter *bf;
973 register unsigned char *p;
974 register unsigned short *s;
975 register unsigned long *l;
976 int total, flags;
977 struct mbuf *m;
978 extern struct mbuf *m_pullup(struct mbuf *, int);
979 extern void kprintf( const char *, ...);
980 #define FILTER_LEN 32
981
982 m = *m0;
983 flags = m->m_flags;
984 if (FILTER_LEN > m->m_pkthdr.len)
985 return(1);
986 while ((FILTER_LEN > m->m_len) && m->m_next) {
987 total = m->m_len + (m->m_next)->m_len;
988 if ((m = m_pullup(m, min(FILTER_LEN, total))) == 0)
989 return(-1);
990 }
991 *m0 = m;
992
993 p = mtod(m, unsigned char *); /* Point to destination media addr */
994 if (p[0] & 0x01) /* Multicast/broadcast */
995 return(0);
996 s = (unsigned short *)p;
997 bf = &RhapFilter[BFS_ATALK];
998 #if 0
999 kprintf("!PKT: %x, %x, %x\n", s[6], s[7], s[8]);
1000 #endif
1001
1002 if (bf->BF_flags) /* Filtering Appletalk */
1003 {
1004 l = (unsigned long *)&s[8];
1005 #if 0
1006 kprintf("!AT: %x, %x, %x, %x, %x, %x\n", s[6], s[7],
1007 *l, s[10], s[13], p[30]);
1008 #endif
1009 if (s[6] <= ETHERMTU)
1010 { if (s[7] == 0xaaaa) /* Could be Atalk */
1011 { /* Verify SNAP header */
1012 if (*l == 0x03080007 && s[10] == 0x809b)
1013 { if (s[13] == bf->BF_address &&
1014 p[30] == bf->BF_node)
1015 return(1);
1016 } else if (*l == 0x03000000 && s[10] == 0x80f3)
1017 /* AARP pkts aren't net-addressed */
1018 return(0);
1019 return(0);
1020 } else /* Not for us? */
1021 return(0);
1022 } /* Fall through */
1023 } /* Fall through */
1024 bf++; /* Look for IP next */
1025 if (bf->BF_flags) /* Filtering IP */
1026 {
1027 l = (unsigned long *)&s[15];
1028 #if 0
1029 kprintf("!IP: %x, %x\n", s[6], *l);
1030 #endif
1031 if (s[6] > ETHERMTU)
1032 { if (s[6] == 0x800) /* Is IP */
1033 { /* Verify IP address */
1034 if (*l == bf->BF_address)
1035 return(1);
1036 else /* Not for us */
1037 return(0);
1038 } else if (s[6] == 0x806)
1039 /* ARP pkts aren't net-addressed */
1040 return(0);
1041 }
1042 }
1043 return(0); /* No filters => Accept */
1044 }
1045
1046
1047
1048 int ether_family_init()
1049 {
1050
1051 int i;
1052
1053 if (ivedonethis)
1054 return 0;
1055
1056 ivedonethis = 1;
1057
1058
1059 if (dlil_reg_if_modules(APPLE_IF_FAM_ETHERNET, ether_add_if, ether_del_if,
1060 ether_add_proto, ether_del_proto,
1061 ether_shutdown)) {
1062 printf("WARNING: ether_family_init -- Can't register if family modules\n");
1063 return EIO;
1064 }
1065
1066 for (i=0; i < (LITMUS_SIZE/4); i++)
1067 litmus_mask[i] = 0xffffffff;
1068
1069 for (i=0; i < MAX_INTERFACES; i++)
1070 ether_desc_blk[i].n_blocks = 0;
1071
1072 for (i=0; i < MAX_EN_COUNT; i++)
1073 en_at_array[i].ifp = 0;
1074
1075 return 0;
1076 }
1077
1078
1079
1080 u_long ether_attach_inet(struct ifnet *ifp)
1081 {
1082 struct dlil_proto_reg_str reg;
1083 struct dlil_demux_desc desc;
1084 struct dlil_demux_desc desc2;
1085 #if INET6
1086 struct dlil_demux_desc desc3;
1087 #endif
1088 u_long ip_dl_tag=0;
1089 u_short en_native=ETHERTYPE_IP;
1090 u_short arp_native=ETHERTYPE_ARP;
1091 #if INET6
1092 u_short en_6native=ETHERTYPE_IPV6;
1093 #endif
1094 int stat;
1095 int i;
1096
1097
1098 stat = dlil_find_dltag(ifp->if_family, ifp->if_unit, PF_INET, &ip_dl_tag);
1099 if (stat == 0)
1100 return ip_dl_tag;
1101
1102 TAILQ_INIT(&reg.demux_desc_head);
1103 desc.type = DLIL_DESC_RAW;
1104 desc.variants.bitmask.proto_id_length = 0;
1105 desc.variants.bitmask.proto_id = 0;
1106 desc.variants.bitmask.proto_id_mask = 0;
1107 desc.native_type = (char *) &en_native;
1108 TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
1109 reg.interface_family = ifp->if_family;
1110 reg.unit_number = ifp->if_unit;
1111 reg.input = new_ether_input;
1112 reg.pre_output = ether_pre_output;
1113 reg.event = 0;
1114 reg.offer = 0;
1115 reg.ioctl = ether_ioctl;
1116 reg.default_proto = 1;
1117 reg.protocol_family = PF_INET;
1118
1119 desc2 = desc;
1120 desc2.native_type = (char *) &arp_native;
1121 TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc2, next);
1122
1123 #if INET6
1124 desc3 = desc;
1125 desc3.native_type = (char *) &en_6native;
1126 TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc3, next);
1127 #endif
1128
1129 stat = dlil_attach_protocol(&reg, &ip_dl_tag);
1130 if (stat) {
1131 printf("WARNING: ether_attach_inet can't attach ip to interface\n");
1132 return stat;
1133 }
1134
1135 return ip_dl_tag;
1136 }
1137
1138 void ether_attach_at(struct ifnet *ifp, u_long *at_dl_tag, u_long *aarp_dl_tag)
1139 {
1140 struct dlil_proto_reg_str reg;
1141 struct dlil_demux_desc desc;
1142 struct dlil_demux_desc desc2;
1143 u_short native = 0; /* 802.2 frames use a length here */
1144 int stat;
1145 int first_empty;
1146 int i;
1147
1148
1149 first_empty = MAX_EN_COUNT;
1150 for (i=0; i < MAX_EN_COUNT; i++) {
1151 if (en_at_array[i].ifp == 0)
1152 first_empty = i;
1153
1154 if (en_at_array[i].ifp == ifp) {
1155 en_at_array[i].ref_count++;
1156 *at_dl_tag = *aarp_dl_tag = en_at_array[i].dl_tag;
1157 return;
1158 }
1159 }
1160
1161 if (first_empty == MAX_EN_COUNT)
1162 return;
1163
1164 TAILQ_INIT(&reg.demux_desc_head);
1165 desc.type = DLIL_DESC_802_2_SNAP;
1166 desc.variants.desc_802_2_SNAP.dsap = LLC_SNAP_LSAP;
1167 desc.variants.desc_802_2_SNAP.ssap = LLC_SNAP_LSAP;
1168 desc.variants.desc_802_2_SNAP.control_code = 0x03;
1169 desc.variants.desc_802_2_SNAP.org[0] = 0x08;
1170 desc.variants.desc_802_2_SNAP.org[1] = 0x00;
1171 desc.variants.desc_802_2_SNAP.org[2] = 0x07;
1172 desc.variants.desc_802_2_SNAP.protocol_type = 0x809B;
1173 desc.native_type = (char *) &native;
1174 TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
1175 reg.interface_family = ifp->if_family;
1176 reg.unit_number = ifp->if_unit;
1177 reg.input = new_ether_input;
1178 reg.pre_output = ether_pre_output;
1179 reg.event = 0;
1180 reg.offer = 0;
1181 reg.ioctl = ether_ioctl;
1182 reg.default_proto = 0;
1183 reg.protocol_family = PF_APPLETALK;
1184
1185 desc2 = desc;
1186 desc2.variants.desc_802_2_SNAP.protocol_type = 0x80F3;
1187 desc2.variants.desc_802_2_SNAP.org[0] = 0;
1188 desc2.variants.desc_802_2_SNAP.org[1] = 0;
1189 desc2.variants.desc_802_2_SNAP.org[2] = 0;
1190
1191 TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc2, next);
1192
1193 stat = dlil_attach_protocol(&reg, at_dl_tag);
1194 if (stat) {
1195 printf("WARNING: ether_attach_at can't attach at to interface\n");
1196 return;
1197 }
1198
1199 *aarp_dl_tag = *at_dl_tag;
1200
1201 en_at_array[first_empty].ifp = ifp;
1202 en_at_array[first_empty].dl_tag = *at_dl_tag;
1203 en_at_array[first_empty].ref_count = 1;
1204
1205 } /* ether_attach_at */
1206
1207
1208 void ether_detach_at(struct ifnet *ifp)
1209 {
1210 int i;
1211
1212 for (i=0; i < MAX_EN_COUNT; i++) {
1213 if (en_at_array[i].ifp == ifp)
1214 break;
1215 }
1216
1217 if (i < MAX_EN_COUNT) {
1218 if (en_at_array[i].ref_count > 1)
1219 en_at_array[i].ref_count--;
1220 else {
1221 if (en_at_array[i].ref_count == 1) {
1222 dlil_detach_protocol(en_at_array[i].dl_tag);
1223 en_at_array[i].ifp = 0;
1224 }
1225 }
1226 }
1227 }