Hello community, here is the log from the commit of package tcpd for openSUSE:Factory checked in at 2015-08-21 07:35:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/tcpd (Old) and /work/SRC/openSUSE:Factory/.tcpd.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "tcpd" Changes: -------- --- /work/SRC/openSUSE:Factory/tcpd/tcpd.changes 2014-12-01 14:00:35.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.tcpd.new/tcpd.changes 2015-08-21 07:35:28.000000000 +0200 @@ -1,0 +2,11 @@ +Mon Jul 20 14:08:16 UTC 2015 - o...@suse.com + +- Fix breakage of IPv6 address handling [bsc#914527, bsc#899185] + Added patches: + tcp_wrappers_7.6-ipv6-sockaddr-storage.patch + tcp_wrappers_7.6-ipv6-subnet.diff + tcp_wrappers_7.6-ipv6-host-match.patch + tcp_wrappers_7.6-ipv6-mapped-v4.patch +- Re-added static library + +------------------------------------------------------------------- New: ---- tcp_wrappers_7.6-ipv6-host-match.patch tcp_wrappers_7.6-ipv6-mapped-v4.patch tcp_wrappers_7.6-ipv6-sockaddr-storage.patch tcp_wrappers_7.6-ipv6-subnet.diff ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ tcpd.spec ++++++ --- /var/tmp/diff_new_pack.FUPkBy/_old 2015-08-21 07:35:29.000000000 +0200 +++ /var/tmp/diff_new_pack.FUPkBy/_new 2015-08-21 07:35:29.000000000 +0200 @@ -1,7 +1,7 @@ # # spec file for package tcpd # -# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,6 +17,7 @@ %define lname libwrap0 + Name: tcpd Version: 7.6 Release: 0 @@ -56,8 +57,16 @@ Patch27: tcp_wrappers_%{version}-fedora-bug17847.diff Patch28: tcp_wrappers_7.6-implicit-decl.patch Patch29: tcpd-ocloexec.patch +Patch30: tcp_wrappers_%{version}-ipv6-sockaddr-storage.patch +Patch31: tcp_wrappers_%{version}-ipv6-subnet.diff +Patch32: tcp_wrappers_%{version}-ipv6-host-match.patch +Patch33: tcp_wrappers_%{version}-ipv6-mapped-v4.patch BuildRequires: linux-kernel-headers Provides: nkitb:%{_sbindir}/tcpd +# bug437293 +%ifarch ppc64 +Obsoletes: tcpd-64bit +%endif BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -78,6 +87,11 @@ Group: Development/Languages/C and C++ Requires: %{lname} = %{version} Requires: glibc-devel +# bug437293 +%ifarch ppc64 +Obsoletes: tcpd-devel-64bit +%endif +# %description devel This package contains the library and header files, which are necessary @@ -115,9 +129,13 @@ %patch27 %patch28 %patch29 +%patch30 -p1 +%patch31 +%patch32 -p1 +%patch33 -p1 %build -make %{?_smp_mflags} linux CC=cc +make %{?_smp_mflags} linux CC="cc" %install install -d -m 755 %{buildroot}%{_includedir} @@ -126,6 +144,7 @@ install -d -m 755 %{buildroot}%{_mandir}/man{1,3,5,8} install -d -m 755 %{buildroot}/%{_lib} install -m 644 ip6utils.h tcpd.h %{buildroot}%{_includedir} +install -m 644 libwrap.a %{buildroot}/%{_libdir} install -m 755 safe_finger tcpd tcpdchk tcpdmatch try-from %{buildroot}%{_sbindir} install -m 644 hosts_access.3 %{buildroot}%{_mandir}/man3 install -m 644 hosts_access.5 hosts_options.5 %{buildroot}%{_mandir}/man5 @@ -141,7 +160,7 @@ %postun -n %{lname} -p /sbin/ldconfig %files -%defattr(-,root,root) +%defattr(644,root,root,755) %doc BLURB CHANGES DISCLAIMER README README.ipv6 README.NIS %doc %{_mandir}/man?/* %attr(755,root,root) %{_sbindir}/* @@ -152,9 +171,10 @@ %attr(755,root,root) /%{_lib}/libwrap.so.0* %files devel -%defattr(-,root,root) +%defattr(644,root,root,755) %{_includedir}/tcpd.h %{_includedir}/ip6utils.h +%{_libdir}/libwrap.a %{_libdir}/libwrap.so %changelog ++++++ tcp_wrappers_7.6-ipv6-host-match.patch ++++++ --- hosts_access.c | 271 ++++++++++++++++++++++++++++++++++----------------------- misc.c | 18 +++ tcpd.h | 2 3 files changed, 183 insertions(+), 108 deletions(-) Index: tcp_wrappers_7.6/hosts_access.c =================================================================== --- tcp_wrappers_7.6.orig/hosts_access.c +++ tcp_wrappers_7.6/hosts_access.c @@ -88,6 +88,10 @@ static int server_match(); static int client_match(); static int host_match(); static int string_match(); +static int masked_match(); +#ifdef INET6 +static void ipv6_mask(); +#endif /* Size of logical line buffer. */ @@ -293,6 +297,74 @@ struct hosts_info *host; return (match); } +static inline int +host_info_ipv6addr(const struct host_info *host, struct in6_addr *addrbuf) +{ + /* + * In some cases we don't get the sockaddr, only the addr. + * We use inet_pton to convert it to its binary representation + * and match against that. + */ + if (host->sin == NULL) { + if (host->addr == NULL || inet_pton(AF_INET6, host->addr, addrbuf) != 1) + return 0; + + return 1; + } else + if (host->sin->ss_family == AF_INET6) { + *addrbuf = ((struct sockaddr_in6 *) host->sin)->sin6_addr; + return 1; + } + return 0; +} + +static inline int +token_ipv6addr_and_mask(char *tok, struct in6_addr *addrbuf, unsigned int *maskbits) +{ + char *cbr; + char *slash; + + if (*tok != '[') + return 0; + + *maskbits = 128; + + ++tok; /* now points to the beginning of the IPv6 addr string */ + if ((cbr = strchr(tok, ']')) == NULL) { + tcpd_warn("bad IP6 address specification"); + return 0; + } + *cbr++ = '\0'; + + /* + * A /nnn prefix specifies how many bits of the address we + * need to check. + * Note, we support both [x::y/64] and [x::y]/64 + */ + if ((slash = strchr(tok, '/')) == NULL && *cbr == '/') + slash = cbr; + + if (slash != NULL) { + int mask; + + *slash++ = '\0'; + mask = atoi(slash); + if (mask < 0 || mask > 128) { + tcpd_warn("bad IP6 prefix specification"); + return 0; + } + + *maskbits = mask; + } + + if (inet_pton(AF_INET6, tok, addrbuf) != 1) { + tcpd_warn("bad IP6 address specification"); + return 0; + } + + return 1; +} + /* host_match - match host name and/or address against pattern */ static int host_match(tok, host) @@ -328,12 +400,68 @@ struct host_info *host; } else if (STR_EQ(tok, "LOCAL")) { /* local: no dots in name */ char *name = eval_hostname(host); return (strchr(name, '.') == 0 && HOSTNAME_KNOWN(name)); + } else if (tok[0] == '[') { /* IPv6 address */ +#ifdef INET6 + struct in6_addr match_addr, host_addr; + unsigned int mask = 128; + + if (!host_info_ipv6addr(host, &host_addr)) + return (NO); + + if (!token_ipv6addr_and_mask(tok, &match_addr, &mask)) + return (NO); + + /* + * Zero the bits we're not interested in in both addresses + * then compare. Note that we take a copy of the host info + * in that case. + */ + if (mask != 128) { + ipv6_mask(&match_addr, mask); + ipv6_mask(&host_addr, mask); + } + if (memcmp(&match_addr, &host_addr, sizeof(struct in6_addr)) == 0) + return (YES); +#endif + return (NO); + } else if ((mask = split_at(tok, '/')) != 0) { /* net/mask */ + return (masked_match(tok, mask, eval_hostaddr(host))); } else { /* anything else */ - return (string_match(tok, eval_hostaddr(host)) - || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host)))); + return (string_match(tok, eval_hostaddr(host)) + || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host)))); } } +static int masked_match(net_tok, mask_tok, string) +char *net_tok; +char *mask_tok; +char *string; +{ + unsigned long net; + unsigned long mask; + unsigned long addr; + + /* + * Disallow forms other than dotted quad: the treatment that inet_addr() + * gives to forms with less than four components is inconsistent with the + * access control language. John P. Rouillard <rou...@cs.umb.edu>. + */ + + if ((addr = dot_quad_addr(string)) == INADDR_NONE) + return (NO); + if ((net = dot_quad_addr(net_tok)) == INADDR_NONE + || ((mask = dot_quad_addr(mask_tok)) == INADDR_NONE + && strcmp(mask_tok, "255.255.255.255") + && (mask = prefix_to_netmask(mask_tok)) == INADDR_NONE + && strcmp(mask_tok, "32"))) { + /* 255.255.255.255 == INADDR_NONE, separate check needed. TJ. */ + /* 32 == INADDR_NONE, separate check needed. philipp */ + tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok); + return (NO); /* not tcpd_jump() */ + } + return ((addr & mask) == net); +} + /* string_match - match string against pattern * * tok = data read from /etc/hosts.* @@ -359,113 +487,14 @@ char *string; return (YES); } else if (STR_EQ(tok, "KNOWN")) { /* not unknown */ return (STR_NE(string, unknown)); - } else if (STR_EQ(tok, string)) /* exact match */ - return (YES); -#ifdef INET6 - else /* IP addresses match - not needed for IPv4 */ - { - /* For simplicity we convert everything to IPv6 (or v4 mapped) */ - struct in6_addr pat, addr; - int len, ret, prefixlen=128, nof_periods = 0; - char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition; - - /* If prefix was given, handle it */ - if ((mask = split_at(tok, '/')) != 0) - { - if (strchr(mask, '.') != NULL) /* We have something - like 255.255.0.0 */ - { - int b1, b2, b3, b4; - uint32_t netmask; - - if (sscanf(mask, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4) - { - tcpd_warn ("Wrong netmask in %s", tok); - return (NO); - } - netmask = (((((b1 * 256) + b2) * 256) + b3) * 256) + b4; - prefixlen = 0; - while (netmask > 0) - { - ++prefixlen; - netmask <<= 1; - } - } - else if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0) - { - tcpd_warn ("Wrong prefix length in %s", tok); - return (NO); - } - - if (is_v4_string (tok)) - prefixlen += 96; /* extend to v4mapped */ - - if (prefixlen > 128) - { - tcpd_warn ("Prefix too long in %s", tok); - return (NO); - } - } - - len = strlen(tok); - if (tok[len - 1] == '.') { /* prefix */ - char *ptok = tok; - - while ((ptok = strchr(ptok, '.')) != NULL){ - nof_periods++; - ptok++; - } - switch(nof_periods){ - case 1: - addition = "0.0.0"; - prefixlen = 8; - break; - case 2: - addition = "0.0"; - prefixlen = 16; - break; - case 3: - addition = "0"; - prefixlen = 24; - break; - default: - tcpd_warn ("Wrong prefix %s", tok); - return (NO); - } - snprintf(token, sizeof(token), "%s%s", tok, addition); - prefixlen += 96; /* extend to v4mapped */ - } - else if (*tok == '[' && tok[len - 1] == ']') - { - ch = tok[len - 1]; - tok[len - 1] = '\0'; - snprintf(token, sizeof(token), "%s", tok+1); - tok[len - 1] = ch; - } - else - snprintf(token, sizeof(token), "%s", tok); - - memset (&pat, 0, sizeof(pat)); - memset (&addr, 0, sizeof(addr)); - - if (inet_pton_mapped(AF_INET6, token, &pat) != 1) - return (NO); - - if (inet_pton_mapped(AF_INET6, string, &addr) != 1) - { - tcpd_warn("Unable to handle client address: %s", string); - return (NO); - } - - if (prefixlen < 128) - { - apply_v6_prefix (&pat, prefixlen); - apply_v6_prefix (&addr, prefixlen); - } - - return (!memcmp(&pat, &addr, sizeof(struct in6_addr))); + } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ + return (STRN_EQ(tok, string, n)); + } else if ((STR_EQ(tok, "localhost") || STR_EQ(tok, "localhost.localdomain")) + && (STR_EQ(string, "localhost") || STR_EQ(string, "localhost.localdomain"))) { + return (YES); /* these localhosts are equivalent */ + } else { /* exact match */ + return (STR_EQ(tok, string)); } -#endif } #ifndef DISABLE_WILDCARD_MATCHING @@ -535,3 +564,29 @@ int match_pattern_ylo(const char *s, con /*NOTREACHED*/ } #endif /* DISABLE_WILDCARD_MATCHING */ + +#ifdef INET6 +/* + * Function that zeros all but the first "maskbits" bits of the IPV6 address + * This function can be made generic by specifying an address length as + * extra parameter. (So Wietse can implement 1.2.3.4/16) + */ +static void ipv6_mask(in6p, maskbits) +struct in6_addr *in6p; +int maskbits; +{ + unsigned char *p = (unsigned char*) in6p; + + if (maskbits < 0 || maskbits >= 128) + return; + + p += maskbits / 8; + maskbits %= 8; + + if (maskbits != 0) + *p++ &= 0xff << (8 - maskbits); + + while (p < (((unsigned char*) in6p)) + sizeof(*in6p)) + *p++ = 0; +} +#endif Index: tcp_wrappers_7.6/misc.c =================================================================== --- tcp_wrappers_7.6.orig/misc.c +++ tcp_wrappers_7.6/misc.c @@ -107,3 +107,21 @@ char *str; } return (runs == 4 ? inet_addr(str) : INADDR_NONE); } + +/* prefix_to_netmask - convert prefix (0-32) to netmask */ + +unsigned long prefix_to_netmask(str) +char *str; +{ + unsigned long prefix; + char *endptr; + + if (!isdigit(str[0])) + return INADDR_NONE; + + prefix = strtoul(str, &endptr, 10); + if ((endptr == str) || (*endptr != '\0') || (prefix > 32)) + return INADDR_NONE; + + return htonl(~0UL << (32 - prefix)); +} Index: tcp_wrappers_7.6/tcpd.h =================================================================== --- tcp_wrappers_7.6.orig/tcpd.h +++ tcp_wrappers_7.6/tcpd.h @@ -88,6 +88,7 @@ extern void refuse(struct request_info * extern char *xgets(char *, int, FILE *); extern char *split_at(char *, int); extern unsigned long dot_quad_addr(char *); +extern char *skip_ipv6_addrs(char *); #else extern int hosts_access(); /* access control */ extern void shell_cmd(); /* execute shell command */ @@ -98,6 +99,7 @@ extern void refuse(); /* clean up and extern char *xgets(); /* fgets() on steroids */ extern char *split_at(); /* strchr() and split */ extern unsigned long dot_quad_addr(); /* restricted inet_addr() */ +extern char *skip_ipv6_addrs(); #endif /* Global variables. */ ++++++ tcp_wrappers_7.6-ipv6-mapped-v4.patch ++++++ --- hosts_access.c | 2 +- socket.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) Index: tcp_wrappers_7.6/hosts_access.c =================================================================== --- tcp_wrappers_7.6.orig/hosts_access.c +++ tcp_wrappers_7.6/hosts_access.c @@ -461,7 +461,7 @@ char *string; } return ((addr & mask) == net); } - + /* string_match - match string against pattern * * tok = data read from /etc/hosts.* Index: tcp_wrappers_7.6/socket.c =================================================================== --- tcp_wrappers_7.6.orig/socket.c +++ tcp_wrappers_7.6/socket.c @@ -187,24 +187,28 @@ struct host_info *host; #ifdef INET6 struct sockaddr *sin = (struct sockaddr *) host->sin; char *ap; - int alen; + int af; if (!sin) return; - switch (sin->sa_family) { + + af = sin->sa_family; + switch (af) { case AF_INET: ap = (char *)&((struct sockaddr_in *)sin)->sin_addr; - alen = sizeof(struct in_addr); break; case AF_INET6: ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr; - alen = sizeof(struct in6_addr); + if (IN6_IS_ADDR_V4MAPPED(ap)) { + ap = &((struct in6_addr *) ap)->s6_addr32[3]; + af = AF_INET; + } break; default: return; } host->addr[0] = '\0'; - inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr)); + inet_ntop(af, ap, host->addr, sizeof(host->addr)); #else struct sockaddr_in *sin = host->sin; ++++++ tcp_wrappers_7.6-ipv6-sockaddr-storage.patch ++++++ --- ip6utils.h | 2 + rfc931.c | 101 +++++++++++++++++++++++++++++++++++++++---------------------- scaffold.c | 9 +---- socket.c | 14 +------- tcpd.h | 8 +--- update.c | 4 +- 6 files changed, 76 insertions(+), 62 deletions(-) Index: tcp_wrappers_7.6/ip6utils.h =================================================================== --- tcp_wrappers_7.6.orig/ip6utils.h +++ tcp_wrappers_7.6/ip6utils.h @@ -1,6 +1,8 @@ #ifndef IP6UTILS_H #define IP6UTILS_H +#include <netinet/in.h> + /* inet_pton_mapped() - works like inet_pton(3) but always returns IPv6 address in dst - either "real" or v4mapped (::ffff:1.2.3.4) in Index: tcp_wrappers_7.6/rfc931.c =================================================================== --- tcp_wrappers_7.6.orig/rfc931.c +++ tcp_wrappers_7.6/rfc931.c @@ -65,28 +65,69 @@ int sig; siglongjmp(timebuf, sig); } +static inline unsigned int +sockaddr_len(const struct sockaddr_storage *ap) +{ + switch (ap->ss_family) { + case AF_INET: + return sizeof(struct sockaddr_in); + + case AF_INET6: + return sizeof(struct sockaddr_in6); + + } + + return 0; +} + +static inline unsigned short +sockaddr_port(const struct sockaddr_storage *ap) +{ + unsigned short num; + + switch (ap->ss_family) { + case AF_INET: + num = ((const struct sockaddr_in *) ap)->sin_port; + break; + case AF_INET6: + num = ((const struct sockaddr_in6 *) ap)->sin6_port; + break; + default: + num = 0; + break; + } + + return ntohs(num); +} + +static inline void +sockaddr_set_port(struct sockaddr_storage *ap, unsigned short port) +{ + unsigned short num = htons(port); + + switch (ap->ss_family) { + case AF_INET: + ((struct sockaddr_in *) ap)->sin_port = num; + break; + case AF_INET6: + ((struct sockaddr_in6 *) ap)->sin6_port = num; + break; + } +} + + /* rfc931 - return remote user name, given socket structures */ void rfc931(rmt_sin, our_sin, dest) -#ifdef INET6 -struct sockaddr *rmt_sin; -struct sockaddr *our_sin; -#else -struct sockaddr_in *rmt_sin; -struct sockaddr_in *our_sin; -#endif +struct sockaddr_storage *rmt_sin; +struct sockaddr_storage *our_sin; char *dest; { unsigned rmt_port; unsigned our_port; -#ifdef INET6 struct sockaddr_storage rmt_query_sin; struct sockaddr_storage our_query_sin; int alen; -#else - struct sockaddr_in rmt_query_sin; - struct sockaddr_in our_query_sin; -#endif char user[256]; /* XXX */ char buffer[512]; /* XXX */ char *cp; @@ -97,18 +138,13 @@ char *dest; #ifdef INET6 /* address family must be the same */ - if (rmt_sin->sa_family != our_sin->sa_family) { + if (rmt_sin->ss_family != our_sin->ss_family) { STRN_CPY(dest, result, STRING_LENGTH); return; } - switch (our_sin->sa_family) { - case AF_INET: - alen = sizeof(struct sockaddr_in); - break; - case AF_INET6: - alen = sizeof(struct sockaddr_in6); - break; - default: + + alen = sockaddr_len(our_sin); + if (alen == 0) { STRN_CPY(dest, result, STRING_LENGTH); return; } @@ -125,7 +161,7 @@ char *dest; */ #ifdef INET6 - if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) { + if ((fp = fsocket(our_sin->ss_family, SOCK_STREAM, 0)) != 0) { #else if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) { #endif @@ -154,18 +190,11 @@ char *dest; */ #ifdef INET6 - memcpy(&our_query_sin, our_sin, alen); - memcpy(&rmt_query_sin, rmt_sin, alen); - switch (our_sin->sa_family) { - case AF_INET: - ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT); - ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT); - break; - case AF_INET6: - ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT); - ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT); - break; - } + our_query_sin = *our_sin; + sockaddr_set_port(&our_query_sin, ANY_PORT); + + rmt_query_sin = *rmt_sin; + sockaddr_set_port(&rmt_query_sin, RFC931_PORT); if (bind(fileno(fp), (struct sockaddr *) & our_query_sin, alen) >= 0 && @@ -191,8 +220,8 @@ char *dest; fprintf(fp, "%u,%u\r\n", #ifdef INET6 - ntohs(((struct sockaddr_in *)rmt_sin)->sin_port), - ntohs(((struct sockaddr_in *)our_sin)->sin_port)); + sockaddr_port(rmt_sin), + sockaddr_port(our_sin)); #else ntohs(rmt_sin->sin_port), ntohs(our_sin->sin_port)); Index: tcp_wrappers_7.6/scaffold.c =================================================================== --- tcp_wrappers_7.6.orig/scaffold.c +++ tcp_wrappers_7.6/scaffold.c @@ -336,13 +336,8 @@ struct request_info *request; /* ARGSUSED */ void rfc931(rmt_sin, our_sin, dest) -#ifndef INET6 -struct sockaddr_in *rmt_sin; -struct sockaddr_in *our_sin; -#else -struct sockaddr *rmt_sin; -struct sockaddr *our_sin; -#endif +struct sockaddr_storage *rmt_sin; +struct sockaddr_storage *our_sin; char *dest; { strcpy(dest, unknown); Index: tcp_wrappers_7.6/tcpd.h =================================================================== --- tcp_wrappers_7.6.orig/tcpd.h +++ tcp_wrappers_7.6/tcpd.h @@ -19,11 +19,7 @@ struct host_info { char name[STRING_LENGTH]; /* access via eval_hostname(host) */ char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */ -#ifdef INET6 - struct sockaddr *sin; /* socket address or 0 */ -#else - struct sockaddr_in *sin; /* socket address or 0 */ -#endif + struct sockaddr_storage *sin; /* socket address or 0 */ struct t_unitdata *unit; /* TLI transport address or 0 */ struct request_info *request; /* for shared information */ }; @@ -86,7 +82,7 @@ extern void fromhost(); /* get/validat extern int hosts_access(struct request_info *); extern void shell_cmd(char *); extern char *percent_x(char *, int, char *, struct request_info *); -extern void rfc931(struct sockaddr *, struct sockaddr *, char *); +extern void rfc931(struct sockaddr_storage *, struct sockaddr_storage *, char *); extern void clean_exit(struct request_info *); extern void refuse(struct request_info *); extern char *xgets(char *, int, FILE *); Index: tcp_wrappers_7.6/socket.c =================================================================== --- tcp_wrappers_7.6.orig/socket.c +++ tcp_wrappers_7.6/socket.c @@ -116,11 +116,7 @@ struct request_info *request; memset(buf, 0 sizeof(buf)); #endif } -#ifdef INET6 - request->client->sin = (struct sockaddr *)&client; -#else request->client->sin = &client; -#endif /* * Determine the server binding. This is used for client username @@ -133,11 +129,7 @@ struct request_info *request; tcpd_warn("getsockname: %m"); return; } -#ifdef INET6 - request->server->sin = (struct sockaddr *)&server; -#else request->server->sin = &server; -#endif } @@ -180,7 +172,7 @@ struct request_info *request; sock_methods(request); memcpy(&client, res->ai_addr, res->ai_addrlen); - request->client->sin = (struct sockaddr *)&client; + request->client->sin = &client; freeaddrinfo(res); request->client->name[0] = 0; @@ -193,7 +185,7 @@ void sock_hostaddr(host) struct host_info *host; { #ifdef INET6 - struct sockaddr *sin = host->sin; + struct sockaddr *sin = (struct sockaddr *) host->sin; char *ap; int alen; @@ -227,7 +219,7 @@ void sock_hostname(struct host_info *host) { struct addrinfo hints, *res, *resbase; - struct sockaddr *sa = host->sin; + struct sockaddr *sa = (struct sockaddr *) host->sin; struct sockaddr_in6 *sin6, sin6buf; int errcode; Index: tcp_wrappers_7.6/update.c =================================================================== --- tcp_wrappers_7.6.orig/update.c +++ tcp_wrappers_7.6/update.c @@ -48,14 +48,14 @@ va_list ap; continue; case RQ_CLIENT_SIN: #ifdef INET6 - request->client->sin = va_arg(ap, struct sockaddr *); + request->client->sin = va_arg(ap, struct sockaddr_storage *); #else request->client->sin = va_arg(ap, struct sockaddr_in *); #endif continue; case RQ_SERVER_SIN: #ifdef INET6 - request->server->sin = va_arg(ap, struct sockaddr *); + request->server->sin = va_arg(ap, struct sockaddr_storage *); #else request->server->sin = va_arg(ap, struct sockaddr_in *); #endif ++++++ tcp_wrappers_7.6-ipv6-subnet.diff ++++++ --- hosts_access.c 2014/10/11 17:16:13 1.57 +++ hosts_access.c 2014/10/12 16:11:45 @@ -367,41 +367,10 @@ /* For simplicity we convert everything to IPv6 (or v4 mapped) */ struct in6_addr pat, addr; int len, ret, prefixlen=128, nof_periods = 0; - char ch, token[INET6_ADDRSTRLEN+1], *mask, *ptok = tok, *addition; - len = strlen(tok); - if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ - while ((ptok = strchr(ptok, '.')) != NULL){ - nof_periods++; - ptok++; - } - switch(nof_periods){ - case 1: - addition = "0.0.0/8"; - break; - case 2: - addition = "0.0/16"; - break; - case 3: - addition = "0/24"; - break; - default: - tcpd_warn ("Wrong prefix %s", tok); - return (NO); - } - snprintf(token, sizeof(token), "%s%s", tok, addition); - } - else if (*tok == '[' && tok[len - 1] == ']') - { - ch = tok[len - 1]; - tok[len - 1] = '\0'; - snprintf(token, sizeof(token), "%s", tok+1); - tok[len - 1] = ch; - } - else - snprintf(token, sizeof(token), "%s", tok); - + char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition; + /* If prefix was given, handle it */ - if ((mask = split_at(token, '/')) != 0) + if ((mask = split_at(tok, '/')) != 0) { if (strchr(mask, '.') != NULL) /* We have something like 255.255.0.0 */ @@ -428,7 +397,7 @@ return (NO); } - if (is_v4_string (token)) + if (is_v4_string (tok)) prefixlen += 96; /* extend to v4mapped */ if (prefixlen > 128) @@ -437,6 +406,44 @@ return (NO); } } + + len = strlen(tok); + if (tok[len - 1] == '.') { /* prefix */ + char *ptok = tok; + + while ((ptok = strchr(ptok, '.')) != NULL){ + nof_periods++; + ptok++; + } + switch(nof_periods){ + case 1: + addition = "0.0.0"; + prefixlen = 8; + break; + case 2: + addition = "0.0"; + prefixlen = 16; + break; + case 3: + addition = "0"; + prefixlen = 24; + break; + default: + tcpd_warn ("Wrong prefix %s", tok); + return (NO); + } + snprintf(token, sizeof(token), "%s%s", tok, addition); + prefixlen += 96; /* extend to v4mapped */ + } + else if (*tok == '[' && tok[len - 1] == ']') + { + ch = tok[len - 1]; + tok[len - 1] = '\0'; + snprintf(token, sizeof(token), "%s", tok+1); + tok[len - 1] = ch; + } + else + snprintf(token, sizeof(token), "%s", tok); memset (&pat, 0, sizeof(pat)); memset (&addr, 0, sizeof(addr));