]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if_fddisubr.c
xnu-1228.3.13.tar.gz
[apple/xnu.git] / bsd / net / if_fddisubr.c
CommitLineData
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 */
126int
127fddi_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
383bad:
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 */
394void
395fddi_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
600void
601fddi_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}