]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
5d5c5d0d A |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. |
3 | * | |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | /* | |
29 | * Copyright (c) 1995, 1996 | |
30 | * Matt Thomas <matt@3am-software.com>. All rights reserved. | |
31 | * Copyright (c) 1982, 1989, 1993 | |
32 | * The Regents of the University of California. All rights reserved. | |
33 | * | |
34 | * Redistribution and use in source and binary forms, with or without | |
35 | * modification, are permitted provided that the following conditions | |
36 | * are met: | |
37 | * 1. Redistributions of source code must retain the above copyright | |
38 | * notice, this list of conditions and the following disclaimer. | |
39 | * 2. Redistributions in binary form must reproduce the above copyright | |
40 | * notice, this list of conditions and the following disclaimer in the | |
41 | * documentation and/or other materials provided with the distribution. | |
42 | * 3. All advertising materials mentioning features or use of this software | |
43 | * must display the following acknowledgement: | |
44 | * This product includes software developed by the University of | |
45 | * California, Berkeley and its contributors. | |
46 | * 4. Neither the name of the University nor the names of its contributors | |
47 | * may be used to endorse or promote products derived from this software | |
48 | * without specific prior written permission. | |
49 | * | |
50 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
51 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
52 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
53 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
54 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
55 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
56 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
57 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
58 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
59 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
60 | * SUCH DAMAGE. | |
61 | * | |
62 | * from: if_ethersubr.c,v 1.5 1994/12/13 22:31:45 wollman Exp | |
63 | */ | |
64 | ||
65 | #include "opt_atalk.h" | |
66 | #include "opt_inet.h" | |
67 | #include "opt_ipx.h" | |
68 | ||
69 | #include <sys/param.h> | |
70 | #include <sys/systm.h> | |
71 | #include <sys/mbuf.h> | |
72 | #include <sys/socket.h> | |
73 | ||
74 | #include <net/if.h> | |
75 | #include <net/netisr.h> | |
76 | #include <net/route.h> | |
77 | #include <net/if_llc.h> | |
78 | #include <net/if_dl.h> | |
79 | #include <net/if_types.h> | |
80 | ||
81 | #if INET | |
82 | #include <netinet/in.h> | |
83 | #include <netinet/in_var.h> | |
84 | #include <netinet/if_ether.h> | |
85 | #endif | |
86 | #if defined(__FreeBSD__) | |
87 | #include <netinet/if_fddi.h> | |
88 | #else | |
89 | #include <net/if_fddi.h> | |
90 | #endif | |
91 | ||
92 | #if IPX | |
93 | #include <netipx/ipx.h> | |
94 | #include <netipx/ipx_if.h> | |
95 | #endif | |
96 | ||
1c79356b A |
97 | #if DECNET |
98 | #include <netdnet/dn.h> | |
99 | #endif | |
100 | ||
1c79356b A |
101 | #include "bpfilter.h" |
102 | ||
103 | #define senderr(e) { error = (e); goto bad;} | |
104 | ||
105 | /* | |
106 | * This really should be defined in if_llc.h but in case it isn't. | |
107 | */ | |
108 | #ifndef llc_snap | |
109 | #define llc_snap llc_un.type_snap | |
110 | #endif | |
111 | ||
112 | #if defined(__bsdi__) || defined(__NetBSD__) | |
113 | #define RTALLOC1(a, b) rtalloc1(a, b) | |
114 | #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e) | |
115 | #elif defined(__FreeBSD__) | |
116 | #define RTALLOC1(a, b) rtalloc1(a, b, 0UL) | |
117 | #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e, f) | |
118 | #endif | |
119 | /* | |
120 | * FDDI output routine. | |
121 | * Encapsulate a packet of type family for the local net. | |
122 | * Use trailer local net encapsulation if enough data in first | |
123 | * packet leaves a multiple of 512 bytes of data in remainder. | |
124 | * Assumes that ifp is actually pointer to arpcom structure. | |
125 | */ | |
126 | int | |
127 | fddi_output(ifp, m0, dst, rt0) | |
128 | register struct ifnet *ifp; | |
129 | struct mbuf *m0; | |
130 | struct sockaddr *dst; | |
131 | struct rtentry *rt0; | |
132 | { | |
133 | u_int16_t type; | |
134 | int s, loop_copy = 0, error = 0; | |
135 | u_char edst[6]; | |
136 | register struct mbuf *m = m0; | |
137 | register struct rtentry *rt; | |
138 | register struct fddi_header *fh; | |
139 | struct arpcom *ac = (struct arpcom *)ifp; | |
140 | ||
141 | if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) | |
142 | senderr(ENETDOWN); | |
143 | getmicrotime(&ifp->if_lastchange); | |
144 | #if !defined(__bsdi__) || _BSDI_VERSION >= 199401 | |
145 | if (rt = rt0) { | |
146 | if ((rt->rt_flags & RTF_UP) == 0) { | |
147 | if (rt0 = rt = RTALLOC1(dst, 1)) | |
9bccf70c | 148 | rtunref(rt); |
1c79356b A |
149 | else |
150 | senderr(EHOSTUNREACH); | |
151 | } | |
152 | if (rt->rt_flags & RTF_GATEWAY) { | |
153 | if (rt->rt_gwroute == 0) | |
154 | goto lookup; | |
155 | if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { | |
156 | rtfree(rt); rt = rt0; | |
157 | lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1); | |
158 | if ((rt = rt->rt_gwroute) == 0) | |
159 | senderr(EHOSTUNREACH); | |
160 | } | |
161 | } | |
162 | if (rt->rt_flags & RTF_REJECT) | |
163 | if (rt->rt_rmx.rmx_expire == 0 || | |
164 | time_second < rt->rt_rmx.rmx_expire) | |
165 | senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); | |
166 | } | |
167 | #endif | |
168 | switch (dst->sa_family) { | |
169 | ||
170 | #if INET | |
171 | case AF_INET: { | |
172 | #if !defined(__bsdi__) || _BSDI_VERSION >= 199401 | |
173 | if (!ARPRESOLVE(ac, rt, m, dst, edst, rt0)) | |
174 | return (0); /* if not yet resolved */ | |
175 | #else | |
176 | int usetrailers; | |
177 | if (!arpresolve(ac, m, &((struct sockaddr_in *)dst)->sin_addr, edst, &usetrailers)) | |
178 | return (0); /* if not yet resolved */ | |
179 | #endif | |
180 | type = htons(ETHERTYPE_IP); | |
181 | break; | |
182 | } | |
183 | #endif | |
184 | #if IPX | |
185 | case AF_IPX: | |
186 | type = htons(ETHERTYPE_IPX); | |
187 | bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), | |
188 | (caddr_t)edst, sizeof (edst)); | |
189 | break; | |
190 | #endif | |
191 | ||
192 | #if NS | |
193 | case AF_NS: | |
194 | type = htons(ETHERTYPE_NS); | |
195 | bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), | |
196 | (caddr_t)edst, sizeof (edst)); | |
197 | break; | |
198 | #endif | |
199 | #if ISO | |
200 | case AF_ISO: { | |
201 | int snpalen; | |
202 | struct llc *l; | |
203 | register struct sockaddr_dl *sdl; | |
204 | ||
205 | if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) && | |
206 | sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) { | |
207 | bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst)); | |
208 | } else if (error = | |
209 | iso_snparesolve(ifp, (struct sockaddr_iso *)dst, | |
210 | (char *)edst, &snpalen)) | |
211 | goto bad; /* Not Resolved */ | |
212 | /* If broadcasting on a simplex interface, loopback a copy */ | |
213 | if (*edst & 1) | |
214 | m->m_flags |= (M_BCAST|M_MCAST); | |
215 | M_PREPEND(m, 3, M_DONTWAIT); | |
216 | if (m == NULL) | |
217 | return (0); | |
218 | type = 0; | |
219 | l = mtod(m, struct llc *); | |
220 | l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP; | |
221 | l->llc_control = LLC_UI; | |
222 | IFDEBUG(D_ETHER) | |
223 | int i; | |
224 | printf("unoutput: sending pkt to: "); | |
225 | for (i=0; i<6; i++) | |
226 | printf("%x ", edst[i] & 0xff); | |
227 | printf("\n"); | |
228 | ENDDEBUG | |
229 | } break; | |
230 | #endif /* ISO */ | |
231 | #if LLC | |
232 | /* case AF_NSAP: */ | |
233 | case AF_CCITT: { | |
234 | register struct sockaddr_dl *sdl = | |
235 | (struct sockaddr_dl *) rt -> rt_gateway; | |
236 | ||
237 | if (sdl && sdl->sdl_family != AF_LINK && sdl->sdl_alen <= 0) | |
238 | goto bad; /* Not a link interface ? Funny ... */ | |
239 | bcopy(LLADDR(sdl), (char *)edst, sizeof(edst)); | |
240 | if (*edst & 1) | |
241 | loop_copy = 1; | |
242 | type = 0; | |
243 | #if LLC_DEBUG | |
244 | { | |
245 | int i; | |
246 | register struct llc *l = mtod(m, struct llc *); | |
247 | ||
248 | printf("fddi_output: sending LLC2 pkt to: "); | |
249 | for (i=0; i<6; i++) | |
250 | printf("%x ", edst[i] & 0xff); | |
251 | printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n", | |
252 | type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff, | |
253 | l->llc_control & 0xff); | |
254 | ||
255 | } | |
256 | #endif /* LLC_DEBUG */ | |
257 | } break; | |
258 | #endif /* LLC */ | |
259 | ||
260 | case AF_UNSPEC: | |
261 | { | |
262 | struct ether_header *eh; | |
263 | loop_copy = -1; | |
264 | eh = (struct ether_header *)dst->sa_data; | |
265 | (void)memcpy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); | |
266 | if (*edst & 1) | |
267 | m->m_flags |= (M_BCAST|M_MCAST); | |
268 | type = eh->ether_type; | |
269 | break; | |
270 | } | |
271 | ||
272 | #if NBPFILTER > 0 | |
273 | case AF_IMPLINK: | |
274 | { | |
275 | fh = mtod(m, struct fddi_header *); | |
276 | error = EPROTONOSUPPORT; | |
277 | switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) { | |
278 | case FDDIFC_LLC_ASYNC: { | |
279 | /* legal priorities are 0 through 7 */ | |
280 | if ((fh->fddi_fc & FDDIFC_Z) > 7) | |
281 | goto bad; | |
282 | break; | |
283 | } | |
284 | case FDDIFC_LLC_SYNC: { | |
285 | /* FDDIFC_Z bits reserved, must be zero */ | |
286 | if (fh->fddi_fc & FDDIFC_Z) | |
287 | goto bad; | |
288 | break; | |
289 | } | |
290 | case FDDIFC_SMT: { | |
291 | /* FDDIFC_Z bits must be non zero */ | |
292 | if ((fh->fddi_fc & FDDIFC_Z) == 0) | |
293 | goto bad; | |
294 | break; | |
295 | } | |
296 | default: { | |
297 | /* anything else is too dangerous */ | |
298 | goto bad; | |
299 | } | |
300 | } | |
301 | error = 0; | |
302 | if (fh->fddi_dhost[0] & 1) | |
303 | m->m_flags |= (M_BCAST|M_MCAST); | |
304 | goto queue_it; | |
305 | } | |
306 | #endif | |
307 | default: | |
308 | printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, | |
309 | dst->sa_family); | |
310 | senderr(EAFNOSUPPORT); | |
311 | } | |
312 | ||
313 | if (type != 0) { | |
314 | register struct llc *l; | |
315 | M_PREPEND(m, sizeof (struct llc), M_DONTWAIT); | |
316 | if (m == 0) | |
317 | senderr(ENOBUFS); | |
318 | l = mtod(m, struct llc *); | |
319 | l->llc_control = LLC_UI; | |
320 | l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP; | |
321 | l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0; | |
322 | (void)memcpy((caddr_t) &l->llc_snap.ether_type, (caddr_t) &type, | |
323 | sizeof(u_int16_t)); | |
324 | } | |
325 | ||
326 | /* | |
327 | * Add local net header. If no space in first mbuf, | |
328 | * allocate another. | |
329 | */ | |
330 | M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT); | |
331 | if (m == 0) | |
332 | senderr(ENOBUFS); | |
333 | fh = mtod(m, struct fddi_header *); | |
334 | fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; | |
335 | (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst)); | |
336 | queue_it: | |
337 | (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr, | |
338 | sizeof(fh->fddi_shost)); | |
339 | ||
340 | /* | |
341 | * If a simplex interface, and the packet is being sent to our | |
342 | * Ethernet address or a broadcast address, loopback a copy. | |
343 | * XXX To make a simplex device behave exactly like a duplex | |
344 | * device, we should copy in the case of sending to our own | |
345 | * ethernet address (thus letting the original actually appear | |
346 | * on the wire). However, we don't do that here for security | |
347 | * reasons and compatibility with the original behavior. | |
348 | */ | |
349 | if ((ifp->if_flags & IFF_SIMPLEX) && | |
350 | (loop_copy != -1)) { | |
351 | if ((m->m_flags & M_BCAST) || loop_copy) { | |
352 | struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); | |
353 | ||
354 | (void) if_simloop(ifp, | |
355 | n, dst, sizeof(struct fddi_header)); | |
356 | } else if (bcmp(fh->fddi_dhost, | |
357 | fh->fddi_shost, sizeof(fh->fddi_shost)) == 0) { | |
358 | (void) if_simloop(ifp, | |
359 | m, dst, sizeof(struct fddi_header)); | |
360 | return(0); /* XXX */ | |
361 | } | |
362 | } | |
363 | ||
364 | s = splimp(); | |
365 | /* | |
366 | * Queue message on interface, and start output if interface | |
367 | * not yet active. | |
368 | */ | |
369 | if (IF_QFULL(&ifp->if_snd)) { | |
370 | IF_DROP(&ifp->if_snd); | |
371 | splx(s); | |
372 | senderr(ENOBUFS); | |
373 | } | |
374 | ifp->if_obytes += m->m_pkthdr.len; | |
375 | IF_ENQUEUE(&ifp->if_snd, m); | |
376 | if ((ifp->if_flags & IFF_OACTIVE) == 0) | |
377 | (*ifp->if_start)(ifp); | |
378 | splx(s); | |
379 | if (m->m_flags & M_MCAST) | |
380 | ifp->if_omcasts++; | |
381 | return (error); | |
382 | ||
383 | bad: | |
384 | if (m) | |
385 | m_freem(m); | |
386 | return (error); | |
387 | } | |
388 | ||
389 | /* | |
390 | * Process a received FDDI packet; | |
391 | * the packet is in the mbuf chain m without | |
392 | * the fddi header, which is provided separately. | |
393 | */ | |
394 | void | |
395 | fddi_input(ifp, fh, m) | |
396 | struct ifnet *ifp; | |
397 | register struct fddi_header *fh; | |
398 | struct mbuf *m; | |
399 | { | |
400 | register struct ifqueue *inq; | |
401 | register struct llc *l; | |
402 | int s; | |
403 | ||
404 | if ((ifp->if_flags & IFF_UP) == 0) { | |
405 | m_freem(m); | |
406 | return; | |
407 | } | |
408 | getmicrotime(&ifp->if_lastchange); | |
409 | ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh); | |
410 | if (fh->fddi_dhost[0] & 1) { | |
411 | if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost, | |
412 | sizeof(fddibroadcastaddr)) == 0) | |
413 | m->m_flags |= M_BCAST; | |
414 | else | |
415 | m->m_flags |= M_MCAST; | |
416 | ifp->if_imcasts++; | |
417 | } else if ((ifp->if_flags & IFF_PROMISC) | |
418 | && bcmp(((struct arpcom *)ifp)->ac_enaddr, (caddr_t)fh->fddi_dhost, | |
419 | sizeof(fh->fddi_dhost)) != 0) { | |
420 | m_freem(m); | |
421 | return; | |
422 | } | |
423 | ||
424 | #ifdef M_LINK0 | |
425 | /* | |
426 | * If this has a LLC priority of 0, then mark it so upper | |
427 | * layers have a hint that it really came via a FDDI/Ethernet | |
428 | * bridge. | |
429 | */ | |
430 | if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0) | |
431 | m->m_flags |= M_LINK0; | |
432 | #endif | |
433 | ||
434 | l = mtod(m, struct llc *); | |
435 | switch (l->llc_dsap) { | |
436 | #if defined(INET) || NS || IPX || defined(NETATALK) | |
437 | case LLC_SNAP_LSAP: | |
438 | { | |
439 | u_int16_t type; | |
440 | if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP) | |
441 | goto dropanyway; | |
442 | ||
443 | if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0) | |
444 | goto dropanyway; | |
445 | type = ntohs(l->llc_snap.ether_type); | |
446 | m_adj(m, 8); | |
447 | switch (type) { | |
448 | #if INET | |
449 | case ETHERTYPE_IP: | |
450 | if (ipflow_fastforward(m)) | |
451 | return; | |
452 | schednetisr(NETISR_IP); | |
453 | inq = &ipintrq; | |
454 | break; | |
455 | ||
456 | case ETHERTYPE_ARP: | |
457 | #if !defined(__bsdi__) || _BSDI_VERSION >= 199401 | |
458 | schednetisr(NETISR_ARP); | |
459 | inq = &arpintrq; | |
460 | break; | |
461 | #else | |
462 | arpinput((struct arpcom *)ifp, m); | |
463 | return; | |
464 | #endif | |
465 | #endif | |
466 | #if IPX | |
467 | case ETHERTYPE_IPX: | |
468 | schednetisr(NETISR_IPX); | |
469 | inq = &ipxintrq; | |
470 | break; | |
471 | #endif | |
472 | #if NS | |
473 | case ETHERTYPE_NS: | |
474 | schednetisr(NETISR_NS); | |
475 | inq = &nsintrq; | |
476 | break; | |
477 | #endif | |
478 | #if DECNET | |
479 | case ETHERTYPE_DECNET: | |
480 | schednetisr(NETISR_DECNET); | |
481 | inq = &decnetintrq; | |
482 | break; | |
483 | #endif | |
484 | ||
485 | default: | |
486 | /* printf("fddi_input: unknown protocol 0x%x\n", type); */ | |
487 | ifp->if_noproto++; | |
488 | goto dropanyway; | |
489 | } | |
490 | break; | |
491 | } | |
492 | #endif /* INET || NS */ | |
493 | #if ISO | |
494 | case LLC_ISO_LSAP: | |
495 | switch (l->llc_control) { | |
496 | case LLC_UI: | |
497 | /* LLC_UI_P forbidden in class 1 service */ | |
498 | if ((l->llc_dsap == LLC_ISO_LSAP) && | |
499 | (l->llc_ssap == LLC_ISO_LSAP)) { | |
500 | /* LSAP for ISO */ | |
501 | m->m_data += 3; /* XXX */ | |
502 | m->m_len -= 3; /* XXX */ | |
503 | m->m_pkthdr.len -= 3; /* XXX */ | |
504 | M_PREPEND(m, sizeof *fh, M_DONTWAIT); | |
505 | if (m == 0) | |
506 | return; | |
507 | *mtod(m, struct fddi_header *) = *fh; | |
508 | IFDEBUG(D_ETHER) | |
509 | printf("clnp packet"); | |
510 | ENDDEBUG | |
511 | schednetisr(NETISR_ISO); | |
512 | inq = &clnlintrq; | |
513 | break; | |
514 | } | |
515 | goto dropanyway; | |
516 | ||
517 | case LLC_XID: | |
518 | case LLC_XID_P: | |
519 | if(m->m_len < 6) | |
520 | goto dropanyway; | |
521 | l->llc_window = 0; | |
522 | l->llc_fid = 9; | |
523 | l->llc_class = 1; | |
524 | l->llc_dsap = l->llc_ssap = 0; | |
525 | /* Fall through to */ | |
526 | case LLC_TEST: | |
527 | case LLC_TEST_P: | |
528 | { | |
529 | struct sockaddr sa; | |
530 | register struct ether_header *eh; | |
531 | struct arpcom *ac = (struct arpcom *) ifp; | |
532 | int i; | |
533 | u_char c = l->llc_dsap; | |
534 | ||
535 | l->llc_dsap = l->llc_ssap; | |
536 | l->llc_ssap = c; | |
537 | if (m->m_flags & (M_BCAST | M_MCAST)) | |
538 | bcopy((caddr_t)ac->ac_enaddr, | |
539 | (caddr_t)eh->ether_dhost, 6); | |
540 | sa.sa_family = AF_UNSPEC; | |
541 | sa.sa_len = sizeof(sa); | |
542 | eh = (struct ether_header *)sa.sa_data; | |
543 | for (i = 0; i < 6; i++) { | |
544 | eh->ether_shost[i] = fh->fddi_dhost[i]; | |
545 | eh->ether_dhost[i] = fh->fddi_shost[i]; | |
546 | } | |
547 | eh->ether_type = 0; | |
548 | ifp->if_output(ifp, m, &sa, NULL); | |
549 | return; | |
550 | } | |
551 | default: | |
552 | m_freem(m); | |
553 | return; | |
554 | } | |
555 | break; | |
556 | #endif /* ISO */ | |
557 | #if LLC | |
558 | case LLC_X25_LSAP: | |
559 | { | |
560 | M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT); | |
561 | if (m == 0) | |
562 | return; | |
563 | if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP, | |
564 | fh->fddi_dhost, LLC_X25_LSAP, 6, | |
565 | mtod(m, struct sdl_hdr *))) | |
566 | panic("ETHER cons addr failure"); | |
567 | mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr); | |
568 | #if LLC_DEBUG | |
569 | printf("llc packet\n"); | |
570 | #endif /* LLC_DEBUG */ | |
571 | schednetisr(NETISR_CCITT); | |
572 | inq = &llcintrq; | |
573 | break; | |
574 | } | |
575 | #endif /* LLC */ | |
576 | ||
577 | default: | |
578 | /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */ | |
579 | ifp->if_noproto++; | |
580 | dropanyway: | |
581 | m_freem(m); | |
582 | return; | |
583 | } | |
584 | ||
585 | s = splimp(); | |
586 | if (IF_QFULL(inq)) { | |
587 | IF_DROP(inq); | |
588 | m_freem(m); | |
589 | } else | |
590 | IF_ENQUEUE(inq, m); | |
591 | splx(s); | |
592 | } | |
593 | /* | |
594 | * Perform common duties while attaching to interface list | |
595 | */ | |
596 | #ifdef __NetBSD__ | |
597 | #define ifa_next ifa_list.tqe_next | |
598 | #endif | |
599 | ||
600 | void | |
601 | fddi_ifattach(ifp) | |
602 | register struct ifnet *ifp; | |
603 | { | |
604 | register struct ifaddr *ifa; | |
605 | register struct sockaddr_dl *sdl; | |
606 | ||
607 | ifp->if_type = IFT_FDDI; | |
608 | ifp->if_addrlen = 6; | |
609 | ifp->if_hdrlen = 21; | |
610 | ifp->if_mtu = FDDIMTU; | |
611 | ifp->if_baudrate = 100000000; | |
612 | #if IFF_NOTRAILERS | |
613 | ifp->if_flags |= IFF_NOTRAILERS; | |
614 | #endif | |
615 | #if defined(__FreeBSD__) | |
616 | ifa = ifnet_addrs[ifp->if_index - 1]; | |
617 | sdl = (struct sockaddr_dl *)ifa->ifa_addr; | |
618 | sdl->sdl_type = IFT_FDDI; | |
619 | sdl->sdl_alen = ifp->if_addrlen; | |
620 | bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); | |
621 | #elif defined(__NetBSD__) | |
622 | LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs); | |
623 | for (ifa = ifp->if_addrlist.tqh_first; ifa != NULL; ifa = ifa->ifa_list.tqe_next) | |
624 | #else | |
625 | for (ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next) | |
626 | #endif | |
627 | #if !defined(__FreeBSD__) | |
628 | if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && | |
629 | sdl->sdl_family == AF_LINK) { | |
630 | sdl->sdl_type = IFT_FDDI; | |
631 | sdl->sdl_alen = ifp->if_addrlen; | |
632 | bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, | |
633 | LLADDR(sdl), ifp->if_addrlen); | |
634 | break; | |
635 | } | |
636 | #endif | |
637 | } |