]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/drv_dep.c
9577b57377fae8fe76e392d3d3313f1af5a3331e
[apple/xnu.git] / bsd / netat / drv_dep.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * Copyright 1994 Apple Computer, Inc.
32 * All Rights Reserved.
33 *
34 * Tuyen A. Nguyen. (December 5, 1994)
35 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
36 */
37
38 #include <sys/errno.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <machine/spl.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/proc.h>
45 #include <sys/filedesc.h>
46 #include <sys/fcntl.h>
47 #include <sys/mbuf.h>
48 #include <sys/ioctl.h>
49 #include <sys/malloc.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/sockio.h>
53
54 #include <net/if.h>
55 #include <net/if_types.h>
56 #include <net/if_dl.h>
57 #include <net/ethernet.h>
58
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/debug.h>
67
68 #define DSAP_SNAP 0xaa
69
70 extern void gref_init(), atp_init(), atp_link(), atp_unlink();
71
72 extern int adspInited;
73
74 static llc_header_t snap_hdr_at = SNAP_HDR_AT;
75 static llc_header_t snap_hdr_aarp = SNAP_HDR_AARP;
76 static unsigned char snap_proto_ddp[5] = SNAP_PROTO_AT;
77 static unsigned char snap_proto_aarp[5] = SNAP_PROTO_AARP;
78
79 static void at_input_packet(protocol_family_t protocol, mbuf_t m);
80
81 int pktsIn, pktsOut;
82
83 struct ifqueue atalkintrq; /* appletalk and aarp packet input queue */
84
85 short appletalk_inited = 0;
86
87
88
89 void atalk_load()
90 {
91 extern lck_mtx_t *domain_proto_mtx;
92
93
94 atp_init();
95 atp_link();
96 adspInited = 0;
97
98 /* adsp_init();
99 for 2225395
100 this happens in adsp_open and is undone on ADSP_UNLINK
101 */
102 lck_mtx_unlock(domain_proto_mtx);
103 proto_register_input(PF_APPLETALK, at_input_packet, NULL);
104 lck_mtx_lock(domain_proto_mtx);
105 } /* atalk_load */
106
107 /* Undo everything atalk_load() did. */
108 void atalk_unload() /* not currently used */
109 {
110 extern gbuf_t *scb_resource_m;
111 extern gbuf_t *atp_resource_m;
112
113 atp_unlink();
114
115 #ifdef NOT_YET
116 if (scb_resource_m) {
117 gbuf_freem(scb_resource_m);
118 scb_resource_m = 0;
119 scb_free_list = 0;
120 }
121 /* allocated in atp_trans_alloc() */
122 if (atp_resource_m) {
123 gbuf_freem(atp_resource_m);
124 atp_resource_m = 0;
125 atp_trans_free_list = 0;
126 }
127 #endif
128
129 appletalk_inited = 0;
130 } /* atalk_unload */
131
132 void appletalk_hack_start()
133 {
134 if (!appletalk_inited) {
135 atalk_load();
136 atalkintrq.ifq_maxlen = IFQ_MAXLEN;
137 appletalk_inited = 1;
138 }
139 } /* appletalk_hack_start */
140
141 int pat_output(patp, mlist, dst_addr, type)
142 at_ifaddr_t *patp;
143 struct mbuf *mlist; /* packet chain */
144 unsigned char *dst_addr; /* for atalk addr - net # must be in network byte order */
145 int type;
146 {
147 struct mbuf *m, *m1;
148 llc_header_t *llc_header;
149 struct sockaddr dst;
150
151 if (! patp->aa_ifp) {
152 for (m = mlist; m; m = mlist) {
153 mlist = m->m_nextpkt;
154 m->m_nextpkt = 0;
155 m_freem(m);
156 }
157 return ENOTREADY;
158 }
159
160 /* this is for ether_output */
161 dst.sa_family = AF_APPLETALK;
162 dst.sa_len = 2 + sizeof(struct etalk_addr);
163 bcopy (dst_addr, &dst.sa_data[0], sizeof(struct etalk_addr));
164
165 /* packet chains are used on output and can be tested using aufs */
166 for (m = mlist; m; m = mlist) {
167 mlist = m->m_nextpkt;
168 m->m_nextpkt = 0;
169
170 M_PREPEND(m, sizeof(llc_header_t), M_DONTWAIT);
171 if (m == 0) {
172 continue;
173 }
174
175 llc_header = mtod(m, llc_header_t *);
176 *llc_header =
177 (type == AARP_AT_TYPE) ? snap_hdr_aarp : snap_hdr_at;
178
179 for (m->m_pkthdr.len = 0, m1 = m; m1; m1 = m1->m_next)
180 m->m_pkthdr.len += m1->m_len;
181 m->m_pkthdr.rcvif = 0;
182
183 /* *** Note: AT is sending out mbufs of type MSG_DATA,
184 not MT_DATA. *** */
185 #ifdef APPLETALK_DEBUG
186 if (m->m_next &&
187 !((m->m_next)->m_flags & M_EXT))
188 kprintf("po: mlen= %d, m2len= %d\n", m->m_len,
189 (m->m_next)->m_len);
190 #endif
191 atalk_unlock();
192 dlil_output(patp->aa_ifp, PF_APPLETALK, m, NULL, &dst, 0);
193 atalk_lock();
194
195 pktsOut++;
196 }
197
198 return 0;
199 } /* pat_output */
200
201 static void
202 at_input_packet(
203 __unused protocol_family_t protocol,
204 mbuf_t m)
205 {
206 struct mbuf *m1;
207 struct ifnet *ifp;
208 llc_header_t *llc_header;
209 at_ifaddr_t *ifID;
210 char src[6];
211 enet_header_t *enet_header;
212
213 if (!appletalk_inited) {
214 m_freem(m);
215 return;
216 }
217
218 if ((m->m_flags & M_PKTHDR) == 0) {
219 #ifdef APPLETALK_DEBUG
220 kprintf("atalkintr: no HDR on packet received");
221 #endif
222 m_freem(m);
223 return;
224 }
225
226 /* make sure the interface this packet was received on is configured
227 for AppleTalk */
228 ifp = m->m_pkthdr.rcvif;
229 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
230 if (ifID->aa_ifp && (ifID->aa_ifp == ifp))
231 break;
232 }
233 /* if we didn't find a matching interface */
234 if (!ifID) {
235 m_freem(m);
236 return; /* was EAFNOSUPPORT */
237 }
238
239 /* make sure the entire packet header is in the current mbuf */
240 if (m->m_len < ENET_LLC_SIZE &&
241 (m = m_pullup(m, ENET_LLC_SIZE)) == 0) {
242 #ifdef APPLETALK_DEBUG
243 kprintf("atalkintr: packet too small\n");
244 #endif
245 m_freem(m);
246 return;
247 }
248 enet_header = mtod(m, enet_header_t *);
249
250 /* Ignore multicast packets from local station */
251 /* *** Note: code for IFTYPE_TOKENTALK may be needed here. *** */
252 if (ifID->aa_ifp->if_type == IFT_ETHER ||
253 ifID->aa_ifp->if_type == IFT_L2VLAN ||
254 ifID->aa_ifp->if_type == IFT_IEEE8023ADLAG) {
255 bcopy((char *)enet_header->src, src, sizeof(src));
256
257 #ifdef COMMENT /* In order to receive packets from the Blue Box, we cannot
258 reject packets whose source address matches our local address.
259 */
260 if ((enet_header->dst[0] & 1) &&
261 (bcmp(src, ifID->xaddr, sizeof(src)) == 0)) {
262 /* Packet rejected: think it's a local mcast. */
263 m_freem(m);
264 return; /* was EAFNOSUPPORT */
265 }
266 #endif /* COMMENT */
267
268 llc_header = (llc_header_t *)(enet_header+1);
269
270 /* advance the mbuf pointers past the ethernet header */
271 m->m_data += ENET_LLC_SIZE;
272 m->m_len -= ENET_LLC_SIZE;
273
274 pktsIn++;
275
276 if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_aarp)) {
277 (void)aarp_rcv_pkt(mtod(m, aarp_pkt_t *), ifID);
278 m_freem(m);
279 }
280 else if (LLC_PROTO_EQUAL(llc_header->protocol, snap_proto_ddp)) {
281 /* if we're a router take all pkts */
282 if (!ROUTING_MODE) {
283 if (aarp_chk_addr(mtod(m, at_ddp_t *), ifID)
284 == AARP_ERR_NOT_OURS) {
285 #ifdef APPLETALK_DEBUG
286 kprintf("pat_input: Packet Rejected: not for us? dest=%x.%x.%x.%x.%x.%x LLC_PROTO= %02x%02x\n",
287 enet_header->dst[0], enet_header->dst[1],
288 enet_header->dst[2], enet_header->dst[3],
289 enet_header->dst[4], enet_header->dst[5],
290 llc_header->protocol[3],
291 llc_header->protocol[4]);
292 #endif
293 m_freem(m);
294 return; /* was EAFNOSUPPORT */
295 }
296 }
297 MCHTYPE(m, MSG_DATA); /* set the mbuf type */
298
299 ifID->stats.rcv_packets++;
300 for (m1 = m; m1; m1 = m1->m_next)
301 ifID->stats.rcv_bytes += m1->m_len;
302
303 if (!MULTIPORT_MODE)
304 ddp_glean(m, ifID, src);
305
306 ddp_input(m, ifID);
307 } else {
308 #ifdef APPLETALK_DEBUG
309 kprintf("pat_input: Packet Rejected: wrong LLC_PROTO = %02x%02x\n",
310 llc_header->protocol[3],
311 llc_header->protocol[4]);
312 #endif
313 m_freem(m);
314 }
315 }
316 }