]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/natpt_dispatch.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netinet6 / natpt_dispatch.c
CommitLineData
1c79356b
A
1/* $KAME: natpt_dispatch.c,v 1.9 2000/03/25 07:23:54 sumikawa Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/malloc.h>
34#include <sys/mbuf.h>
35#include <sys/socket.h>
36#include <sys/syslog.h>
37#include <sys/systm.h>
38
39#ifdef __FreeBSD__
40# include <sys/kernel.h>
41#endif
42
43#include <net/if.h>
44#include <net/net_osdep.h>
45
46#include <netinet/in.h>
47#include <netinet/in_systm.h>
48#include <netinet/ip.h>
49#include <netinet/ip_icmp.h>
50
51#include <netinet/ip6.h>
52#include <netinet6/ip6_var.h>
53#include <netinet/icmp6.h>
54
55#include <netinet6/natpt_defs.h>
56#include <netinet6/natpt_list.h>
57#include <netinet6/natpt_log.h>
58#include <netinet6/natpt_var.h>
59
60
61/*
62 *
63 */
64
65u_int natpt_debug;
66u_int natpt_dump;
67
68static struct _cell *ifBox;
69
70struct ifnet *natpt_ip6src;
71
72struct in6_addr faith_prefix
73 = {{{0x00000000, 0x00000000, 0x00000000, 0x00000000}}};
74struct in6_addr faith_prefixmask
75 = {{{0x00000000, 0x00000000, 0x00000000, 0x00000000}}};
76struct in6_addr natpt_prefix
77 = {{{0x00000000, 0x00000000, 0x00000000, 0x00000000}}};
78struct in6_addr natpt_prefixmask
79 = {{{0x00000000, 0x00000000, 0x00000000, 0x00000000}}};
80
81int natpt_in4 __P((struct mbuf *, struct mbuf **));
82int natpt_in6 __P((struct mbuf *, struct mbuf **));
83int natpt_out4 __P((struct mbuf *, struct mbuf **));
84int natpt_out6 __P((struct mbuf *, struct mbuf **));
85int natpt_incomingIPv4 __P((int, struct mbuf *, struct mbuf **));
86int natpt_outgoingIPv4 __P((int, struct mbuf *, struct mbuf **));
87int natpt_incomingIPv6 __P((int, struct mbuf *, struct mbuf **));
88int natpt_outgoingIPv6 __P((int, struct mbuf *, struct mbuf **));
89
90int configCv4 __P((int, struct mbuf *, struct _cv *));
91int configCv6 __P((int, struct mbuf *, struct _cv *));
92caddr_t foundFinalPayload __P((struct mbuf *, int *, int *));
93int sanityCheckIn4 __P((struct _cv *));
94int sanityCheckOut6 __P((struct _cv *));
95int checkMTU __P((struct _cv *));
96
97
98#if defined(__FreeBSD__) && __FreeBSD__ >= 3
99static MALLOC_DEFINE(M_NATPT, "NATPT", "Network Address Translation - Protocol Translation");
100#endif
101
102
103/*
104 *
105 */
106
107int
108natpt_in4(struct mbuf *m4, struct mbuf **m6)
109{
110 Cell *p;
111 struct ifnet *ifnet;
112 struct ifBox *ifb;
113 int rv = IPPROTO_IP;
114
115 if (natpt_initialized == 0)
116 return (IPPROTO_IP); /* goto ours */
117
118 if (isDump(D_DIVEIN4))
119 natpt_logMBuf(LOG_DEBUG, m4, "dive into natpt_in4.");
120
121 ifnet = m4->m_pkthdr.rcvif;
122 for (p = ifBox; p; p = CDR(p))
123 {
124 ifb = (struct ifBox *)CAR(p);
125 if (ifb->ifnet == ifnet)
126 {
127 if (ifb->side == outSide)
128 rv = natpt_incomingIPv4(NATPT_INBOUND, m4, m6);
129 else
130 rv = natpt_outgoingIPv4(NATPT_OUTBOUND, m4, m6);
131 goto exit;
132 }
133 }
134
135 exit:;
136 return (rv);
137}
138
139
140int
141natpt_in6(struct mbuf *m6, struct mbuf **m4)
142{
143 Cell *p;
144 struct ifnet *ifnet;
145 struct ifBox *ifb;
146 struct ip6_hdr *ip6;
147 struct in6_addr cand;
148 int rv = IPPROTO_IP;
149
150 if (natpt_initialized == 0)
151 return (IPPROTO_IP); /* goto mcastcheck */
152
153 if (isDump(D_DIVEIN6))
154 natpt_logMBuf(LOG_DEBUG, m6, "dive into natpt_in6.");
155
156 ip6 = mtod(m6, struct ip6_hdr *);
157
158 cand.s6_addr32[0] = ip6->ip6_dst.s6_addr32[0] & natpt_prefixmask.s6_addr32[0];
159 cand.s6_addr32[1] = ip6->ip6_dst.s6_addr32[1] & natpt_prefixmask.s6_addr32[1];
160 cand.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] & natpt_prefixmask.s6_addr32[2];
161 cand.s6_addr32[3] = ip6->ip6_dst.s6_addr32[3] & natpt_prefixmask.s6_addr32[3];
162
163 if ((cand.s6_addr32[0] != natpt_prefix.s6_addr32[0])
164 || (cand.s6_addr32[1] != natpt_prefix.s6_addr32[1])
165 || (cand.s6_addr32[2] != natpt_prefix.s6_addr32[2])
166 || (cand.s6_addr32[3] != natpt_prefix.s6_addr32[3]))
167 {
168 if (isDump(D_IN6REJECT))
169 natpt_logMBuf(LOG_DEBUG, m6, "v6 translation rejected.");
170
171 return (IPPROTO_IP); /* goto mcastcheck */
172 }
173
174 if (isDump(D_IN6ACCEPT))
175 natpt_logMBuf(LOG_DEBUG, m6, "v6 translation start.");
176
177 ifnet = m6->m_pkthdr.rcvif;
178 for (p = ifBox; p; p = CDR(p))
179 {
180 ifb = (struct ifBox *)CAR(p);
181 if (ifb->ifnet == ifnet)
182 {
183 if (ifb->side == outSide)
184 rv = natpt_incomingIPv6(NATPT_INBOUND, m6, m4);
185 else
186 rv = natpt_outgoingIPv6(NATPT_OUTBOUND, m6, m4);
187 goto exit;
188 }
189 }
190
191 exit:;
192 return (rv);
193}
194
195
196int
197natpt_out4(struct mbuf *m4, struct mbuf **m6)
198{
199 Cell *p;
200 struct ifnet *ifnet;
201 struct ifBox *ifb;
202 int rv = IPPROTO_IP;
203
204 ifnet = m4->m_pkthdr.rcvif;
205 for (p = ifBox; p; p = CDR(p))
206 {
207 ifb = (struct ifBox *)CAR(p);
208 if (ifb->ifnet == ifnet)
209 {
210 if (ifb->side == outSide)
211 rv = natpt_outgoingIPv4(NATPT_OUTBOUND, m4, m6);
212 else
213 rv = natpt_incomingIPv4(NATPT_INBOUND, m4, m6);
214 goto exit;
215 }
216 }
217
218 exit:;
219 return (rv);
220}
221
222
223
224int
225natpt_out6(struct mbuf *m6, struct mbuf **m4)
226{
227 Cell *p;
228 struct ifnet *ifnet;
229 struct ifBox *ifb;
230 int rv = IPPROTO_IP;
231
232 ifnet = m6->m_pkthdr.rcvif;
233 for (p = ifBox; p; p = CDR(p))
234 {
235 ifb = (struct ifBox *)CAR(p);
236 if (ifb->ifnet == ifnet)
237 {
238 if (ifb->side == outSide)
239 rv = natpt_outgoingIPv6(NATPT_OUTBOUND, m6, m4);
240 else
241 rv = natpt_incomingIPv6(NATPT_INBOUND, m6, m4);
242 goto exit;
243 }
244 }
245
246 exit:;
247 return (rv);
248}
249
250
251int
252natpt_incomingIPv4(int sess, struct mbuf *m4, struct mbuf **m6)
253{
254 int rv;
255 struct _cv cv;
256 struct _cSlot *acs;
257 struct _tSlot *ats;
258
259 if ((rv = configCv4(sess, m4, &cv)) == IPPROTO_MAX)
260 return (IPPROTO_MAX); /* discard this packet */
261
262 if ((rv = sanityCheckIn4(&cv)) != IPPROTO_IPV4)
263 return (IPPROTO_DONE); /* discard this packet without free */
264
265 cv.ats = lookingForIncomingV4Hash(&cv);
266 if ((ats = checkTraceroute6Return(&cv)) != NULL)
267 cv.ats = ats;
268
269 if (cv.ats == NULL)
270 {
271 if ((acs = lookingForIncomingV4Rule(&cv)) == NULL)
272 return (IPPROTO_IP); /* goto ours */
273
274 if ((cv.ats = internIncomingV4Hash(sess, acs, &cv)) == NULL)
275 return (IPPROTO_IP); /* goto ours */
276 }
277
278 if (checkMTU(&cv) != IPPROTO_IPV4)
279 return (IPPROTO_DONE); /* discard this packet without free */
280
281#ifdef NATPT_NAT
282 if (cv.ats->local.sa_family == AF_INET)
283 {
284 if ((*m6 = translatingIPv4To4(&cv, &cv.ats->local)) != NULL)
285 return (IPPROTO_IPV4);
286 }
287 else
288#endif
289 {
290 if ((*m6 = translatingIPv4To6(&cv, &cv.ats->local)) != NULL)
291 return (IPPROTO_IPV6);
292 }
293
294 return (IPPROTO_MAX); /* discard this packet */
295}
296
297
298int
299natpt_outgoingIPv4(int sess, struct mbuf *m4, struct mbuf **m6)
300{
301 int rv;
302 struct _cv cv;
303 struct _cSlot *acs;
304 struct ip *ip4;
305
306 if ((rv = configCv4(sess, m4, &cv)) == IPPROTO_MAX)
307 return (IPPROTO_MAX); /* discard this packet */
308
309 if ((cv.ats = lookingForOutgoingV4Hash(&cv)) == NULL)
310 {
311 if ((acs = lookingForOutgoingV4Rule(&cv)) == NULL)
312 return (IPPROTO_IP); /* goto ours */
313
314 ip4 = mtod(m4, struct ip *);
315 if (ip4->ip_ttl <= IPTTLDEC)
316 {
317 n_long dest = 0;
318
319 icmp_error(m4, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
320 return (IPPROTO_MAX); /* discard this packet */
321 }
322
323 if ((cv.ats = internOutgoingV4Hash(sess, acs, &cv)) == NULL)
324 return (IPPROTO_IP); /* goto ours */
325 }
326
327#ifdef NATPT_NAT
328 if (cv.ats->remote.sa_family == AF_INET)
329 {
330 if ((*m6 = translatingIPv4To4(&cv, &cv.ats->remote)) != NULL)
331 return (IPPROTO_IPV4);
332 }
333 else
334#endif
335 {
336 if ((*m6 = translatingIPv4To6(&cv, &cv.ats->remote)) != NULL)
337 return (IPPROTO_IPV6);
338 }
339
340 return (IPPROTO_MAX); /* discard this packet */
341}
342
343
344int
345natpt_incomingIPv6(int sess, struct mbuf *m6, struct mbuf **m4)
346{
347 int rv;
348 struct _cv cv;
349 struct _cSlot *acs;
350 struct ip6_hdr *ip6;
351
352 rv = configCv6(sess, m6, &cv);
353 if ((rv == IPPROTO_IP) || (rv == IPPROTO_MAX) || (rv == IPPROTO_DONE))
354 return (rv);
355
356 if ((cv.ats = lookingForIncomingV6Hash(&cv)) == NULL)
357 {
358 if ((acs = lookingForIncomingV6Rule(&cv)) == NULL)
359 return (IPPROTO_IP); /* goto mcastcheck */
360
361 ip6 = mtod(m6, struct ip6_hdr *);
362 if (ip6->ip6_hlim <= IPV6_HLIMDEC)
363 {
364 icmp6_error(m6, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT, 0);
365 return (IPPROTO_MAX); /* discard this packet */
366 }
367
368 if ((cv.ats = internIncomingV6Hash(sess, acs, &cv)) == NULL)
369 return (IPPROTO_IP); /* goto mcastcheck */
370 }
371
372 if ((*m4 = translatingIPv6To4(&cv, &cv.ats->local)) != NULL)
373 return (IPPROTO_IPV4);
374
375 return (IPPROTO_MAX); /* discard this packet */
376}
377
378
379int
380natpt_outgoingIPv6(int sess, struct mbuf *m6, struct mbuf **m4)
381{
382 int rv;
383 struct _cv cv6;
384 struct _cSlot *acs;
385
386 rv = configCv6(sess, m6, &cv6);
387 if ((rv == IPPROTO_IP) || (rv == IPPROTO_MAX) || (rv == IPPROTO_DONE))
388 return (rv);
389
390 if ((rv = sanityCheckOut6(&cv6)) != IPPROTO_IPV6)
391 return (IPPROTO_DONE); /* discard this packet */
392
393 if (isDump(D_PEEKOUTGOINGV6))
394 natpt_logIp6(LOG_DEBUG, cv6._ip._ip6);
395
396 if ((cv6.ats = lookingForOutgoingV6Hash(&cv6)) == NULL)
397 {
398 if ((acs = lookingForOutgoingV6Rule(&cv6)) == NULL)
399 return (IPPROTO_IP); /* goto mcastcheck */
400
401 if ((cv6.ats = internOutgoingV6Hash(sess, acs, &cv6)) == NULL)
402 return (IPPROTO_IP); /* goto mcastcheck */
403 }
404
405 if ((*m4 = translatingIPv6To4(&cv6, &cv6.ats->remote)) != NULL)
406 return (IPPROTO_IPV4);
407
408 return (IPPROTO_MAX); /* discard this packet */
409}
410
411
412int
413configCv4(int sess, struct mbuf *m, struct _cv *cv)
414{
415 struct ip *ip = mtod(m, struct ip *);
416
417 bzero(cv, sizeof(struct _cv));
418 cv->ip_p = ip->ip_p;
419 cv->m = m;
420 cv->_ip._ip4 = ip;
421 cv->inout = sess;
422
423 switch (ip->ip_p)
424 {
425 case IPPROTO_ICMP:
426 case IPPROTO_TCP:
427 case IPPROTO_UDP:
428 cv->ip_payload = ip->ip_p;
429 cv->_payload._caddr = (caddr_t)((u_long *)ip + ip->ip_hl);
430 cv->poff = cv->_payload._caddr - (caddr_t)cv->_ip._ip4;
431 cv->plen = (caddr_t)m->m_data + m->m_len - cv->_payload._caddr;
432 return (ip->ip_p);
433 }
434
435 return (IPPROTO_MAX);
436}
437
438
439int
440configCv6(int sess, struct mbuf *m, struct _cv *cv)
441{
442 int proto;
443 int offset;
444 caddr_t tcpudp;
445
446 bzero(cv, sizeof(struct _cv));
447 cv->m = m;
448 cv->_ip._ip6 = mtod(m, struct ip6_hdr *);
449 cv->inout = sess;
450
451 if ((tcpudp = foundFinalPayload(m, &proto, &offset)))
452 {
453 switch (proto)
454 {
455 case IPPROTO_ICMP:
456 case IPPROTO_ICMPV6:
457 case IPPROTO_TCP:
458 case IPPROTO_UDP:
459 cv->ip_p = proto;
460 cv->ip_payload = proto;
461 if (proto == IPPROTO_ICMPV6)
462 cv->ip_payload = IPPROTO_ICMP;
463 cv->_payload._caddr = tcpudp;
464 cv->poff = offset;
465 cv->plen = (caddr_t)m->m_data + m->m_len - cv->_payload._caddr;
466 return (proto);
467 }
468 }
469
470 return (proto);
471}
472
473
474caddr_t
475foundFinalPayload(struct mbuf *m, int *proto, int *offset)
476{
477 int nxt;
478 int off;
479 struct ip6_hdr *ip6;
480 struct ip6_ext *ip6ext;
481
482 ip6 = mtod(m, struct ip6_hdr *);
483 nxt = ip6->ip6_nxt;
484 off = sizeof(struct ip6_hdr);
485 ip6ext = (struct ip6_ext *)((struct ip6_hdr *)(ip6 + 1));
486 while (nxt != IPPROTO_NONE && off + sizeof(*ip6ext) < m->m_len)
487 {
488 switch (nxt)
489 {
490 case IPPROTO_HOPOPTS:
491 case IPPROTO_ROUTING:
492#if 0
493 case IPPROTO_FRAGMENT:
494#endif
495 case IPPROTO_DSTOPTS:
496 nxt = ip6ext->ip6e_nxt;
497 off += ip6ext->ip6e_len;
498 ip6ext = (struct ip6_ext *)(((caddr_t)ip6ext) + ip6ext->ip6e_len);
499 break;
500
501 case IPPROTO_ICMPV6:
502 case IPPROTO_TCP:
503 case IPPROTO_UDP:
504 *proto = nxt;
505 *offset = off;
506 return ((caddr_t)ip6ext);
507
508 default:
509 *proto = IPPROTO_IP; /* goto mcastcheck */
510 *offset = off;
511 return (NULL);
512 }
513 }
514
515 *proto = IPPROTO_IP; /* goto mcastcheck */
516 *offset = off;
517 return (NULL);
518}
519
520
521int
522sanityCheckIn4(struct _cv *cv4)
523{
524 struct mbuf *m4 = cv4->m;
525 struct ip *ip4 = mtod(m4, struct ip *);
526
527 if (ip4->ip_ttl <= IPTTLDEC)
528 {
529 n_long dest = 0;
530
531 icmp_error(m4, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
532 return (IPPROTO_DONE); /* discard this packet without free */
533 }
534
535 return (IPPROTO_IPV4);
536}
537
538
539int
540sanityCheckOut6(struct _cv *cv6)
541{
542 struct mbuf *m6 = cv6->m;
543 struct ip6_hdr *ip6 = mtod(m6, struct ip6_hdr *);
544
545 if (ip6->ip6_hlim <= IPV6_HLIMDEC)
546 {
547 icmp6_error(m6, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT, 0);
548 return (IPPROTO_DONE); /* discard this packet */
549 }
550
551 return (IPPROTO_IPV6);
552}
553
554
555int
556checkMTU(struct _cv *cv4)
557{
558 int mmtu;
559 struct mbuf *m4 = cv4->m;
560 struct ip *ip4 = mtod(m4, struct ip *);
561
562 mmtu = IPV6_MMTU - sizeof(struct ip6_hdr) - sizeof(struct ip6_frag);
563 /* This should be 1232[byte] */
564
565 if ((m4->m_flags & M_PKTHDR)
566 && (m4->m_pkthdr.len >= mmtu))
567 {
568 if (ip4->ip_off & IP_DF)
569 {
570 n_long dest = 0;
571 struct ifnet destif;
572
573 bzero(&destif, sizeof(struct ifnet));
574 destif.if_mtu = mmtu;
575
576#ifdef fixSuMiReICMPBug
577 ip4->ip_dst.s_addr = IPDST; /* XXX */
578#endif
579
580 icmp_error(m4, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, dest, &destif);
581 return (IPPROTO_DONE); /* discard this packet without free */
582 }
583
584 cv4->flags |= NATPT_NEEDFRAGMENT; /* fragment, then translate */
585 }
586
587 return (IPPROTO_IPV4);
588}
589
590
591/*
592 *
593 */
594
595
596struct ifBox *
597natpt_asIfBox(char *ifName)
598{
599 Cell *p;
600
601 for (p = ifBox; p; p = CDR(p))
602 {
603 if (strcmp(ifName, ((struct ifBox *)CAR(p))->ifName) == SAME)
604 return ((struct ifBox *)CAR(p));
605 }
606
607 return (NULL);
608}
609
610
611struct ifBox *
612natpt_setIfBox(char *ifName)
613{
614 struct ifnet *p;
615 struct ifBox *q;
616 char Wow[IFNAMSIZ];
617
618#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
619 for (p = ifnet; p; p = p->if_next)
620#else
621 for (p = TAILQ_FIRST(&ifnet); p; p = TAILQ_NEXT(p, if_list))
622#endif
623 {
624#ifdef __NetBSD__
625 sprintf(Wow, "%s%c", p->if_xname, '\0');
626#else
627 sprintf(Wow, "%s%d%c", p->if_name, p->if_unit, '\0');
628#endif
629 if (strcmp(ifName, Wow) != SAME)
630 continue;
631
632 natpt_ip6src = p;
633
634 MALLOC(q, struct ifBox *, sizeof(struct ifBox), M_NATPT, M_WAITOK);
635 bzero(q, sizeof(struct ifBox));
636
637 q->ifnet = p;
638#ifdef __NetBSD__
639 sprintf(q->ifName, "%s%c", p->if_xname, '\0');
640#else
641 sprintf(q->ifName, "%s%d%c", p->if_name, p->if_unit, '\0');
642#endif
643
644 LST_hookup_list((Cell**)&ifBox, q);
645 return (q);
646 }
647 return (NULL);
648}
649
650
651/*
652 *
653 */
654
655void
656natpt_debugProbe()
657{
658 printf("DebugProbe");
659}
660
661
662void
663natpt_assert(const char *file, int line, const char *failedexpr)
664{
665 (void)printf("natpt assertion \"%s\" failed: file \"%s\", line %d\n",
666 failedexpr, file, line);
667 panic("natpt assertion");
668 /* NOTREACHED */
669}
670
671
672/*
673 *
674 */
675
676void
677natpt_initialize()
678{
679 struct ifnet *ifn;
680 struct ifaddr *ifa;
681 struct ifBox *ibox;
682
683 if (natpt_initialized)
684 return;
685
686 natpt_initialized = 1;
687
688#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
689 for (ifn = ifnet; ifn; ifn = ifn->if_next)
690#else
691 for (ifn = TAILQ_FIRST(&ifnet); ifn; ifn = TAILQ_NEXT(ifn, if_list))
692#endif
693 {
694#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
695 for (ifa = ifn->if_addrlist; ifa; ifa = ifa->ifa_next)
696#else
697 for (ifa = ifn->if_addrlist.tqh_first; ifa;
698 ifa = ifa->ifa_list.tqe_next)
699#endif
700 {
701 if (((ifa->ifa_addr->sa_family) == AF_INET)
702 || ((ifa->ifa_addr->sa_family) == AF_INET6))
703 {
704 MALLOC(ibox, struct ifBox *, sizeof(struct ifBox), M_TEMP, M_WAITOK);
705#ifdef __NetBSD__
706 sprintf(ibox->ifName, "%s", ifn->if_xname);
707#else
708 sprintf(ibox->ifName, "%s%d", ifn->if_name, ifn->if_unit);
709#endif
710 ibox->ifnet = ifn;
711 ibox->side = NULL;
712 LST_hookup_list(&ifBox, ibox);
713 goto nextif;
714 }
715 }
716 nextif:
717 }
718}