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