diff options
author | ume <ume@FreeBSD.org> | 2000-07-14 17:15:34 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2000-07-14 17:15:34 +0000 |
commit | 70f27cd4dd7e1d1d852cba36b094d6dc066d927d (patch) | |
tree | f2ea77bde85e774d904c6d9e876c7f0783fca721 /contrib/tcp_wrappers/hosts_access.c | |
parent | 55485e0103d7b63665f16e41d400e306498c92a8 (diff) | |
download | FreeBSD-src-70f27cd4dd7e1d1d852cba36b094d6dc066d927d.zip FreeBSD-src-70f27cd4dd7e1d1d852cba36b094d6dc066d927d.tar.gz |
Add IPv6 scoped address support.
It enables us to control link-local connections by interface like
this:
ALL : [fe80::%ed0]/10 : allow
ALL : [fe80::]/10 : deny
Diffstat (limited to 'contrib/tcp_wrappers/hosts_access.c')
-rw-r--r-- | contrib/tcp_wrappers/hosts_access.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/contrib/tcp_wrappers/hosts_access.c b/contrib/tcp_wrappers/hosts_access.c index 2b4dcee..24f5753 100644 --- a/contrib/tcp_wrappers/hosts_access.c +++ b/contrib/tcp_wrappers/hosts_access.c @@ -41,6 +41,9 @@ static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22"; #include <errno.h> #include <setjmp.h> #include <string.h> +#ifdef INET6 +#include <netdb.h> +#endif extern char *fgets(); extern int errno; @@ -341,7 +344,8 @@ char *string; return (STRN_EQ(tok, string, n)); } else { /* exact match */ #ifdef INET6 - struct in6_addr pat, addr; + struct addrinfo hints, *res; + struct sockaddr_in6 pat, addr; int len, ret; char ch; @@ -349,11 +353,27 @@ char *string; if (*tok == '[' && tok[len - 1] == ']') { ch = tok[len - 1]; tok[len - 1] = '\0'; - ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + if ((ret = getaddrinfo(tok + 1, NULL, &hints, &res)) == 0) { + memcpy(&pat, res->ai_addr, sizeof(pat)); + freeaddrinfo(res); + } tok[len - 1] = ch; - if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1) + if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0) return NO; - return (!memcmp(&pat, &addr, sizeof(struct in6_addr))); + memcpy(&addr, res->ai_addr, sizeof(addr)); + freeaddrinfo(res); +#ifdef NI_WITHSCOPEID + if (pat.sin6_scope_id != 0 && + addr.sin6_scope_id != pat.sin6_scope_id) + return NO; +#endif + return (!memcmp(&pat.sin6_addr, &addr.sin6_addr, + sizeof(struct in6_addr))); + return (ret); } #endif return (STR_EQ(tok, string)); @@ -414,19 +434,26 @@ char *net_tok; char *mask_tok; char *string; { - struct in6_addr net, addr; + struct addrinfo hints, *res; + struct sockaddr_in6 net, addr; u_int32_t mask; int len, mask_len, i = 0; char ch; - if (inet_pton(AF_INET6, string, addr.s6_addr) != 1) - return NO; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + if (getaddrinfo(string, NULL, &hints, &res) != 0) + return NO; + memcpy(&addr, res->ai_addr, sizeof(addr)); + freeaddrinfo(res); - if (IN6_IS_ADDR_V4MAPPED(&addr)) { - if ((*(u_int32_t *)&net.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE + if (IN6_IS_ADDR_V4MAPPED(&addr.sin6_addr)) { + if ((*(u_int32_t *)&net.sin6_addr.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) return (NO); - return ((*(u_int32_t *)&addr.s6_addr[12] & mask) == *(u_int32_t *)&net.s6_addr[12]); + return ((*(u_int32_t *)&addr.sin6_addr.s6_addr[12] & mask) == *(u_int32_t *)&net.sin6_addr.s6_addr[12]); } /* match IPv6 address against netnumber/prefixlen */ @@ -435,22 +462,28 @@ char *string; return NO; ch = net_tok[len - 1]; net_tok[len - 1] = '\0'; - if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) { + if (getaddrinfo(net_tok + 1, NULL, &hints, &res) != 0) { net_tok[len - 1] = ch; return NO; } + memcpy(&net, res->ai_addr, sizeof(net)); + freeaddrinfo(res); net_tok[len - 1] = ch; if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128) return NO; +#ifdef NI_WITHSCOPEID + if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id) + return NO; +#endif while (mask_len > 0) { if (mask_len < 32) { mask = htonl(~(0xffffffff >> mask_len)); - if ((*(u_int32_t *)&addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.s6_addr[i] & mask)) + if ((*(u_int32_t *)&addr.sin6_addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.sin6_addr.s6_addr[i] & mask)) return NO; break; } - if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i]) + if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i]) return NO; i += 4; mask_len -= 32; |