From e7672a71aaa21f1dd2325ed1b64e222c9b19e612 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Sat, 26 Mar 2011 21:44:52 -0500 Subject: [PATCH] Patch to include non-loopback addresses from loopback interfaces. Signed-off-by: Love Hornquist Astrand --- lib/krb5/addr_families.c | 41 ++++++++++++++++++++++++++++++++++------ lib/krb5/get_addrs.c | 13 +++++++------ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/lib/krb5/addr_families.c b/lib/krb5/addr_families.c index cccf1cbc9..96e68620a 100644 --- a/lib/krb5/addr_families.c +++ b/lib/krb5/addr_families.c @@ -44,6 +44,7 @@ struct addr_operations { void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int); krb5_error_code (*h_addr2addr)(const char *, krb5_address *); krb5_boolean (*uninteresting)(const struct sockaddr *); + krb5_boolean (*is_loopback)(const struct sockaddr *); void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int); int (*print_addr)(const krb5_address *, char *, size_t); int (*parse_addr)(krb5_context, const char*, krb5_address *); @@ -136,6 +137,17 @@ ipv4_uninteresting (const struct sockaddr *sa) return FALSE; } +static krb5_boolean +ipv4_is_loopback (const struct sockaddr *sa) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + + if ((ntohl(sin4->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET) + return TRUE; + + return FALSE; +} + static void ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) { @@ -310,11 +322,19 @@ ipv6_uninteresting (const struct sockaddr *sa) const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr; - return - IN6_IS_ADDR_LINKLOCAL(in6) + return IN6_IS_ADDR_LINKLOCAL(in6) || IN6_IS_ADDR_V4COMPAT(in6); } +static krb5_boolean +ipv6_is_loopback (const struct sockaddr *sa) +{ + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr; + + return (IN6_IS_ADDR_LOOPBACK(in6)); +} + static void ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) { @@ -713,8 +733,8 @@ static struct addr_operations at[] = { ipv4_addr2sockaddr, ipv4_h_addr2sockaddr, ipv4_h_addr2addr, - ipv4_uninteresting, ipv4_anyaddr, ipv4_print_addr, ipv4_parse_addr, - NULL, NULL, NULL, ipv4_mask_boundary }, + ipv4_uninteresting, ipv4_is_loopback, ipv4_anyaddr, ipv4_print_addr, + ipv4_parse_addr, NULL, NULL, NULL, ipv4_mask_boundary }, #ifdef HAVE_IPV6 {AF_INET6, KRB5_ADDRESS_INET6, sizeof(struct sockaddr_in6), ipv6_sockaddr2addr, @@ -722,8 +742,8 @@ static struct addr_operations at[] = { ipv6_addr2sockaddr, ipv6_h_addr2sockaddr, ipv6_h_addr2addr, - ipv6_uninteresting, ipv6_anyaddr, ipv6_print_addr, ipv6_parse_addr, - NULL, NULL, NULL, ipv6_mask_boundary } , + ipv6_uninteresting, ipv6_is_loopback, ipv6_anyaddr, ipv6_print_addr, + ipv6_parse_addr, NULL, NULL, NULL, ipv6_mask_boundary } , #endif #ifndef HEIMDAL_SMALLER /* fake address type */ @@ -912,6 +932,15 @@ krb5_sockaddr_uninteresting(const struct sockaddr *sa) return (*a->uninteresting)(sa); } +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL +krb5_sockaddr_is_loopback(const struct sockaddr *sa) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL || a->is_loopback == NULL) + return TRUE; + return (*a->is_loopback)(sa); +} + /** * krb5_h_addr2sockaddr initializes a "struct sockaddr sa" from af and * the "struct hostent" (see gethostbyname(3) ) h_addr_list diff --git a/lib/krb5/get_addrs.c b/lib/krb5/get_addrs.c index 829b2acc1..8c692ecec 100644 --- a/lib/krb5/get_addrs.c +++ b/lib/krb5/get_addrs.c @@ -82,7 +82,7 @@ gethostname_fallback (krb5_context context, krb5_addresses *res) } enum { - LOOP = 1, /* do include loopback interfaces */ + LOOP = 1, /* do include loopback interfaces XXX remove */ LOOP_IF_NONE = 2, /* include loopback if no other if's */ EXTRA_ADDRESSES = 4, /* include extra addresses */ SCAN_INTERFACES = 8 /* scan interfaces for addresses */ @@ -146,11 +146,11 @@ find_all_addresses (krb5_context context, krb5_addresses *res, int flags) continue; if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) continue; - if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { + if (krb5_sockaddr_is_loopback(ifa->ifa_addr)) + continue; + if ((ifa->ifa_flags & IFF_LOOPBACK) != 0 && (flags & LOOP) == 0) /* We'll deal with the LOOP_IF_NONE case later. */ - if ((flags & LOOP) == 0) - continue; - } + continue; ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]); if (ret) { @@ -189,6 +189,7 @@ find_all_addresses (krb5_context context, krb5_addresses *res, int flags) continue; if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) continue; + /* XXX Do we really want to allow loopback addresses here? */ if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { ret = krb5_sockaddr2address(context, @@ -269,7 +270,7 @@ get_addrs_int (krb5_context context, krb5_addresses *res, int flags) KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_all_client_addrs (krb5_context context, krb5_addresses *res) { - int flags = LOOP_IF_NONE | EXTRA_ADDRESSES; + int flags = LOOP | LOOP_IF_NONE | EXTRA_ADDRESSES; if (context->scan_interfaces) flags |= SCAN_INTERFACES;