From: Alan T. DeKok Date: Sat, 6 Mar 2010 13:26:27 +0000 (+0100) Subject: Add IPv6 "scope" for link-local addresses. X-Git-Tag: release_2_1_9~72 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e97b634069c2b0dabce0e64194c10250ac51b82b;p=thirdparty%2Ffreeradius-server.git Add IPv6 "scope" for link-local addresses. Added to fr_ipaddr_t. fr_ipaddr_cmp(), fr_sockaddr2ipaddr(), fr_ipaddr2sockaddr(). Also made ip_hton() call fr_sockaddr2ipaddr() to prevent code duplication. --- diff --git a/src/include/libradius.h b/src/include/libradius.h index 95535446390..db174226aad 100644 --- a/src/include/libradius.h +++ b/src/include/libradius.h @@ -194,6 +194,7 @@ typedef struct fr_ipaddr_t { struct in_addr ip4addr; struct in6_addr ip6addr; /* maybe defined in missing.h */ } ipaddr; + uint32_t scope; /* for IPv6 */ } fr_ipaddr_t; /* diff --git a/src/lib/misc.c b/src/lib/misc.c index 544ef8262ae..6963505aa90 100644 --- a/src/lib/misc.c +++ b/src/lib/misc.c @@ -405,14 +405,14 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t cnt) */ int ip_hton(const char *src, int af, fr_ipaddr_t *dst) { - int error; + int rcode; struct addrinfo hints, *ai = NULL, *res = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = af; - if ((error = getaddrinfo(src, NULL, &hints, &res)) != 0) { - fr_strerror_printf("ip_hton: %s", gai_strerror(error)); + if ((rcode = getaddrinfo(src, NULL, &hints, &res)) != 0) { + fr_strerror_printf("ip_hton: %s", gai_strerror(rcode)); return -1; } @@ -427,32 +427,11 @@ int ip_hton(const char *src, int af, fr_ipaddr_t *dst) return -1; } - switch (ai->ai_family) { - case AF_INET : - dst->af = AF_INET; - memcpy(&dst->ipaddr, - &((struct sockaddr_in*)ai->ai_addr)->sin_addr, - sizeof(struct in_addr)); - break; - -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - case AF_INET6 : - dst->af = AF_INET6; - memcpy(&dst->ipaddr, - &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr, - sizeof(struct in6_addr)); - break; -#endif - - /* Flow should never reach here */ - case AF_UNSPEC : - default : - fr_strerror_printf("ip_hton found unusable information for host %.100s", src); - freeaddrinfo(ai); - return -1; - } - + rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr, + ai->ai_addrlen, dst, NULL); freeaddrinfo(ai); + if (!rcode) return -1; + return 0; } @@ -573,6 +552,9 @@ int fr_ipaddr_cmp(const fr_ipaddr_t *a, const fr_ipaddr_t *b) #ifdef HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6: + if (a->scope < b->scope) return -1; + if (a->scope > b->scope) return +1; + return memcmp(&a->ipaddr.ip6addr, &b->ipaddr.ip6addr, sizeof(a->ipaddr.ip6addr)); @@ -611,6 +593,7 @@ int fr_ipaddr2sockaddr(const fr_ipaddr_t *ipaddr, int port, s6.sin6_family = AF_INET6; s6.sin6_addr = ipaddr->ipaddr.ip6addr; s6.sin6_port = htons(port); + s6.sin6_scope_id = ipaddr->scope; memset(sa, 0, sizeof(*sa)); memcpy(sa, &s6, sizeof(s6)); #endif @@ -623,15 +606,15 @@ int fr_ipaddr2sockaddr(const fr_ipaddr_t *ipaddr, int port, int fr_sockaddr2ipaddr(const struct sockaddr_storage *sa, socklen_t salen, - fr_ipaddr_t *ipaddr, int * port) + fr_ipaddr_t *ipaddr, int *port) { - /* - * FIXME: Check salen against sizeof socket structures. - */ - salen = salen; /* -Wunused */ - if (sa->ss_family == AF_INET) { struct sockaddr_in s4; + + if (salen < sizeof(s4)) { + fr_strerror_printf("IPv4 address is too small"); + return 0; + } memcpy(&s4, sa, sizeof(s4)); ipaddr->af = AF_INET; @@ -642,13 +625,21 @@ int fr_sockaddr2ipaddr(const struct sockaddr_storage *sa, socklen_t salen, } else if (sa->ss_family == AF_INET6) { struct sockaddr_in6 s6; + if (salen < sizeof(s6)) { + fr_strerror_printf("IPv6 address is too small"); + return 0; + } + memcpy(&s6, sa, sizeof(s6)); ipaddr->af = AF_INET6; ipaddr->ipaddr.ip6addr = s6.sin6_addr; if (port) *port = ntohs(s6.sin6_port); + ipaddr->scope = s6.sin6_scope_id; #endif } else { + fr_strerror_printf("Unsupported address famility %d", + sa->ss_family); return 0; }