]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/drv_dep.c
acaf3da2aa5ead943a84d1c9119e42cd12078b50
[apple/xnu.git] / bsd / netat / drv_dep.c
1 /*
2 * Copyright (c) 2006 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 extern atlock_t
88 ddpall_lock, ddpinp_lock, arpinp_lock, refall_lock, nve_lock,
89 aspall_lock, asptmo_lock, atpall_lock, atptmo_lock, atpgen_lock;
90
91 extern int (*sys_ATsocket )(), (*sys_ATgetmsg)(), (*sys_ATputmsg)();
92 extern int (*sys_ATPsndreq)(), (*sys_ATPsndrsp)();
93 extern int (*sys_ATPgetreq)(), (*sys_ATPgetrsp)();
94
95 void atalk_load()
96 {
97 extern int _ATsocket(), _ATgetmsg(), _ATputmsg();
98 extern int _ATPsndreq(), _ATPsndrsp(), _ATPgetreq(), _ATPgetrsp();
99 extern lck_mtx_t *domain_proto_mtx;
100
101 sys_ATsocket = _ATsocket;
102 sys_ATgetmsg = _ATgetmsg;
103 sys_ATputmsg = _ATputmsg;
104 sys_ATPsndreq = _ATPsndreq;
105 sys_ATPsndrsp = _ATPsndrsp;
106 sys_ATPgetreq = _ATPgetreq;
107 sys_ATPgetrsp = _ATPgetrsp;
108
109 ATLOCKINIT(ddpall_lock);
110 ATLOCKINIT(ddpinp_lock);
111 ATLOCKINIT(arpinp_lock);
112 ATLOCKINIT(refall_lock);
113 ATLOCKINIT(aspall_lock);
114 ATLOCKINIT(asptmo_lock);
115 ATLOCKINIT(atpall_lock);
116 ATLOCKINIT(atptmo_lock);
117 ATLOCKINIT(atpgen_lock);
118 ATLOCKINIT(nve_lock);
119
120 atp_init();
121 atp_link();
122 adspInited = 0;
123
124 /* adsp_init();
125 for 2225395
126 this happens in adsp_open and is undone on ADSP_UNLINK
127 */
128 lck_mtx_unlock(domain_proto_mtx);
129 proto_register_input(PF_APPLETALK, at_input_packet, NULL);
130 lck_mtx_lock(domain_proto_mtx);
131 } /* atalk_load */
132
133 /* Undo everything atalk_load() did. */
134 void atalk_unload() /* not currently used */
135 {
136 extern gbuf_t *scb_resource_m;
137 extern gbuf_t *atp_resource_m;
138
139 sys_ATsocket = 0;
140 sys_ATgetmsg = 0;
141 sys_ATputmsg = 0;
142 sys_ATPsndreq = 0;
143 sys_ATPsndrsp = 0;
144 sys_ATPgetreq = 0;
145 sys_ATPgetrsp = 0;
146
147 atp_unlink();
148
149 #ifdef NOT_YET
150 if (scb_resource_m) {
151 gbuf_freem(scb_resource_m);
152 scb_resource_m = 0;
153 scb_free_list = 0;
154 }
155 /* allocated in atp_trans_alloc() */
156 if (atp_resource_m) {
157 gbuf_freem(atp_resource_m);
158 atp_resource_m = 0;
159 atp_trans_free_list = 0;
160 }
161 #endif
162
163 appletalk_inited = 0;
164 } /* atalk_unload */
165
166 void appletalk_hack_start()
167 {
168 if (!appletalk_inited) {
169 atalk_load();
170 atalkintrq.ifq_maxlen = IFQ_MAXLEN;
171 appletalk_inited = 1;
172 }
173 } /* appletalk_hack_start */
174
175 int pat_output(patp, mlist, dst_addr, type)
176 at_ifaddr_t *patp;
177 struct mbuf *mlist; /* packet chain */
178 unsigned char *dst_addr;
179 int type;
180 {
181 struct mbuf *m, *m1;
182 llc_header_t *llc_header;
183 struct sockaddr dst;
184
185 if (! patp->aa_ifp) {
186 for (m = mlist; m; m = mlist) {
187 mlist = m->m_nextpkt;
188 m->m_nextpkt = 0;
189 m_freem(m);
190 }
191 return ENOTREADY;
192 }
193
194 /* this is for ether_output */
195 dst.sa_family = AF_APPLETALK;
196 dst.sa_len = 2 + sizeof(struct etalk_addr);
197 bcopy (dst_addr, &dst.sa_data[0], sizeof(struct etalk_addr));
198
199 /* packet chains are used on output and can be tested using aufs */
200 for (m = mlist; m; m = mlist) {
201 mlist = m->m_nextpkt;
202 m->m_nextpkt = 0;
203
204 M_PREPEND(m, sizeof(llc_header_t), M_DONTWAIT);
205 if (m == 0) {
206 continue;
207 }
208
209 llc_header = mtod(m, llc_header_t *);
210 *llc_header =
211 (type == AARP_AT_TYPE) ? snap_hdr_aarp : snap_hdr_at;
212
213 for (m->m_pkthdr.len = 0, m1 = m; m1; m1 = m1->m_next)
214 m->m_pkthdr.len += m1->m_len;
215 m->m_pkthdr.rcvif = 0;
216
217 /* *** Note: AT is sending out mbufs of type MSG_DATA,
218 not MT_DATA. *** */
219 #ifdef APPLETALK_DEBUG
220 if (m->m_next &&
221 !((m->m_next)->m_flags & M_EXT))
222 kprintf("po: mlen= %d, m2len= %d\n", m->m_len,
223 (m->m_next)->m_len);
224 #endif
225 atalk_unlock();
226 dlil_output(patp->aa_ifp, PF_APPLETALK, m, NULL, &dst, 0);
227 atalk_lock();
228
229 pktsOut++;
230 }
231
232 return 0;
233 } /* pat_output */
234
235 static void
236 at_input_packet(
237 __unused protocol_family_t protocol,
238 mbuf_t m)
239 {
240 struct mbuf *m1;
241 struct ifnet *ifp;
242 llc_header_t *llc_header;
243 at_ifaddr_t *ifID;
244 char src[6];
245 enet_header_t *enet_header;
246
247 if (!appletalk_inited) {
248 m_freem(m);
249 return;
250 }
251
252 if ((m->m_flags & M_PKTHDR) == 0) {
253 #ifdef APPLETALK_DEBUG
254 kprintf("atalkintr: no HDR on packet received");
255 #endif
256 m_freem(m);
257 return;
258 }
259
260 /* make sure the interface this packet was received on is configured
261 for AppleTalk */
262 ifp = m->m_pkthdr.rcvif;
263 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
264 if (ifID->aa_ifp && (ifID->aa_ifp == ifp))
265 break;
266 }
267 /* if we didn't find a matching interface */
268 if (!ifID) {
269 m_freem(m);
270 return; /* was EAFNOSUPPORT */
271 }
272
273 /* make sure the entire packet header is in the current mbuf */
274 if (m->m_len < ENET_LLC_SIZE &&
275 (m = m_pullup(m, ENET_LLC_SIZE)) == 0) {
276 #ifdef APPLETALK_DEBUG
277 kprintf("atalkintr: packet too small\n");
278 #endif
279 m_freem(m);
280 return;
281 }
282 enet_header = mtod(m, enet_header_t *);
283
284 /* Ignore multicast packets from local station */
285 /* *** Note: code for IFTYPE_TOKENTALK may be needed here. *** */
286 if (ifID->aa_ifp->if_type == IFT_ETHER ||
287 ifID->aa_ifp->if_type == IFT_L2VLAN ||
288 ifID->aa_ifp->if_type == IFT_IEEE8023ADLAG) {
289 bcopy((char *)enet_header->src, src, sizeof(src));
290
291 #ifdef COMMENT /* In order to receive packets from the Blue Box, we cannot
292 reject packets whose source address matches our local address.
293 */
294 if ((enet_header->dst[0] & 1) &&
295 (bcmp(src, ifID->xaddr, sizeof(src)) == 0)) {
296 /* Packet rejected: think it's a local mcast. */
297 m_freem(m);
298 return; /* was EAFNOSUPPORT */
299 }
300 #endif /* COMMENT */
301
302 llc_header = (llc_header_t *)(enet_header+1);
303
304 /* advance the mbuf pointers past the ethernet header */
305 m->m_data += ENET_LLC_SIZE;
306 m->m_len -= ENET_LLC_SIZE;
307
308 pktsIn++;
309
310 if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_aarp)) {
311 (void)aarp_rcv_pkt(mtod(m, aarp_pkt_t *), ifID);
312 m_freem(m);
313 }
314 else if (LLC_PROTO_EQUAL(llc_header->protocol, snap_proto_ddp)) {
315 /* if we're a router take all pkts */
316 if (!ROUTING_MODE) {
317 if (aarp_chk_addr(mtod(m, at_ddp_t *), ifID)
318 == AARP_ERR_NOT_OURS) {
319 #ifdef APPLETALK_DEBUG
320 kprintf("pat_input: Packet Rejected: not for us? dest=%x.%x.%x.%x.%x.%x LLC_PROTO= %02x%02x\n",
321 enet_header->dst[0], enet_header->dst[1],
322 enet_header->dst[2], enet_header->dst[3],
323 enet_header->dst[4], enet_header->dst[5],
324 llc_header->protocol[3],
325 llc_header->protocol[4]);
326 #endif
327 m_freem(m);
328 return; /* was EAFNOSUPPORT */
329 }
330 }
331 MCHTYPE(m, MSG_DATA); /* set the mbuf type */
332
333 ifID->stats.rcv_packets++;
334 for (m1 = m; m1; m1 = m1->m_next)
335 ifID->stats.rcv_bytes += m1->m_len;
336
337 if (!MULTIPORT_MODE)
338 ddp_glean(m, ifID, src);
339
340 ddp_input(m, ifID);
341 } else {
342 #ifdef APPLETALK_DEBUG
343 kprintf("pat_input: Packet Rejected: wrong LLC_PROTO = %02x%02x\n",
344 llc_header->protocol[3],
345 llc_header->protocol[4]);
346 #endif
347 m_freem(m);
348 }
349 }
350 }