2 * Copyright (C) 1999-2001 Internet Software Consortium.
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
9 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
11 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
13 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
14 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: ifiter_ioctl.c,v 1.34 2002/08/16 00:05:57 marka Exp $ */
21 * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
25 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
26 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
27 #define lifc_len iflc_len
28 #define lifc_buf iflc_buf
29 #define lifc_req iflc_req
30 #define LIFCONF if_laddrconf
32 #define ISC_HAVE_LIFC_FAMILY 1
33 #define ISC_HAVE_LIFC_FLAGS 1
34 #define LIFCONF lifconf
37 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
38 #define lifr_addr iflr_addr
39 #define lifr_name iflr_name
40 #define lifr_dstaddr iflr_dstaddr
41 #define lifr_broadaddr iflr_broadaddr
42 #define lifr_flags iflr_flags
43 #define ss_family sa_family
44 #define LIFREQ if_laddrreq
50 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
51 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
53 struct isc_interfaceiter {
54 unsigned int magic; /* Magic number. */
59 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
62 void *buf; /* Buffer for sysctl data. */
63 unsigned int bufsize; /* Bytes allocated. */
64 #ifdef HAVE_TRUCLUSTER
65 int clua_context; /* Cluster alias context */
67 unsigned int pos; /* Current offset in
69 isc_interface_t current; /* Current interface data. */
70 isc_result_t result; /* Last result code. */
73 #ifdef HAVE_TRUCLUSTER
74 #include <clua/clua.h>
75 #include <sys/socket.h>
80 * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
81 * will have more than a megabyte of interface configuration data.
83 #define IFCONF_BUFSIZE_INITIAL 4096
84 #define IFCONF_BUFSIZE_MAX 1048576
87 getbuf4(isc_interfaceiter_t *iter) {
88 char strbuf[ISC_STRERRORSIZE];
90 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
93 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
94 if (iter->buf == NULL)
95 return (ISC_R_NOMEMORY);
97 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
98 iter->ifc.ifc_len = iter->bufsize;
99 iter->ifc.ifc_buf = iter->buf;
101 * Ignore the HP/UX warning about "integer overflow during
102 * conversion". It comes from its own macro definition,
103 * and is really hard to shut up.
105 if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
107 if (errno != EINVAL) {
108 isc__strerror(errno, strbuf, sizeof(strbuf));
109 UNEXPECTED_ERROR(__FILE__, __LINE__,
110 isc_msgcat_get(isc_msgcat,
111 ISC_MSGSET_IFITERIOCTL,
114 "configuration: %s"),
119 * EINVAL. Retry with a bigger buffer.
123 * The ioctl succeeded.
124 * Some OS's just return what will fit rather
125 * than set EINVAL if the buffer is too small
126 * to fit all the interfaces in. If
127 * ifc.lifc_len is too near to the end of the
128 * buffer we will grow it just in case and
131 if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
135 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
136 UNEXPECTED_ERROR(__FILE__, __LINE__,
137 isc_msgcat_get(isc_msgcat,
138 ISC_MSGSET_IFITERIOCTL,
146 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
151 return (ISC_R_SUCCESS);
154 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
156 return (ISC_R_UNEXPECTED);
160 getbuf6(isc_interfaceiter_t *iter) {
161 #if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
163 return (ISC_R_NOTIMPLEMENTED);
165 char strbuf[ISC_STRERRORSIZE];
168 iter->bufsize = IFCONF_BUFSIZE_INITIAL;
171 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
172 if (iter->buf == NULL)
173 return (ISC_R_NOMEMORY);
175 memset(&iter->lifc.lifc_len, 0, sizeof(iter->lifc.lifc_len));
176 #ifdef ISC_HAVE_LIFC_FAMILY
177 iter->lifc.lifc_family = AF_UNSPEC;
179 #ifdef ISC_HAVE_LIFC_FLAGS
180 iter->lifc.lifc_flags = 0;
182 iter->lifc.lifc_len = iter->bufsize;
183 iter->lifc.lifc_buf = iter->buf;
185 * Ignore the HP/UX warning about "integer overflow during
186 * conversion". It comes from its own macro definition,
187 * and is really hard to shut up.
189 if (ioctl(iter->socket, SIOCGLIFCONF, (char *)&iter->lifc)
193 * IPv6 interface scanning is not available on all
194 * kernels w/ IPv6 sockets.
196 if (errno == ENOENT) {
197 isc__strerror(errno, strbuf, sizeof(strbuf));
198 UNEXPECTED_ERROR(__FILE__, __LINE__,
199 isc_msgcat_get(isc_msgcat,
200 ISC_MSGSET_IFITERIOCTL,
203 "configuration: %s"),
205 result = ISC_R_FAILURE;
209 if (errno != EINVAL) {
210 isc__strerror(errno, strbuf, sizeof(strbuf));
211 UNEXPECTED_ERROR(__FILE__, __LINE__,
212 isc_msgcat_get(isc_msgcat,
213 ISC_MSGSET_IFITERIOCTL,
216 "configuration: %s"),
218 result = ISC_R_UNEXPECTED;
222 * EINVAL. Retry with a bigger buffer.
226 * The ioctl succeeded.
227 * Some OS's just return what will fit rather
228 * than set EINVAL if the buffer is too small
229 * to fit all the interfaces in. If
230 * ifc.ifc_len is too near to the end of the
231 * buffer we will grow it just in case and
234 if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
238 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
239 UNEXPECTED_ERROR(__FILE__, __LINE__,
240 isc_msgcat_get(isc_msgcat,
241 ISC_MSGSET_IFITERIOCTL,
247 result = ISC_R_UNEXPECTED;
250 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
256 return (ISC_R_SUCCESS);
259 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
266 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
267 isc_interfaceiter_t *iter;
269 char strbuf[ISC_STRERRORSIZE];
271 REQUIRE(iterp != NULL);
272 REQUIRE(*iterp == NULL);
274 iter = isc_mem_get(mctx, sizeof(*iter));
276 return (ISC_R_NOMEMORY);
283 * Create an unbound datagram socket to do the SIOCGLIFADDR ioctl on.
285 if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
286 isc__strerror(errno, strbuf, sizeof(strbuf));
287 UNEXPECTED_ERROR(__FILE__, __LINE__,
288 isc_msgcat_get(isc_msgcat,
289 ISC_MSGSET_IFITERIOCTL,
290 ISC_MSG_MAKESCANSOCKET,
294 result = ISC_R_UNEXPECTED;
299 * Get the interface configuration, allocating more memory if
303 result = isc_net_probeipv6();
304 if (result == ISC_R_SUCCESS)
305 result = getbuf6(iter);
306 if (result != ISC_R_SUCCESS)
307 result = getbuf4(iter);
308 if (result != ISC_R_SUCCESS)
312 * A newly created iterator has an undefined position
313 * until isc_interfaceiter_first() is called.
315 #ifdef HAVE_TRUCLUSTER
316 iter->clua_context = -1;
318 iter->pos = (unsigned int) -1;
319 iter->result = ISC_R_FAILURE;
321 iter->magic = IFITER_MAGIC;
323 return (ISC_R_SUCCESS);
326 if (iter->buf != NULL)
327 isc_mem_put(mctx, iter->buf, iter->bufsize);
328 (void) close(iter->socket);
331 isc_mem_put(mctx, iter, sizeof(*iter));
335 #ifdef HAVE_TRUCLUSTER
337 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
338 dst->family = AF_INET;
339 memcpy(&dst->type.in, src, sizeof(struct in_addr));
343 internal_current_clusteralias(isc_interfaceiter_t *iter) {
346 while (clua_getaliasaddress(&sa, &iter->clua_context) == CLUA_SUCCESS) {
347 if (clua_getaliasinfo(&sa, &ci) != CLUA_SUCCESS)
349 memset(&iter->current, 0, sizeof(iter->current));
350 iter->current.af = sa.sa_family;
351 memset(iter->current.name, 0, sizeof(iter->current.name));
352 sprintf(iter->current.name, "clua%d", ci.aliasid);
353 iter->current.flags = INTERFACE_F_UP;
354 get_inaddr(&iter->current.address, &ci.addr);
355 get_inaddr(&iter->current.netmask, &ci.netmask);
356 return (ISC_R_SUCCESS);
358 return (ISC_R_NOMORE);
363 * Get information about the current interface to iter->current.
364 * If successful, return ISC_R_SUCCESS.
365 * If the interface has an unsupported address family, or if
366 * some operation on it fails, return ISC_R_IGNORE to make
367 * the higher-level iterator code ignore it.
371 internal_current4(isc_interfaceiter_t *iter) {
375 char strbuf[ISC_STRERRORSIZE];
376 #if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
377 struct if_laddrreq if_laddrreq;
381 REQUIRE(VALID_IFITER(iter));
382 REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
384 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
386 memset(&ifreq, 0, sizeof(ifreq));
387 memcpy(&ifreq, ifrp, sizeof(ifreq));
389 family = ifreq.ifr_addr.sa_family;
390 #if !defined (SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
391 defined(ISC_PLATFORM_HAVEIPV6)
392 if (family != AF_INET && family != AF_INET6)
394 if (family != AF_INET)
396 return (ISC_R_IGNORE);
398 memset(&iter->current, 0, sizeof(iter->current));
399 iter->current.af = family;
401 INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
402 memset(iter->current.name, 0, sizeof(iter->current.name));
403 memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
405 get_addr(family, &iter->current.address,
406 (struct sockaddr *)&ifrp->ifr_addr);
409 * If the interface does not have a address ignore it.
413 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
414 return (ISC_R_IGNORE);
417 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
418 sizeof(in6addr_any)) == 0)
419 return (ISC_R_IGNORE);
424 * Get interface flags.
427 iter->current.flags = 0;
430 * Ignore the HP/UX warning about "integer overflow during
431 * conversion. It comes from its own macro definition,
432 * and is really hard to shut up.
434 if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
435 isc__strerror(errno, strbuf, sizeof(strbuf));
436 UNEXPECTED_ERROR(__FILE__, __LINE__,
437 "%s: getting interface flags: %s",
438 ifreq.ifr_name, strbuf);
439 return (ISC_R_IGNORE);
442 if ((ifreq.ifr_flags & IFF_UP) != 0)
443 iter->current.flags |= INTERFACE_F_UP;
445 if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
446 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
448 if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
449 iter->current.flags |= INTERFACE_F_LOOPBACK;
451 if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) {
452 iter->current.flags |= INTERFACE_F_BROADCAST;
456 if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) {
457 iter->current.flags |= INTERFACE_F_MULTICAST;
461 #if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
462 if (family == AF_INET)
465 memset(&if_laddrreq, 0, sizeof(if_laddrreq));
466 memcpy(if_laddrreq.iflr_name, iter->current.name,
467 sizeof(if_laddrreq.iflr_name));
468 memcpy(&if_laddrreq.addr, &iter->current.address.type.in6,
469 sizeof(iter->current.address.type.in6));
471 if (ioctl(iter->socket, SIOCGLIFADDR, &if_laddrreq) < 0) {
472 isc__strerror(errno, strbuf, sizeof(strbuf));
473 UNEXPECTED_ERROR(__FILE__, __LINE__,
474 "%s: getting interface address: %s",
475 ifreq.ifr_name, strbuf);
476 return (ISC_R_IGNORE);
480 * Netmask already zeroed.
482 iter->current.netmask.family = family;
483 for (i = 0; i < 16; i++) {
484 if (if_laddrreq.prefixlen > 8) {
486 if_laddrreq.prefixlen -= 8;
488 bits = 8 - if_laddrreq.prefixlen;
489 if_laddrreq.prefixlen = 0;
491 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
493 return (ISC_R_SUCCESS);
497 if (family != AF_INET)
498 return (ISC_R_IGNORE);
500 * If the interface is point-to-point, get the destination address.
502 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
504 * Ignore the HP/UX warning about "integer overflow during
505 * conversion. It comes from its own macro definition,
506 * and is really hard to shut up.
508 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
510 isc__strerror(errno, strbuf, sizeof(strbuf));
511 UNEXPECTED_ERROR(__FILE__, __LINE__,
512 isc_msgcat_get(isc_msgcat,
513 ISC_MSGSET_IFITERIOCTL,
516 "destination address: %s"),
517 ifreq.ifr_name, strbuf);
518 return (ISC_R_IGNORE);
520 get_addr(family, &iter->current.dstaddress,
521 (struct sockaddr *)&ifreq.ifr_dstaddr);
524 if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
526 * Ignore the HP/UX warning about "integer overflow during
527 * conversion. It comes from its own macro definition,
528 * and is really hard to shut up.
530 if (ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq)
532 isc__strerror(errno, strbuf, sizeof(strbuf));
533 UNEXPECTED_ERROR(__FILE__, __LINE__,
534 isc_msgcat_get(isc_msgcat,
535 ISC_MSGSET_IFITERIOCTL,
538 "broadcast address: %s"),
539 ifreq.ifr_name, strbuf);
540 return (ISC_R_IGNORE);
542 get_addr(family, &iter->current.broadcast,
543 (struct sockaddr *)&ifreq.ifr_broadaddr);
546 * Get the network mask.
548 memset(&ifreq, 0, sizeof(ifreq));
549 memcpy(&ifreq, ifrp, sizeof(ifreq));
551 * Ignore the HP/UX warning about "integer overflow during
552 * conversion. It comes from its own macro definition,
553 * and is really hard to shut up.
555 if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq)
557 isc__strerror(errno, strbuf, sizeof(strbuf));
558 UNEXPECTED_ERROR(__FILE__, __LINE__,
559 isc_msgcat_get(isc_msgcat,
560 ISC_MSGSET_IFITERIOCTL,
562 "%s: getting netmask: %s"),
563 ifreq.ifr_name, strbuf);
564 return (ISC_R_IGNORE);
566 get_addr(family, &iter->current.netmask,
567 (struct sockaddr *)&ifreq.ifr_addr);
568 return (ISC_R_SUCCESS);
572 internal_current6(isc_interfaceiter_t *iter) {
573 #if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
575 return (ISC_R_NOTIMPLEMENTED);
578 struct LIFREQ lifreq;
580 char strbuf[ISC_STRERRORSIZE];
582 REQUIRE(VALID_IFITER(iter));
583 REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len);
585 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos);
587 memset(&lifreq, 0, sizeof(lifreq));
588 memcpy(&lifreq, ifrp, sizeof(lifreq));
590 family = lifreq.lifr_addr.ss_family;
591 #ifdef ISC_PLATFORM_HAVEIPV6
592 if (family != AF_INET && family != AF_INET6)
594 if (family != AF_INET)
596 return (ISC_R_IGNORE);
598 memset(&iter->current, 0, sizeof(iter->current));
599 iter->current.af = family;
601 INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
602 memset(iter->current.name, 0, sizeof(iter->current.name));
603 memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
605 get_addr(family, &iter->current.address,
606 (struct sockaddr *)&lifreq.lifr_addr);
609 * If the interface does not have a address ignore it.
613 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
614 return (ISC_R_IGNORE);
617 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
618 sizeof(in6addr_any)) == 0)
619 return (ISC_R_IGNORE);
624 * Get interface flags.
627 iter->current.flags = 0;
630 * Ignore the HP/UX warning about "integer overflow during
631 * conversion. It comes from its own macro definition,
632 * and is really hard to shut up.
634 if (ioctl(iter->socket, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
637 * XXX This should be looked at further since it looks strange.
638 * If we get an ENXIO then we ignore the error and not worry
641 if (errno != ENXIO) {
642 isc__strerror(errno, strbuf, sizeof(strbuf));
643 UNEXPECTED_ERROR(__FILE__, __LINE__,
644 "%s: getting interface flags: %s",
645 lifreq.lifr_name, strbuf);
646 return (ISC_R_IGNORE);
650 if ((lifreq.lifr_flags & IFF_UP) != 0)
651 iter->current.flags |= INTERFACE_F_UP;
653 if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
654 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
656 if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
657 iter->current.flags |= INTERFACE_F_LOOPBACK;
660 * Note that IPv6 broadcast does not exist
661 * so don't check for IPv6 broadcast flag
665 if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) {
666 iter->current.flags |= INTERFACE_F_MULTICAST;
671 * If the interface is point-to-point, get the destination address.
673 if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
675 * Ignore the HP/UX warning about "interger overflow during
676 * conversion. It comes from its own macro definition,
677 * and is really hard to shut up.
679 if (ioctl(iter->socket, SIOCGLIFDSTADDR, (char *)&lifreq)
681 isc__strerror(errno, strbuf, sizeof(strbuf));
682 UNEXPECTED_ERROR(__FILE__, __LINE__,
683 isc_msgcat_get(isc_msgcat,
684 ISC_MSGSET_IFITERIOCTL,
687 "destination address: %s"),
688 lifreq.lifr_name, strbuf);
689 return (ISC_R_IGNORE);
691 get_addr(family, &iter->current.dstaddress,
692 (struct sockaddr *)&lifreq.lifr_dstaddr);
697 * Get the network mask.
699 memset(&lifreq, 0, sizeof(lifreq));
700 memcpy(&lifreq, ifrp, sizeof(lifreq));
704 * Ignore the HP/UX warning about "integer overflow during
705 * conversion. It comes from its own macro definition,
706 * and is really hard to shut up.
708 if (ioctl(iter->socket, SIOCGLIFNETMASK, (char *)&lifreq)
710 isc__strerror(errno, strbuf, sizeof(strbuf));
711 UNEXPECTED_ERROR(__FILE__, __LINE__,
712 isc_msgcat_get(isc_msgcat,
713 ISC_MSGSET_IFITERIOCTL,
715 "%s: getting netmask: %s"),
716 lifreq.lifr_name, strbuf);
717 return (ISC_R_IGNORE);
719 get_addr(family, &iter->current.netmask,
720 (struct sockaddr *)&lifreq.lifr_addr);
727 * Netmask already zeroed.
729 iter->current.netmask.family = family;
730 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
731 bits = lifreq.lifr_addrlen - i;
732 bits = (bits < 8) ? (8 - bits) : 0;
733 iter->current.netmask.type.in6.s6_addr[i / 8] =
741 return (ISC_R_SUCCESS);
746 internal_current(isc_interfaceiter_t *iter) {
748 return (internal_current6(iter));
749 return (internal_current4(iter));
753 * Step the iterator to the next interface. Unlike
754 * isc_interfaceiter_next(), this may leave the iterator
755 * positioned on an interface that will ultimately
756 * be ignored. Return ISC_R_NOMORE if there are no more
757 * interfaces, otherwise ISC_R_SUCCESS.
760 internal_next4(isc_interfaceiter_t *iter) {
763 REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
765 #ifdef HAVE_TRUCLUSTER
766 if (internal_current_clusteralias(iter) == ISC_R_SUCCESS)
767 return (ISC_R_SUCCESS);
769 ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
771 #ifdef ISC_PLATFORM_HAVESALEN
772 if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
773 iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
776 iter->pos += sizeof(*ifrp);
778 if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
779 return (ISC_R_NOMORE);
781 return (ISC_R_SUCCESS);
785 internal_next6(isc_interfaceiter_t *iter) {
786 #if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
788 return (ISC_R_NOTIMPLEMENTED);
792 REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len);
794 ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos);
796 #ifdef ISC_PLATFORM_HAVESALEN
797 if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
798 iter->pos += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
801 iter->pos += sizeof(*ifrp);
803 if (iter->pos >= (unsigned int) iter->lifc.lifc_len)
804 return (ISC_R_NOMORE);
806 return (ISC_R_SUCCESS);
811 internal_next(isc_interfaceiter_t *iter) {
813 return (internal_next6(iter));
814 return (internal_next4(iter));
818 internal_destroy(isc_interfaceiter_t *iter) {
819 (void) close(iter->socket);