diff --git a/CHANGES b/CHANGES index 19e35a41f5..36a4813b2d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +2342. [func] Use getifaddrs() if available under Linux. [RT #17224] + 2341. [bug] libbind: add missing -I../include for off source tree builds. [RT #17606] diff --git a/bin/tests/inter_test.c b/bin/tests/inter_test.c index 4dc19a801b..ffc9c36045 100644 --- a/bin/tests/inter_test.c +++ b/bin/tests/inter_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: inter_test.c,v 1.14 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: inter_test.c,v 1.15 2008/03/20 04:50:02 marka Exp $ */ /*! \file */ #include @@ -83,6 +83,53 @@ main(int argc, char **argv) { } } isc_interfaceiter_destroy(&iter); + + fprintf(stdout, "\nPass 2\n\n"); + + result = isc_interfaceiter_create(mctx, &iter); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_interfaceiter_first(iter); + while (result == ISC_R_SUCCESS) { + result = isc_interfaceiter_current(iter, &ifdata); + if (result != ISC_R_SUCCESS) { + fprintf(stdout, "isc_interfaceiter_current: %s", + isc_result_totext(result)); + continue; + } + fprintf(stdout, "%s %d %x\n", ifdata.name, ifdata.af, + ifdata.flags); + INSIST(ifdata.af == AF_INET || ifdata.af == AF_INET6); + res = inet_ntop(ifdata.af, &ifdata.address.type, buf, + sizeof(buf)); + if (ifdata.address.zone != 0) + fprintf(stdout, "address = %s (zone %u)\n", + res == NULL ? "BAD" : res, + ifdata.address.zone); + else + fprintf(stdout, "address = %s\n", + res == NULL ? "BAD" : res); + INSIST(ifdata.address.family == ifdata.af); + res = inet_ntop(ifdata.af, &ifdata.netmask.type, buf, + sizeof(buf)); + fprintf(stdout, "netmask = %s\n", res == NULL ? "BAD" : res); + INSIST(ifdata.netmask.family == ifdata.af); + if ((ifdata.flags & INTERFACE_F_POINTTOPOINT) != 0) { + res = inet_ntop(ifdata.af, &ifdata.dstaddress.type, + buf, sizeof(buf)); + fprintf(stdout, "dstaddress = %s\n", + res == NULL ? "BAD" : res); + + INSIST(ifdata.dstaddress.family == ifdata.af); + } + result = isc_interfaceiter_next(iter); + if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) { + fprintf(stdout, "isc_interfaceiter_next: %s", + isc_result_totext(result)); + continue; + } + } + isc_interfaceiter_destroy(&iter); cleanup: isc_mem_destroy(&mctx); diff --git a/configure b/configure index 0df76dc03e..1e879639c9 100755 --- a/configure +++ b/configure @@ -14,7 +14,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # -# $Id: configure,v 1.423 2008/01/30 04:49:59 marka Exp $ +# $Id: configure,v 1.424 2008/03/20 04:51:00 marka Exp $ # # Portions Copyright (C) 1996-2001 Nominum, Inc. # @@ -29,7 +29,7 @@ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# From configure.in Revision: 1.438 . +# From configure.in Revision: 1.439 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # @@ -1632,8 +1632,7 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --enable-libbind build libbind default=no --enable-ipv6 use IPv6 default=autodetect - --enable-getifaddrs Enable the use of getifaddrs() [yes|no|glibc]. - glibc: Use getifaddrs() in glibc if you know it supports IPv6. + --enable-getifaddrs Enable the use of getifaddrs() [yes|no]. --disable-isc-spnego use SPNEGO from GSSAPI library --disable-linux-caps disable linux capabilities --enable-atomic enable machine specific atomic operations @@ -9581,7 +9580,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 9584 "configure"' > conftest.$ac_ext + echo '#line 9583 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -11703,11 +11702,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11706: $lt_compile\"" >&5) + (eval echo "\"\$as_me:11705: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:11710: \$? = $ac_status" >&5 + echo "$as_me:11709: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -11946,11 +11945,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11949: $lt_compile\"" >&5) + (eval echo "\"\$as_me:11948: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:11953: \$? = $ac_status" >&5 + echo "$as_me:11952: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -12006,11 +12005,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12009: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12008: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12013: \$? = $ac_status" >&5 + echo "$as_me:12012: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14154,7 +14153,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:16447: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16452: \$? = $ac_status" >&5 + echo "$as_me:16451: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -16505,11 +16504,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16508: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16507: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16512: \$? = $ac_status" >&5 + echo "$as_me:16511: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -17833,7 +17832,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:18770: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:18775: \$? = $ac_status" >&5 + echo "$as_me:18774: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -18828,11 +18827,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:18831: $lt_compile\"" >&5) + (eval echo "\"\$as_me:18830: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:18835: \$? = $ac_status" >&5 + echo "$as_me:18834: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -20862,11 +20861,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:20865: $lt_compile\"" >&5) + (eval echo "\"\$as_me:20864: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:20869: \$? = $ac_status" >&5 + echo "$as_me:20868: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -21105,11 +21104,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:21108: $lt_compile\"" >&5) + (eval echo "\"\$as_me:21107: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:21112: \$? = $ac_status" >&5 + echo "$as_me:21111: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -21165,11 +21164,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:21168: $lt_compile\"" >&5) + (eval echo "\"\$as_me:21167: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:21172: \$? = $ac_status" >&5 + echo "$as_me:21171: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -23313,7 +23312,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5 +glibc) +{ echo "$as_me:$LINENO: WARNING: \"--enable-getifaddrs=glibc is no longer required\"" >&5 +echo "$as_me: WARNING: \"--enable-getifaddrs=glibc is no longer required\"" >&2;} +{ echo "$as_me:$LINENO: checking for getifaddrs" >&5 echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6; } if test "${ac_cv_func_getifaddrs+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -26402,84 +26396,9 @@ _ACEOF fi - else - save_LIBS="$LIBS" - LIBS="-L/usr/local/v6/lib $LIBS" - { echo "$as_me:$LINENO: checking for getifaddrs in -linet6" >&5 -echo $ECHO_N "checking for getifaddrs in -linet6... $ECHO_C" >&6; } -if test "${ac_cv_lib_inet6_getifaddrs+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-linet6 $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char getifaddrs (); -int -main () -{ -return getifaddrs (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_inet6_getifaddrs=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_inet6_getifaddrs=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_inet6_getifaddrs" >&5 -echo "${ECHO_T}$ac_cv_lib_inet6_getifaddrs" >&6; } -if test $ac_cv_lib_inet6_getifaddrs = yes; then - LIBS="$LIBS -linet6" - cat >>confdefs.h <<\_ACEOF -#define HAVE_GETIFADDRS 1 -_ACEOF - -else - LIBS=${save_LIBS} -fi - - fi - ;; -*) - { echo "$as_me:$LINENO: checking for getifaddrs" >&5 +;; +yes) +{ echo "$as_me:$LINENO: checking for getifaddrs" >&5 echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6; } if test "${ac_cv_func_getifaddrs+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -26567,8 +26486,6 @@ _ACEOF fi - ;; -esac ;; no) ;; diff --git a/configure.in b/configure.in index a05b7f8e1d..91d8ba1b84 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl AC_DIVERT_POP()dnl -AC_REVISION($Revision: 1.438 $) +AC_REVISION($Revision: 1.439 $) AC_INIT(lib/dns/name.c) AC_PREREQ(2.59) @@ -1669,38 +1669,21 @@ AC_SUBST(ISC_LWRES_GETADDRINFOPROTO) AC_SUBST(ISC_LWRES_GETNAMEINFOPROTO) AC_ARG_ENABLE(getifaddrs, -[ --enable-getifaddrs Enable the use of getifaddrs() [[yes|no|glibc]]. - glibc: Use getifaddrs() in glibc if you know it supports IPv6.], +[ --enable-getifaddrs Enable the use of getifaddrs() [[yes|no]].], want_getifaddrs="$enableval", want_getifaddrs="yes") +# +# This interface iteration code for getifaddrs() will fall back to using +# /proc/net/if_inet6 if getifaddrs() in glibc doesn't return any IPv6 +# addresses. +# case $want_getifaddrs in -yes|glibc) -# -# Do we have getifaddrs() ? -# -case $host in -*-linux*) - # Some recent versions of glibc support getifaddrs() which does not - # provide AF_INET6 addresses while the function provided by the USAGI - # project handles the AF_INET6 case correctly. We need to avoid - # using the former but prefer the latter unless overridden by - # --enable-getifaddrs=glibc. - if test $want_getifaddrs = glibc - then - AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS)) - else - save_LIBS="$LIBS" - LIBS="-L/usr/local/v6/lib $LIBS" - AC_CHECK_LIB(inet6, getifaddrs, - LIBS="$LIBS -linet6" - AC_DEFINE(HAVE_GETIFADDRS), - LIBS=${save_LIBS}) - fi - ;; -*) - AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS)) - ;; -esac +glibc) +AC_MSG_WARN("--enable-getifaddrs=glibc is no longer required") +AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS)) +;; +yes) +AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS)) ;; no) ;; diff --git a/lib/isc/unix/ifiter_getifaddrs.c b/lib/isc/unix/ifiter_getifaddrs.c index 4eaba33979..3a5a029f4c 100644 --- a/lib/isc/unix/ifiter_getifaddrs.c +++ b/lib/isc/unix/ifiter_getifaddrs.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ifiter_getifaddrs.c,v 1.9 2007/06/18 23:47:48 tbox Exp $ */ +/* $Id: ifiter_getifaddrs.c,v 1.10 2008/03/20 04:50:02 marka Exp $ */ /*! \file * \brief @@ -29,6 +29,10 @@ /*% Valid Iterator */ #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) +#ifdef __linux +static isc_boolean_t seenv6 = ISC_FALSE; +#endif + /*% Iterator structure */ struct isc_interfaceiter { unsigned int magic; /*%< Magic number. */ @@ -39,9 +43,13 @@ struct isc_interfaceiter { struct ifaddrs *pos; /*%< Ptr to current ifaddr */ isc_interface_t current; /*%< Current interface data. */ isc_result_t result; /*%< Last result code. */ +#ifdef __linux + FILE * proc; + char entry[ISC_IF_INET6_SZ]; + isc_result_t valid; +#endif }; - isc_result_t isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { isc_interfaceiter_t *iter; @@ -60,6 +68,17 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { iter->buf = NULL; iter->bufsize = 0; iter->ifaddrs = NULL; +#ifdef __linux + /* + * Only open "/proc/net/if_inet6" if we have never seen a IPv6 + * address returned by getifaddrs(). + */ + if (!seenv6) + iter->proc = fopen("/proc/net/if_inet6", "r"); + else + iter->proc = NULL; + iter->valid = ISC_R_FAILURE; +#endif if (getifaddrs(&iter->ifaddrs) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); @@ -86,6 +105,10 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { return (ISC_R_SUCCESS); failure: +#ifdef __linux + if (iter->proc != NULL) + fclose(iter->proc); +#endif if (iter->ifaddrs != NULL) /* just in case */ freeifaddrs(iter->ifaddrs); isc_mem_put(mctx, iter, sizeof(*iter)); @@ -109,6 +132,11 @@ internal_current(isc_interfaceiter_t *iter) { ifa = iter->pos; +#ifdef __linux + if (iter->pos == NULL) + return (linux_if_inet6_current(iter)); +#endif + INSIST(ifa != NULL); INSIST(ifa->ifa_name != NULL); @@ -119,6 +147,11 @@ internal_current(isc_interfaceiter_t *iter) { if (family != AF_INET && family != AF_INET6) return (ISC_R_IGNORE); +#ifdef __linux + if (family == AF_INET6) + seenv6 = ISC_TRUE; +#endif + memset(&iter->current, 0, sizeof(iter->current)); namelen = strlen(ifa->ifa_name); @@ -164,16 +197,28 @@ internal_current(isc_interfaceiter_t *iter) { */ static isc_result_t internal_next(isc_interfaceiter_t *iter) { - iter->pos = iter->pos->ifa_next; - if (iter->pos == NULL) + if (iter->pos != NULL) + iter->pos = iter->pos->ifa_next; + if (iter->pos == NULL) { +#ifdef __linux + if (!seenv6) + return (linux_if_inet6_next(iter)); +#endif return (ISC_R_NOMORE); + } return (ISC_R_SUCCESS); } static void internal_destroy(isc_interfaceiter_t *iter) { + +#ifdef __linux + if (iter->proc != NULL) + fclose(iter->proc); + iter->proc = NULL; +#endif if (iter->ifaddrs) freeifaddrs(iter->ifaddrs); iter->ifaddrs = NULL; @@ -181,5 +226,9 @@ internal_destroy(isc_interfaceiter_t *iter) { static void internal_first(isc_interfaceiter_t *iter) { + +#ifdef __linux + linux_if_inet6_first(iter); +#endif iter->pos = iter->ifaddrs; } diff --git a/lib/isc/unix/ifiter_ioctl.c b/lib/isc/unix/ifiter_ioctl.c index 46949e8f3c..6ea9a674cb 100644 --- a/lib/isc/unix/ifiter_ioctl.c +++ b/lib/isc/unix/ifiter_ioctl.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ifiter_ioctl.c,v 1.58 2007/08/30 06:02:28 marka Exp $ */ +/* $Id: ifiter_ioctl.c,v 1.59 2008/03/20 04:50:02 marka Exp $ */ /*! \file * \brief @@ -50,9 +50,6 @@ #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T') #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) -#define ISC_IF_INET6_SZ \ - sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n") - struct isc_interfaceiter { unsigned int magic; /* Magic number. */ isc_mem_t *mctx; @@ -82,7 +79,6 @@ struct isc_interfaceiter { FILE * proc; char entry[ISC_IF_INET6_SZ]; isc_result_t valid; - isc_boolean_t first; #endif isc_interface_t current; /* Current interface data. */ isc_result_t result; /* Last result code. */ @@ -372,7 +368,6 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { #ifdef __linux iter->proc = fopen("/proc/net/if_inet6", "r"); iter->valid = ISC_R_FAILURE; - iter->first = ISC_FALSE; #endif iter->result = ISC_R_FAILURE; @@ -422,89 +417,6 @@ internal_current_clusteralias(isc_interfaceiter_t *iter) { } #endif -#ifdef __linux -static isc_result_t -linux_if_inet6_next(isc_interfaceiter_t *iter) { - if (iter->proc != NULL && - fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL) - iter->valid = ISC_R_SUCCESS; - else - iter->valid = ISC_R_NOMORE; - return (iter->valid); -} - -static void -linux_if_inet6_first(isc_interfaceiter_t *iter) { - if (iter->proc != NULL) { - rewind(iter->proc); - (void)linux_if_inet6_next(iter); - } else - iter->valid = ISC_R_NOMORE; - iter->first = ISC_FALSE; -} - -static isc_result_t -linux_if_inet6_current(isc_interfaceiter_t *iter) { - char address[33]; - char name[IF_NAMESIZE+1]; - struct in6_addr addr6; - int ifindex, prefix, flag3, flag4; - int res; - unsigned int i; - - if (iter->valid != ISC_R_SUCCESS) - return (iter->valid); - if (iter->proc == NULL) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, - "/proc/net/if_inet6:iter->proc == NULL"); - return (ISC_R_FAILURE); - } - - res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n", - address, &ifindex, &prefix, &flag3, &flag4, name); - if (res != 6) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, - "/proc/net/if_inet6:sscanf() -> %d (expected 6)", - res); - return (ISC_R_FAILURE); - } - if (strlen(address) != 32) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, - "/proc/net/if_inet6:strlen(%s) != 32", address); - return (ISC_R_FAILURE); - } - for (i = 0; i < 16; i++) { - unsigned char byte; - static const char hex[] = "0123456789abcdef"; - byte = ((index(hex, address[i * 2]) - hex) << 4) | - (index(hex, address[i * 2 + 1]) - hex); - addr6.s6_addr[i] = byte; - } - iter->current.af = AF_INET6; - iter->current.flags = INTERFACE_F_UP; - isc_netaddr_fromin6(&iter->current.address, &addr6); - if (isc_netaddr_islinklocal(&iter->current.address)) { - isc_netaddr_setzone(&iter->current.address, - (isc_uint32_t)ifindex); - } - for (i = 0; i < 16; i++) { - if (prefix > 8) { - addr6.s6_addr[i] = 0xff; - prefix -= 8; - } else { - addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff; - prefix = 0; - } - } - isc_netaddr_fromin6(&iter->current.netmask, &addr6); - strncpy(iter->current.name, name, sizeof(iter->current.name)); - return (ISC_R_SUCCESS); -} -#endif - /* * Get information about the current interface to iter->current. * If successful, return ISC_R_SUCCESS. @@ -525,23 +437,19 @@ internal_current4(isc_interfaceiter_t *iter) { char sabuf[256]; #endif int i, bits, prefixlen; -#ifdef __linux - isc_result_t result; -#endif REQUIRE(VALID_IFITER(iter)); - REQUIRE(iter->ifc.ifc_len == 0 || - iter->pos < (unsigned int) iter->ifc.ifc_len); + if (iter->ifc.ifc_len == 0 || + iter->pos == (unsigned int)iter->ifc.ifc_len) { #ifdef __linux - result = linux_if_inet6_current(iter); - if (result != ISC_R_NOMORE) - return (result); - iter->first = ISC_TRUE; -#endif - - if (iter->ifc.ifc_len == 0) + return (linux_if_inet6_current(iter)); +#else return (ISC_R_NOMORE); +#endif + } + + INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len); ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); @@ -905,31 +813,25 @@ internal_next4(isc_interfaceiter_t *iter) { struct ifreq *ifrp; #endif - REQUIRE(iter->ifc.ifc_len == 0 || - iter->pos < (unsigned int) iter->ifc.ifc_len); - -#ifdef __linux - if (linux_if_inet6_next(iter) == ISC_R_SUCCESS) - return (ISC_R_SUCCESS); - if (!iter->first) - return (ISC_R_SUCCESS); -#endif - - if (iter->ifc.ifc_len == 0) - return (ISC_R_NOMORE); - + if (iter->pos < (unsigned int) iter->ifc.ifc_len) { #ifdef ISC_PLATFORM_HAVESALEN - ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); + ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); - if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr)) - iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len; - else + if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr)) + iter->pos += sizeof(ifrp->ifr_name) + + ifrp->ifr_addr.sa_len; + else #endif - iter->pos += sizeof(struct ifreq); + iter->pos += sizeof(struct ifreq); - if (iter->pos >= (unsigned int) iter->ifc.ifc_len) + } else { + INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len); +#ifdef __linux + return (linux_if_inet6_next(iter)); +#else return (ISC_R_NOMORE); - +#endif + } return (ISC_R_SUCCESS); } diff --git a/lib/isc/unix/interfaceiter.c b/lib/isc/unix/interfaceiter.c index 359e363a98..8321e7a375 100644 --- a/lib/isc/unix/interfaceiter.c +++ b/lib/isc/unix/interfaceiter.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfaceiter.c,v 1.42 2007/06/19 23:47:18 tbox Exp $ */ +/* $Id: interfaceiter.c,v 1.43 2008/03/20 04:50:02 marka Exp $ */ /*! \file */ @@ -145,6 +145,14 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src, * Include system-dependent code. */ +#ifdef __linux +#define ISC_IF_INET6_SZ \ + sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n") +static isc_result_t linux_if_inet6_next(isc_interfaceiter_t *); +static isc_result_t linux_if_inet6_current(isc_interfaceiter_t *); +static void linux_if_inet6_first(isc_interfaceiter_t *iter); +#endif + #if HAVE_GETIFADDRS #include "ifiter_getifaddrs.c" #elif HAVE_IFLIST_SYSCTL @@ -153,6 +161,88 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src, #include "ifiter_ioctl.c" #endif +#ifdef __linux +static void +linux_if_inet6_first(isc_interfaceiter_t *iter) { + if (iter->proc != NULL) { + rewind(iter->proc); + (void)linux_if_inet6_next(iter); + } else + iter->valid = ISC_R_NOMORE; +} + +static isc_result_t +linux_if_inet6_next(isc_interfaceiter_t *iter) { + if (iter->proc != NULL && + fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL) + iter->valid = ISC_R_SUCCESS; + else + iter->valid = ISC_R_NOMORE; + return (iter->valid); +} + +static isc_result_t +linux_if_inet6_current(isc_interfaceiter_t *iter) { + char address[33]; + char name[IF_NAMESIZE+1]; + struct in6_addr addr6; + int ifindex, prefix, flag3, flag4; + int res; + unsigned int i; + + if (iter->valid != ISC_R_SUCCESS) + return (iter->valid); + if (iter->proc == NULL) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, + "/proc/net/if_inet6:iter->proc == NULL"); + return (ISC_R_FAILURE); + } + + res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n", + address, &ifindex, &prefix, &flag3, &flag4, name); + if (res != 6) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, + "/proc/net/if_inet6:sscanf() -> %d (expected 6)", + res); + return (ISC_R_FAILURE); + } + if (strlen(address) != 32) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, + "/proc/net/if_inet6:strlen(%s) != 32", address); + return (ISC_R_FAILURE); + } + for (i = 0; i < 16; i++) { + unsigned char byte; + static const char hex[] = "0123456789abcdef"; + byte = ((index(hex, address[i * 2]) - hex) << 4) | + (index(hex, address[i * 2 + 1]) - hex); + addr6.s6_addr[i] = byte; + } + iter->current.af = AF_INET6; + iter->current.flags = INTERFACE_F_UP; + isc_netaddr_fromin6(&iter->current.address, &addr6); + if (isc_netaddr_islinklocal(&iter->current.address)) { + isc_netaddr_setzone(&iter->current.address, + (isc_uint32_t)ifindex); + } + for (i = 0; i < 16; i++) { + if (prefix > 8) { + addr6.s6_addr[i] = 0xff; + prefix -= 8; + } else { + addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff; + prefix = 0; + } + } + isc_netaddr_fromin6(&iter->current.netmask, &addr6); + strncpy(iter->current.name, name, sizeof(iter->current.name)); + return (ISC_R_SUCCESS); +} +#endif + /* * The remaining code is common to the sysctl and ioctl case. */