|
|
1.1 root 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 <[email protected]>. 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:
91: #if NS
92: #include <netns/ns.h>
93: #include <netns/ns_if.h>
94: #endif
95:
96: #if DECNET
97: #include <netdnet/dn.h>
98: #endif
99:
100: #if ISO
101: #include <netiso/argo_debug.h>
102: #include <netiso/iso.h>
103: #include <netiso/iso_var.h>
104: #include <netiso/iso_snpac.h>
105: #endif
106:
107: #if LLC
108: #include <netccitt/dll.h>
109: #include <netccitt/llc_var.h>
110: #endif
111:
112:
113: #if LLC && CCITT
114: extern struct ifqueue pkintrq;
115: #endif
116:
117: #include "bpfilter.h"
118:
119: #define senderr(e) { error = (e); goto bad;}
120:
121: /*
122: * This really should be defined in if_llc.h but in case it isn't.
123: */
124: #ifndef llc_snap
125: #define llc_snap llc_un.type_snap
126: #endif
127:
128: #if defined(__bsdi__) || defined(__NetBSD__)
129: #define RTALLOC1(a, b) rtalloc1(a, b)
130: #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e)
131: #elif defined(__FreeBSD__)
132: #define RTALLOC1(a, b) rtalloc1(a, b, 0UL)
133: #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e, f)
134: #endif
135: /*
136: * FDDI output routine.
137: * Encapsulate a packet of type family for the local net.
138: * Use trailer local net encapsulation if enough data in first
139: * packet leaves a multiple of 512 bytes of data in remainder.
140: * Assumes that ifp is actually pointer to arpcom structure.
141: */
142: int
143: fddi_output(ifp, m0, dst, rt0)
144: register struct ifnet *ifp;
145: struct mbuf *m0;
146: struct sockaddr *dst;
147: struct rtentry *rt0;
148: {
149: u_int16_t type;
150: int s, loop_copy = 0, error = 0;
151: u_char edst[6];
152: register struct mbuf *m = m0;
153: register struct rtentry *rt;
154: register struct fddi_header *fh;
155: struct arpcom *ac = (struct arpcom *)ifp;
156:
157: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
158: senderr(ENETDOWN);
159: getmicrotime(&ifp->if_lastchange);
160: #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
161: if (rt = rt0) {
162: if ((rt->rt_flags & RTF_UP) == 0) {
163: if (rt0 = rt = RTALLOC1(dst, 1))
164: rt->rt_refcnt--;
165: else
166: senderr(EHOSTUNREACH);
167: }
168: if (rt->rt_flags & RTF_GATEWAY) {
169: if (rt->rt_gwroute == 0)
170: goto lookup;
171: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
172: rtfree(rt); rt = rt0;
173: lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 1);
174: if ((rt = rt->rt_gwroute) == 0)
175: senderr(EHOSTUNREACH);
176: }
177: }
178: if (rt->rt_flags & RTF_REJECT)
179: if (rt->rt_rmx.rmx_expire == 0 ||
180: time_second < rt->rt_rmx.rmx_expire)
181: senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
182: }
183: #endif
184: switch (dst->sa_family) {
185:
186: #if INET
187: case AF_INET: {
188: #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
189: if (!ARPRESOLVE(ac, rt, m, dst, edst, rt0))
190: return (0); /* if not yet resolved */
191: #else
192: int usetrailers;
193: if (!arpresolve(ac, m, &((struct sockaddr_in *)dst)->sin_addr, edst, &usetrailers))
194: return (0); /* if not yet resolved */
195: #endif
196: type = htons(ETHERTYPE_IP);
197: break;
198: }
199: #endif
200: #if IPX
201: case AF_IPX:
202: type = htons(ETHERTYPE_IPX);
203: bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
204: (caddr_t)edst, sizeof (edst));
205: break;
206: #endif
207:
208: #if NS
209: case AF_NS:
210: type = htons(ETHERTYPE_NS);
211: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
212: (caddr_t)edst, sizeof (edst));
213: break;
214: #endif
215: #if ISO
216: case AF_ISO: {
217: int snpalen;
218: struct llc *l;
219: register struct sockaddr_dl *sdl;
220:
221: if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
222: sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
223: bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
224: } else if (error =
225: iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
226: (char *)edst, &snpalen))
227: goto bad; /* Not Resolved */
228: /* If broadcasting on a simplex interface, loopback a copy */
229: if (*edst & 1)
230: m->m_flags |= (M_BCAST|M_MCAST);
231: M_PREPEND(m, 3, M_DONTWAIT);
232: if (m == NULL)
233: return (0);
234: type = 0;
235: l = mtod(m, struct llc *);
236: l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
237: l->llc_control = LLC_UI;
238: IFDEBUG(D_ETHER)
239: int i;
240: printf("unoutput: sending pkt to: ");
241: for (i=0; i<6; i++)
242: printf("%x ", edst[i] & 0xff);
243: printf("\n");
244: ENDDEBUG
245: } break;
246: #endif /* ISO */
247: #if LLC
248: /* case AF_NSAP: */
249: case AF_CCITT: {
250: register struct sockaddr_dl *sdl =
251: (struct sockaddr_dl *) rt -> rt_gateway;
252:
253: if (sdl && sdl->sdl_family != AF_LINK && sdl->sdl_alen <= 0)
254: goto bad; /* Not a link interface ? Funny ... */
255: bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
256: if (*edst & 1)
257: loop_copy = 1;
258: type = 0;
259: #if LLC_DEBUG
260: {
261: int i;
262: register struct llc *l = mtod(m, struct llc *);
263:
264: printf("fddi_output: sending LLC2 pkt to: ");
265: for (i=0; i<6; i++)
266: printf("%x ", edst[i] & 0xff);
267: printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
268: type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
269: l->llc_control & 0xff);
270:
271: }
272: #endif /* LLC_DEBUG */
273: } break;
274: #endif /* LLC */
275:
276: case AF_UNSPEC:
277: {
278: struct ether_header *eh;
279: loop_copy = -1;
280: eh = (struct ether_header *)dst->sa_data;
281: (void)memcpy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
282: if (*edst & 1)
283: m->m_flags |= (M_BCAST|M_MCAST);
284: type = eh->ether_type;
285: break;
286: }
287:
288: #if NBPFILTER > 0
289: case AF_IMPLINK:
290: {
291: fh = mtod(m, struct fddi_header *);
292: error = EPROTONOSUPPORT;
293: switch (fh->fddi_fc & (FDDIFC_C|FDDIFC_L|FDDIFC_F)) {
294: case FDDIFC_LLC_ASYNC: {
295: /* legal priorities are 0 through 7 */
296: if ((fh->fddi_fc & FDDIFC_Z) > 7)
297: goto bad;
298: break;
299: }
300: case FDDIFC_LLC_SYNC: {
301: /* FDDIFC_Z bits reserved, must be zero */
302: if (fh->fddi_fc & FDDIFC_Z)
303: goto bad;
304: break;
305: }
306: case FDDIFC_SMT: {
307: /* FDDIFC_Z bits must be non zero */
308: if ((fh->fddi_fc & FDDIFC_Z) == 0)
309: goto bad;
310: break;
311: }
312: default: {
313: /* anything else is too dangerous */
314: goto bad;
315: }
316: }
317: error = 0;
318: if (fh->fddi_dhost[0] & 1)
319: m->m_flags |= (M_BCAST|M_MCAST);
320: goto queue_it;
321: }
322: #endif
323: default:
324: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
325: dst->sa_family);
326: senderr(EAFNOSUPPORT);
327: }
328:
329: if (type != 0) {
330: register struct llc *l;
331: M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
332: if (m == 0)
333: senderr(ENOBUFS);
334: l = mtod(m, struct llc *);
335: l->llc_control = LLC_UI;
336: l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
337: l->llc_snap.org_code[0] = l->llc_snap.org_code[1] = l->llc_snap.org_code[2] = 0;
338: (void)memcpy((caddr_t) &l->llc_snap.ether_type, (caddr_t) &type,
339: sizeof(u_int16_t));
340: }
341:
342: /*
343: * Add local net header. If no space in first mbuf,
344: * allocate another.
345: */
346: M_PREPEND(m, sizeof (struct fddi_header), M_DONTWAIT);
347: if (m == 0)
348: senderr(ENOBUFS);
349: fh = mtod(m, struct fddi_header *);
350: fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4;
351: (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst));
352: queue_it:
353: (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr,
354: sizeof(fh->fddi_shost));
355:
356: /*
357: * If a simplex interface, and the packet is being sent to our
358: * Ethernet address or a broadcast address, loopback a copy.
359: * XXX To make a simplex device behave exactly like a duplex
360: * device, we should copy in the case of sending to our own
361: * ethernet address (thus letting the original actually appear
362: * on the wire). However, we don't do that here for security
363: * reasons and compatibility with the original behavior.
364: */
365: if ((ifp->if_flags & IFF_SIMPLEX) &&
366: (loop_copy != -1)) {
367: if ((m->m_flags & M_BCAST) || loop_copy) {
368: struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
369:
370: (void) if_simloop(ifp,
371: n, dst, sizeof(struct fddi_header));
372: } else if (bcmp(fh->fddi_dhost,
373: fh->fddi_shost, sizeof(fh->fddi_shost)) == 0) {
374: (void) if_simloop(ifp,
375: m, dst, sizeof(struct fddi_header));
376: return(0); /* XXX */
377: }
378: }
379:
380: s = splimp();
381: /*
382: * Queue message on interface, and start output if interface
383: * not yet active.
384: */
385: if (IF_QFULL(&ifp->if_snd)) {
386: IF_DROP(&ifp->if_snd);
387: splx(s);
388: senderr(ENOBUFS);
389: }
390: ifp->if_obytes += m->m_pkthdr.len;
391: IF_ENQUEUE(&ifp->if_snd, m);
392: if ((ifp->if_flags & IFF_OACTIVE) == 0)
393: (*ifp->if_start)(ifp);
394: splx(s);
395: if (m->m_flags & M_MCAST)
396: ifp->if_omcasts++;
397: return (error);
398:
399: bad:
400: if (m)
401: m_freem(m);
402: return (error);
403: }
404:
405: /*
406: * Process a received FDDI packet;
407: * the packet is in the mbuf chain m without
408: * the fddi header, which is provided separately.
409: */
410: void
411: fddi_input(ifp, fh, m)
412: struct ifnet *ifp;
413: register struct fddi_header *fh;
414: struct mbuf *m;
415: {
416: register struct ifqueue *inq;
417: register struct llc *l;
418: int s;
419:
420: if ((ifp->if_flags & IFF_UP) == 0) {
421: m_freem(m);
422: return;
423: }
424: getmicrotime(&ifp->if_lastchange);
425: ifp->if_ibytes += m->m_pkthdr.len + sizeof (*fh);
426: if (fh->fddi_dhost[0] & 1) {
427: if (bcmp((caddr_t)fddibroadcastaddr, (caddr_t)fh->fddi_dhost,
428: sizeof(fddibroadcastaddr)) == 0)
429: m->m_flags |= M_BCAST;
430: else
431: m->m_flags |= M_MCAST;
432: ifp->if_imcasts++;
433: } else if ((ifp->if_flags & IFF_PROMISC)
434: && bcmp(((struct arpcom *)ifp)->ac_enaddr, (caddr_t)fh->fddi_dhost,
435: sizeof(fh->fddi_dhost)) != 0) {
436: m_freem(m);
437: return;
438: }
439:
440: #ifdef M_LINK0
441: /*
442: * If this has a LLC priority of 0, then mark it so upper
443: * layers have a hint that it really came via a FDDI/Ethernet
444: * bridge.
445: */
446: if ((fh->fddi_fc & FDDIFC_LLC_PRIO7) == FDDIFC_LLC_PRIO0)
447: m->m_flags |= M_LINK0;
448: #endif
449:
450: l = mtod(m, struct llc *);
451: switch (l->llc_dsap) {
452: #if defined(INET) || NS || IPX || defined(NETATALK)
453: case LLC_SNAP_LSAP:
454: {
455: u_int16_t type;
456: if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
457: goto dropanyway;
458:
459: if (l->llc_snap.org_code[0] != 0 || l->llc_snap.org_code[1] != 0|| l->llc_snap.org_code[2] != 0)
460: goto dropanyway;
461: type = ntohs(l->llc_snap.ether_type);
462: m_adj(m, 8);
463: switch (type) {
464: #if INET
465: case ETHERTYPE_IP:
466: if (ipflow_fastforward(m))
467: return;
468: schednetisr(NETISR_IP);
469: inq = &ipintrq;
470: break;
471:
472: case ETHERTYPE_ARP:
473: #if !defined(__bsdi__) || _BSDI_VERSION >= 199401
474: schednetisr(NETISR_ARP);
475: inq = &arpintrq;
476: break;
477: #else
478: arpinput((struct arpcom *)ifp, m);
479: return;
480: #endif
481: #endif
482: #if IPX
483: case ETHERTYPE_IPX:
484: schednetisr(NETISR_IPX);
485: inq = &ipxintrq;
486: break;
487: #endif
488: #if NS
489: case ETHERTYPE_NS:
490: schednetisr(NETISR_NS);
491: inq = &nsintrq;
492: break;
493: #endif
494: #if DECNET
495: case ETHERTYPE_DECNET:
496: schednetisr(NETISR_DECNET);
497: inq = &decnetintrq;
498: break;
499: #endif
500:
501: default:
502: /* printf("fddi_input: unknown protocol 0x%x\n", type); */
503: ifp->if_noproto++;
504: goto dropanyway;
505: }
506: break;
507: }
508: #endif /* INET || NS */
509: #if ISO
510: case LLC_ISO_LSAP:
511: switch (l->llc_control) {
512: case LLC_UI:
513: /* LLC_UI_P forbidden in class 1 service */
514: if ((l->llc_dsap == LLC_ISO_LSAP) &&
515: (l->llc_ssap == LLC_ISO_LSAP)) {
516: /* LSAP for ISO */
517: m->m_data += 3; /* XXX */
518: m->m_len -= 3; /* XXX */
519: m->m_pkthdr.len -= 3; /* XXX */
520: M_PREPEND(m, sizeof *fh, M_DONTWAIT);
521: if (m == 0)
522: return;
523: *mtod(m, struct fddi_header *) = *fh;
524: IFDEBUG(D_ETHER)
525: printf("clnp packet");
526: ENDDEBUG
527: schednetisr(NETISR_ISO);
528: inq = &clnlintrq;
529: break;
530: }
531: goto dropanyway;
532:
533: case LLC_XID:
534: case LLC_XID_P:
535: if(m->m_len < 6)
536: goto dropanyway;
537: l->llc_window = 0;
538: l->llc_fid = 9;
539: l->llc_class = 1;
540: l->llc_dsap = l->llc_ssap = 0;
541: /* Fall through to */
542: case LLC_TEST:
543: case LLC_TEST_P:
544: {
545: struct sockaddr sa;
546: register struct ether_header *eh;
547: struct arpcom *ac = (struct arpcom *) ifp;
548: int i;
549: u_char c = l->llc_dsap;
550:
551: l->llc_dsap = l->llc_ssap;
552: l->llc_ssap = c;
553: if (m->m_flags & (M_BCAST | M_MCAST))
554: bcopy((caddr_t)ac->ac_enaddr,
555: (caddr_t)eh->ether_dhost, 6);
556: sa.sa_family = AF_UNSPEC;
557: sa.sa_len = sizeof(sa);
558: eh = (struct ether_header *)sa.sa_data;
559: for (i = 0; i < 6; i++) {
560: eh->ether_shost[i] = fh->fddi_dhost[i];
561: eh->ether_dhost[i] = fh->fddi_shost[i];
562: }
563: eh->ether_type = 0;
564: ifp->if_output(ifp, m, &sa, NULL);
565: return;
566: }
567: default:
568: m_freem(m);
569: return;
570: }
571: break;
572: #endif /* ISO */
573: #if LLC
574: case LLC_X25_LSAP:
575: {
576: M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
577: if (m == 0)
578: return;
579: if ( !sdl_sethdrif(ifp, fh->fddi_shost, LLC_X25_LSAP,
580: fh->fddi_dhost, LLC_X25_LSAP, 6,
581: mtod(m, struct sdl_hdr *)))
582: panic("ETHER cons addr failure");
583: mtod(m, struct sdl_hdr *)->sdlhdr_len = m->m_pkthdr.len - sizeof(struct sdl_hdr);
584: #if LLC_DEBUG
585: printf("llc packet\n");
586: #endif /* LLC_DEBUG */
587: schednetisr(NETISR_CCITT);
588: inq = &llcintrq;
589: break;
590: }
591: #endif /* LLC */
592:
593: default:
594: /* printf("fddi_input: unknown dsap 0x%x\n", l->llc_dsap); */
595: ifp->if_noproto++;
596: dropanyway:
597: m_freem(m);
598: return;
599: }
600:
601: s = splimp();
602: if (IF_QFULL(inq)) {
603: IF_DROP(inq);
604: m_freem(m);
605: } else
606: IF_ENQUEUE(inq, m);
607: splx(s);
608: }
609: /*
610: * Perform common duties while attaching to interface list
611: */
612: #ifdef __NetBSD__
613: #define ifa_next ifa_list.tqe_next
614: #endif
615:
616: void
617: fddi_ifattach(ifp)
618: register struct ifnet *ifp;
619: {
620: register struct ifaddr *ifa;
621: register struct sockaddr_dl *sdl;
622:
623: ifp->if_type = IFT_FDDI;
624: ifp->if_addrlen = 6;
625: ifp->if_hdrlen = 21;
626: ifp->if_mtu = FDDIMTU;
627: ifp->if_baudrate = 100000000;
628: #if IFF_NOTRAILERS
629: ifp->if_flags |= IFF_NOTRAILERS;
630: #endif
631: #if defined(__FreeBSD__)
632: ifa = ifnet_addrs[ifp->if_index - 1];
633: sdl = (struct sockaddr_dl *)ifa->ifa_addr;
634: sdl->sdl_type = IFT_FDDI;
635: sdl->sdl_alen = ifp->if_addrlen;
636: bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
637: #elif defined(__NetBSD__)
638: LIST_INIT(&((struct arpcom *)ifp)->ac_multiaddrs);
639: for (ifa = ifp->if_addrlist.tqh_first; ifa != NULL; ifa = ifa->ifa_list.tqe_next)
640: #else
641: for (ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next)
642: #endif
643: #if !defined(__FreeBSD__)
644: if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
645: sdl->sdl_family == AF_LINK) {
646: sdl->sdl_type = IFT_FDDI;
647: sdl->sdl_alen = ifp->if_addrlen;
648: bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
649: LLADDR(sdl), ifp->if_addrlen);
650: break;
651: }
652: #endif
653: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.