]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/drv_dep.c
96fa0d78af468e33a45fb9a2fc00a8bac2567551
[apple/xnu.git] / bsd / netat / drv_dep.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 1994 Apple Computer, Inc.
24 * All Rights Reserved.
25 *
26 * Tuyen A. Nguyen. (December 5, 1994)
27 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
28 */
29
30 #include <sys/errno.h>
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <machine/spl.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/proc.h>
37 #include <sys/filedesc.h>
38 #include <sys/fcntl.h>
39 #include <sys/mbuf.h>
40 #include <sys/ioctl.h>
41 #include <sys/malloc.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/sockio.h>
45
46 #include <net/if.h>
47 #include <net/if_types.h>
48 #include <net/if_dl.h>
49 #include <net/etherdefs.h>
50 #include <net/ethernet.h>
51 #include <net/tokendefs.h>
52
53 #include <netat/sysglue.h>
54 #include <netat/appletalk.h>
55 #include <netat/at_pcb.h>
56 #include <netat/at_var.h>
57 #include <netat/ddp.h>
58 #include <netat/at_aarp.h>
59 #include <netat/at_pat.h>
60 #include <netat/debug.h>
61
62 #define DSAP_SNAP 0xaa
63
64 extern void gref_init(), atp_init(), atp_link(), atp_unlink();
65
66 extern int adspInited;
67
68 static llc_header_t snap_hdr_at = SNAP_HDR_AT;
69 static llc_header_t snap_hdr_aarp = SNAP_HDR_AARP;
70 static unsigned char snap_proto_ddp[5] = SNAP_PROTO_AT;
71 static unsigned char snap_proto_aarp[5] = SNAP_PROTO_AARP;
72
73 int pktsIn, pktsOut;
74
75 struct ifqueue atalkintrq; /* appletalk and aarp packet input queue */
76
77 short appletalk_inited = 0;
78
79 extern atlock_t
80 ddpall_lock, ddpinp_lock, arpinp_lock, refall_lock, nve_lock,
81 aspall_lock, asptmo_lock, atpall_lock, atptmo_lock, atpgen_lock;
82
83 extern int (*sys_ATsocket )(), (*sys_ATgetmsg)(), (*sys_ATputmsg)();
84 extern int (*sys_ATPsndreq)(), (*sys_ATPsndrsp)();
85 extern int (*sys_ATPgetreq)(), (*sys_ATPgetrsp)();
86
87 void atalk_load()
88 {
89 extern int _ATsocket(), _ATgetmsg(), _ATputmsg();
90 extern int _ATPsndreq(), _ATPsndrsp(), _ATPgetreq(), _ATPgetrsp();
91
92 sys_ATsocket = _ATsocket;
93 sys_ATgetmsg = _ATgetmsg;
94 sys_ATputmsg = _ATputmsg;
95 sys_ATPsndreq = _ATPsndreq;
96 sys_ATPsndrsp = _ATPsndrsp;
97 sys_ATPgetreq = _ATPgetreq;
98 sys_ATPgetrsp = _ATPgetrsp;
99
100 ATLOCKINIT(ddpall_lock);
101 ATLOCKINIT(ddpinp_lock);
102 ATLOCKINIT(arpinp_lock);
103 ATLOCKINIT(refall_lock);
104 ATLOCKINIT(aspall_lock);
105 ATLOCKINIT(asptmo_lock);
106 ATLOCKINIT(atpall_lock);
107 ATLOCKINIT(atptmo_lock);
108 ATLOCKINIT(atpgen_lock);
109 ATLOCKINIT(nve_lock);
110
111 atp_init();
112 atp_link();
113 adspInited = 0;
114
115 /* adsp_init();
116 for 2225395
117 this happens in adsp_open and is undone on ADSP_UNLINK
118 */
119 } /* atalk_load */
120
121 /* Undo everything atalk_load() did. */
122 void atalk_unload() /* not currently used */
123 {
124 extern gbuf_t *scb_resource_m;
125 extern gbuf_t *atp_resource_m;
126
127 sys_ATsocket = 0;
128 sys_ATgetmsg = 0;
129 sys_ATputmsg = 0;
130 sys_ATPsndreq = 0;
131 sys_ATPsndrsp = 0;
132 sys_ATPgetreq = 0;
133 sys_ATPgetrsp = 0;
134
135 atp_unlink();
136
137 #ifdef NOT_YET
138 if (scb_resource_m) {
139 gbuf_freem(scb_resource_m);
140 scb_resource_m = 0;
141 scb_free_list = 0;
142 }
143 /* allocated in atp_trans_alloc() */
144 if (atp_resource_m) {
145 gbuf_freem(atp_resource_m);
146 atp_resource_m = 0;
147 atp_trans_free_list = 0;
148 }
149 #endif
150
151 appletalk_inited = 0;
152 } /* atalk_unload */
153
154 void appletalk_hack_start()
155 {
156 if (!appletalk_inited) {
157 atalk_load();
158 atalkintrq.ifq_maxlen = IFQ_MAXLEN;
159 appletalk_inited = 1;
160 }
161 } /* appletalk_hack_start */
162
163 int pat_output(patp, mlist, dst_addr, type)
164 at_ifaddr_t *patp;
165 struct mbuf *mlist; /* packet chain */
166 unsigned char *dst_addr;
167 int type;
168 {
169 struct mbuf *m, *m1;
170 llc_header_t *llc_header;
171 struct sockaddr dst;
172
173 if (! patp->aa_ifp) {
174 for (m = mlist; m; m = mlist) {
175 mlist = m->m_nextpkt;
176 m->m_nextpkt = 0;
177 m_freem(m);
178 }
179 return ENOTREADY;
180 }
181
182 /* this is for ether_output */
183 dst.sa_family = AF_APPLETALK;
184 dst.sa_len = 2 + sizeof(struct etalk_addr);
185 bcopy (dst_addr, &dst.sa_data[0], sizeof(struct etalk_addr));
186
187 /* packet chains are used on output and can be tested using aufs */
188 for (m = mlist; m; m = mlist) {
189 mlist = m->m_nextpkt;
190 m->m_nextpkt = 0;
191
192 M_PREPEND(m, sizeof(llc_header_t), M_DONTWAIT)
193 if (m == 0) {
194 continue;
195 }
196
197 llc_header = mtod(m, llc_header_t *);
198 *llc_header =
199 (type == AARP_AT_TYPE) ? snap_hdr_aarp : snap_hdr_at;
200
201 for (m->m_pkthdr.len = 0, m1 = m; m1; m1 = m1->m_next)
202 m->m_pkthdr.len += m1->m_len;
203 m->m_pkthdr.rcvif = 0;
204
205 /* *** Note: AT is sending out mbufs of type MSG_DATA,
206 not MT_DATA. *** */
207 #ifdef APPLETALK_DEBUG
208 if (m->m_next &&
209 !((m->m_next)->m_flags & M_EXT))
210 kprintf("po: mlen= %d, m2len= %d\n", m->m_len,
211 (m->m_next)->m_len);
212 #endif
213 dlil_output(patp->at_dl_tag, m, NULL, &dst, 0);
214
215 pktsOut++;
216 }
217
218 return 0;
219 } /* pat_output */
220
221 void atalkintr()
222 {
223 struct mbuf *m, *m1, *mlist = NULL;
224 struct ifnet *ifp;
225 int s;
226 llc_header_t *llc_header;
227 at_ifaddr_t *ifID;
228 char src[6];
229 enet_header_t *enet_header;
230
231 next:
232 s = splimp();
233 IF_DEQUEUE(&atalkintrq, m);
234 splx(s);
235
236 if (m == 0)
237 return;
238
239 for ( ; m ; m = mlist) {
240 mlist = m->m_nextpkt;
241 #ifdef APPLETALK_DEBUG
242 /* packet chains are not yet in use on input */
243 if (mlist) kprintf("atalkintr: packet chain\n");
244 #endif
245 m->m_nextpkt = 0;
246
247 if (!appletalk_inited) {
248 m_freem(m);
249 continue;
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 continue;
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 continue; /* 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 continue;
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 bcopy((char *)enet_header->src, src, sizeof(src));
288
289 #ifdef COMMENT /* In order to receive packets from the Blue Box, we cannot
290 reject packets whose source address matches our local address.
291 */
292 if ((enet_header->dst[0] & 1) &&
293 (bcmp(src, ifID->xaddr, sizeof(src)) == 0)) {
294 /* Packet rejected: think it's a local mcast. */
295 m_freem(m);
296 continue; /* was EAFNOSUPPORT */
297 }
298 #endif COMMENT
299
300 llc_header = (llc_header_t *)(enet_header+1);
301
302 /* advance the mbuf pointers past the ethernet header */
303 m->m_data += ENET_LLC_SIZE;
304 m->m_len -= ENET_LLC_SIZE;
305
306 pktsIn++;
307
308 if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_aarp)) {
309 (void)aarp_rcv_pkt(mtod(m, aarp_pkt_t *), ifID);
310 m_freem(m);
311 }
312 else if (LLC_PROTO_EQUAL(llc_header->protocol, snap_proto_ddp)) {
313 /* if we're a router take all pkts */
314 if (!ROUTING_MODE) {
315 if (aarp_chk_addr(mtod(m, at_ddp_t *), ifID)
316 == AARP_ERR_NOT_OURS) {
317 #ifdef APPLETALK_DEBUG
318 kprintf("pat_input: Packet Rejected: not for us? dest=%x.%x.%x.%x.%x.%x LLC_PROTO= %02x%02x\n",
319 enet_header->dst[0], enet_header->dst[1],
320 enet_header->dst[2], enet_header->dst[3],
321 enet_header->dst[4], enet_header->dst[5],
322 llc_header->protocol[3],
323 llc_header->protocol[4]);
324 #endif
325 m_freem(m);
326 continue; /* was EAFNOSUPPORT */
327 }
328 }
329 MCHTYPE(m, MSG_DATA); /* set the mbuf type */
330
331 ifID->stats.rcv_packets++;
332 for (m1 = m; m1; m1 = m1->m_next)
333 ifID->stats.rcv_bytes += m1->m_len;
334
335 if (!MULTIPORT_MODE)
336 ddp_glean(m, ifID, src);
337
338 ddp_input(m, ifID);
339 } else {
340 #ifdef APPLETALK_DEBUG
341 kprintf("pat_input: Packet Rejected: wrong LLC_PROTO = %02x%02x\n",
342 llc_header->protocol[3],
343 llc_header->protocol[4]);
344 #endif
345 m_freem(m);
346 }
347 }
348 }
349 goto next;
350 } /* atalkintr */