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