2 * Copyright (c) 2000-2012 Apple, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright 1994 Apple Computer, Inc.
30 * All Rights Reserved.
32 * Tuyen A. Nguyen. (December 5, 1994)
33 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
36 #include <sys/errno.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <machine/spl.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
43 #include <sys/filedesc.h>
44 #include <sys/fcntl.h>
46 #include <sys/ioctl.h>
47 #include <sys/malloc.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/sockio.h>
53 #include <net/if_types.h>
54 #include <net/if_dl.h>
56 #include <net/ethernet.h>
57 #include <net/kpi_protocol.h>
59 #include <netat/sysglue.h>
60 #include <netat/appletalk.h>
61 #include <netat/at_pcb.h>
62 #include <netat/at_var.h>
63 #include <netat/ddp.h>
64 #include <netat/at_aarp.h>
65 #include <netat/at_pat.h>
66 #include <netat/atp.h>
67 #include <netat/debug.h>
69 #define DSAP_SNAP 0xaa
71 extern int adspInited
;
73 static llc_header_t snap_hdr_at
= SNAP_HDR_AT
;
74 static llc_header_t snap_hdr_aarp
= SNAP_HDR_AARP
;
75 static unsigned char snap_proto_ddp
[5] = SNAP_PROTO_AT
;
76 static unsigned char snap_proto_aarp
[5] = SNAP_PROTO_AARP
;
78 static void at_input_packet(protocol_family_t protocol
, mbuf_t m
);
80 struct ifqueue atalkintrq
; /* appletalk and aarp packet input queue */
82 short appletalk_inited
= 0;
84 void atalk_load(void);
85 void atalk_unload(void);
87 extern int pktsIn
, pktsOut
;
98 this happens in adsp_open and is undone on ADSP_UNLINK
100 domain_proto_mtx_unlock(TRUE
);
101 proto_register_input(PF_APPLETALK
, at_input_packet
, NULL
, 0);
102 domain_proto_mtx_lock();
105 /* Undo everything atalk_load() did. */
106 void atalk_unload() /* not currently used */
112 extern gbuf_t
*scb_resource_m
;
113 extern gbuf_t
*atp_resource_m
;
114 if (scb_resource_m
) {
115 gbuf_freem(scb_resource_m
);
119 /* allocated in atp_trans_alloc() */
120 if (atp_resource_m
) {
121 gbuf_freem(atp_resource_m
);
123 atp_trans_free_list
= 0;
128 appletalk_inited
= 0;
131 void appletalk_hack_start(void)
133 if (!appletalk_inited
) {
135 atalkintrq
.ifq_maxlen
= IFQ_MAXLEN
;
136 appletalk_inited
= 1;
138 } /* appletalk_hack_start */
140 int pat_output(patp
, mlist
, dst_addr
, type
)
142 struct mbuf
*mlist
; /* packet chain */
143 unsigned char *dst_addr
; /* for atalk addr - net # must be in network byte order */
147 llc_header_t
*llc_header
;
150 if (! patp
->aa_ifp
) {
151 for (m
= mlist
; m
; m
= mlist
) {
152 mlist
= m
->m_nextpkt
;
159 /* this is for ether_output */
160 dst
.sa_family
= AF_APPLETALK
;
161 dst
.sa_len
= 2 + sizeof(struct etalk_addr
);
162 bcopy (dst_addr
, &dst
.sa_data
[0], sizeof(struct etalk_addr
));
164 /* packet chains are used on output and can be tested using aufs */
165 for (m
= mlist
; m
; m
= mlist
) {
166 mlist
= m
->m_nextpkt
;
169 M_PREPEND(m
, sizeof(llc_header_t
), M_DONTWAIT
);
174 llc_header
= mtod(m
, llc_header_t
*);
176 (type
== AARP_AT_TYPE
) ? snap_hdr_aarp
: snap_hdr_at
;
178 for (m
->m_pkthdr
.len
= 0, m1
= m
; m1
; m1
= m1
->m_next
)
179 m
->m_pkthdr
.len
+= m1
->m_len
;
180 m
->m_pkthdr
.rcvif
= 0;
182 /* *** Note: AT is sending out mbufs of type MSG_DATA,
184 #ifdef APPLETALK_DEBUG
186 !((m
->m_next
)->m_flags
& M_EXT
))
187 kprintf("po: mlen= %d, m2len= %d\n", m
->m_len
,
191 dlil_output(patp
->aa_ifp
, PF_APPLETALK
, m
, NULL
, &dst
, 0, NULL
);
202 __unused protocol_family_t protocol
,
207 llc_header_t
*llc_header
;
210 enet_header_t
*enet_header
;
212 if (!appletalk_inited
) {
217 if ((m
->m_flags
& M_PKTHDR
) == 0) {
218 #ifdef APPLETALK_DEBUG
219 kprintf("atalkintr: no HDR on packet received");
225 /* make sure the interface this packet was received on is configured
227 ifp
= m
->m_pkthdr
.rcvif
;
228 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
229 if (ifID
->aa_ifp
&& (ifID
->aa_ifp
== ifp
))
232 /* if we didn't find a matching interface */
235 return; /* was EAFNOSUPPORT */
238 /* make sure the entire packet header is in the current mbuf */
239 if (m
->m_len
< ENET_LLC_SIZE
&&
240 (m
= m_pullup(m
, ENET_LLC_SIZE
)) == 0) {
241 #ifdef APPLETALK_DEBUG
242 kprintf("atalkintr: packet too small\n");
247 enet_header
= mtod(m
, enet_header_t
*);
249 /* Ignore multicast packets from local station */
250 /* *** Note: code for IFTYPE_TOKENTALK may be needed here. *** */
251 if (ifID
->aa_ifp
->if_type
== IFT_ETHER
||
252 ifID
->aa_ifp
->if_type
== IFT_L2VLAN
||
253 ifID
->aa_ifp
->if_type
== IFT_IEEE8023ADLAG
) {
254 bcopy((char *)enet_header
->src
, src
, sizeof(src
));
256 #ifdef COMMENT /* In order to receive packets from the Blue Box, we cannot
257 reject packets whose source address matches our local address.
259 if ((enet_header
->dst
[0] & 1) &&
260 (bcmp(src
, ifID
->xaddr
, sizeof(src
)) == 0)) {
261 /* Packet rejected: think it's a local mcast. */
263 return; /* was EAFNOSUPPORT */
267 llc_header
= (llc_header_t
*)(enet_header
+1);
269 /* advance the mbuf pointers past the ethernet header */
270 m
->m_data
+= ENET_LLC_SIZE
;
271 m
->m_len
-= ENET_LLC_SIZE
;
275 if (LLC_PROTO_EQUAL(llc_header
->protocol
,snap_proto_aarp
)) {
276 (void)aarp_rcv_pkt(mtod(m
, aarp_pkt_t
*), ifID
);
279 else if (LLC_PROTO_EQUAL(llc_header
->protocol
, snap_proto_ddp
)) {
280 /* if we're a router take all pkts */
282 if (aarp_chk_addr(mtod(m
, at_ddp_t
*), ifID
)
283 == AARP_ERR_NOT_OURS
) {
284 #ifdef APPLETALK_DEBUG
285 kprintf("pat_input: Packet Rejected: not for us? dest=%x.%x.%x.%x.%x.%x LLC_PROTO= %02x%02x\n",
286 enet_header
->dst
[0], enet_header
->dst
[1],
287 enet_header
->dst
[2], enet_header
->dst
[3],
288 enet_header
->dst
[4], enet_header
->dst
[5],
289 llc_header
->protocol
[3],
290 llc_header
->protocol
[4]);
293 return; /* was EAFNOSUPPORT */
296 MCHTYPE(m
, MSG_DATA
); /* set the mbuf type */
298 ifID
->stats
.rcv_packets
++;
299 for (m1
= m
; m1
; m1
= m1
->m_next
)
300 ifID
->stats
.rcv_bytes
+= m1
->m_len
;
303 ddp_glean(m
, ifID
, (struct etalk_addr
*)src
);
307 #ifdef APPLETALK_DEBUG
308 kprintf("pat_input: Packet Rejected: wrong LLC_PROTO = %02x%02x\n",
309 llc_header
->protocol
[3],
310 llc_header
->protocol
[4]);