# ipv6_onoff.dpatch by Francesco Paolo Lovergine diff -urNad proftpd-dfsg-1.3.0~/include/netaddr.h proftpd-dfsg-1.3.0/include/netaddr.h --- proftpd-dfsg-1.3.0~/include/netaddr.h 2006-11-22 19:44:32.000000000 +0100 +++ proftpd-dfsg-1.3.0/include/netaddr.h 2006-11-22 19:44:46.000000000 +0100 @@ -1,6 +1,6 @@ /* * ProFTPD - FTP server daemon - * Copyright (c) 2003-2005 The ProFTPD Project team + * Copyright (c) 2003-2006 The ProFTPD Project team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -344,7 +344,7 @@ /* Returns TRUE if the given pr_netaddr_t contains a loopback address, * FALSE otherwise. */ -int pr_netaddr_loopback(const pr_netaddr_t *); +int pr_netaddr_is_loopback(const pr_netaddr_t *); /* Returns TRUE if the given pr_netaddr_t is of the AF_INET6 family and * contains an IPv4-mapped IPv6 address; otherwise FALSE is returned. A @@ -352,6 +352,15 @@ */ int pr_netaddr_is_v4mappedv6(const pr_netaddr_t *); +/* Returns TRUE if IPv6 support is enabled, FALSE otherwise. */ +unsigned char pr_netaddr_use_ipv6(void); + +/* Disables runtime use of IPv6 functionality (assuming IPv6 is supported). */ +void pr_netaddr_disable_ipv6(void); + +/* Enables runtime use of IPv6 functionality (assuming IPv6 is supported). */ +void pr_netaddr_enable_ipv6(void); + /* Return pointers to static memory which contains the local and remote * netaddr information for the sesssion. DO NOT MODIFY the pointed-to * memory! Returns NULL if no such session information exists. diff -urNad proftpd-dfsg-1.3.0~/modules/mod_core.c proftpd-dfsg-1.3.0/modules/mod_core.c --- proftpd-dfsg-1.3.0~/modules/mod_core.c 2006-11-22 19:44:45.000000000 +0100 +++ proftpd-dfsg-1.3.0/modules/mod_core.c 2006-11-22 19:48:23.000000000 +0100 @@ -448,14 +448,16 @@ const char *ipstr = pr_netaddr_get_ipstr(elts[i]); #ifdef PR_USE_IPV6 - char ipbuf[INET6_ADDRSTRLEN]; - if (pr_netaddr_get_family(elts[i]) == AF_INET) { + if (pr_netaddr_use_ipv6()) { + char *ipbuf = pcalloc(cmd->tmp_pool, INET6_ADDRSTRLEN); + if (pr_netaddr_get_family(elts[i]) == AF_INET) { - /* Create the bind record using the IPv4-mapped IPv6 version of - * this address. - */ - snprintf(ipbuf, sizeof(ipbuf), "::ffff:%s", ipstr); - ipstr = ipbuf; + /* Create the bind record using the IPv4-mapped IPv6 version of + * this address. + */ + snprintf(ipbuf, sizeof(ipbuf), "::ffff:%s", ipstr); + ipstr = ipbuf; + } } #endif /* PR_USE_IPV6 */ @@ -601,6 +603,33 @@ return HANDLED(cmd); } +/* usage: UseIPv6 on|off */ +MODRET set_useipv6(cmd_rec *cmd) { +#ifdef PR_USE_IPV6 + int bool = -1; + + CHECK_ARGS(cmd, 1); + CHECK_CONF(cmd, CONF_ROOT); + + bool = get_boolean(cmd, 1); + if (bool == -1) + CONF_ERROR(cmd, "expected Boolean parameter"); + + if (bool == 0) { + pr_log_debug(DEBUG2, "disabling runtime support for IPv6 connections"); + pr_netaddr_disable_ipv6(); + + } else { + pr_netaddr_enable_ipv6(); + } + + return HANDLED(cmd); +#else + CONF_ERROR(cmd, + "Use of the UseIPv6 directive requires IPv6 support (--enable-ipv6)"); +#endif /* PR_USE_IPV6 */ +} + MODRET set_usereversedns(cmd_rec *cmd) { int bool = -1; @@ -3110,9 +3139,15 @@ port = ((p1 << 8) | p2); #ifdef PR_USE_IPV6 - if (pr_netaddr_get_family(session.c->remote_addr) == AF_INET6) - snprintf(buf, sizeof(buf), "::ffff:%u.%u.%u.%u", h1, h2, h3, h4); - else + if (pr_netaddr_use_ipv6()) { + if (pr_netaddr_get_family(session.c->remote_addr) == AF_INET6) { + snprintf(buf, sizeof(buf), "::ffff:%u.%u.%u.%u", h1, h2, h3, h4); + + } else { + snprintf(buf, sizeof(buf), "%u.%u.%u.%u", h1, h2, h3, h4); + } + + } else #endif /* PR_USE_IPV6 */ snprintf(buf, sizeof(buf), "%u.%u.%u.%u", h1, h2, h3, h4); buf[sizeof(buf)-1] = '\0'; @@ -3139,15 +3174,17 @@ pr_netaddr_t *remote_addr = session.c->remote_addr; #ifdef PR_USE_IPV6 - /* We can only compare the PORT-given address against the remote client - * address if the remote client address is an IPv4-mapped IPv6 address. - */ - if (pr_netaddr_get_family(remote_addr) == AF_INET6 && - pr_netaddr_is_v4mappedv6(remote_addr) != TRUE) { - pr_log_pri(PR_LOG_WARNING, "Refused PORT %s (IPv4/IPv6 address mismatch)", - cmd->arg); - pr_response_add_err(R_500, "Illegal PORT command"); - return ERROR(cmd); + if (pr_netaddr_use_ipv6()) { + /* We can only compare the PORT-given address against the remote client + * address if the remote client address is an IPv4-mapped IPv6 address. + */ + if (pr_netaddr_get_family(remote_addr) == AF_INET6 && + pr_netaddr_is_v4mappedv6(remote_addr) != TRUE) { + pr_log_pri(PR_LOG_WARNING, + "Refused PORT %s (IPv4/IPv6 address mismatch)", cmd->arg); + pr_response_add_err(R_500, "Illegal PORT command"); + return ERROR(cmd); + } } #endif /* PR_USE_IPV6 */ @@ -3244,12 +3281,16 @@ #ifdef PR_USE_IPV6 case 2: - break; + if (pr_netaddr_use_ipv6()) + break; #endif /* PR_USE_IPV6 */ default: #ifdef PR_USE_IPV6 - pr_response_add_err(R_522, "Network protocol not supported, use (1,2)"); + if (pr_netaddr_use_ipv6()) + pr_response_add_err(R_522, "Network protocol not supported, use (1,2)"); + else + pr_response_add_err(R_522, "Network protocol not supported, use (1)"); #else pr_response_add_err(R_522, "Network protocol not supported, use (1)"); #endif /* PR_USE_IPV6 */ @@ -3435,8 +3476,10 @@ #ifdef PR_USE_IPV6 case AF_INET6: - family = 2; - break; + if (pr_netaddr_use_ipv6()) { + family = 2; + break; + } #endif /* PR_USE_IPV6 */ default: @@ -3451,12 +3494,16 @@ #ifdef PR_USE_IPV6 case 2: - break; + if (pr_netaddr_use_ipv6()) + break; #endif /* PR_USE_IPV6 */ default: #ifdef PR_USE_IPV6 - pr_response_add_err(R_522, "Network protocol not supported, use (1,2)"); + if (pr_netaddr_use_ipv6()) + pr_response_add_err(R_522, "Network protocol not supported, use (1,2)"); + else + pr_response_add_err(R_522, "Network protocol not supported, use (1)"); #else pr_response_add_err(R_522, "Network protocol not supported, use (1)"); #endif /* PR_USE_IPV6 */ @@ -4619,6 +4666,7 @@ { "TransferLog", add_transferlog, NULL }, { "Umask", set_umask, NULL }, { "UnsetEnv", set_unsetenv, NULL }, + { "UseIPv6", set_useipv6, NULL }, { "UseReverseDNS", set_usereversedns, NULL }, { "User", set_user, NULL }, { "UserOwner", add_userowner, NULL }, diff -urNad proftpd-dfsg-1.3.0~/src/bindings.c proftpd-dfsg-1.3.0/src/bindings.c --- proftpd-dfsg-1.3.0~/src/bindings.c 2006-11-22 19:44:32.000000000 +0100 +++ proftpd-dfsg-1.3.0/src/bindings.c 2006-11-22 19:44:46.000000000 +0100 @@ -57,10 +57,6 @@ static pr_ipbind_t *ipbind_default_server = NULL, *ipbind_localhost_server = NULL; -#ifdef PR_USE_IPV6 -static int ipv6_supported = TRUE; -#endif /* PR_USE_IPV6 */ - /* Server cleanup callback function */ static void server_cleanup_cb(void *conn) { *((conn_t **) conn) = NULL; @@ -464,7 +460,7 @@ /* Not found in binding list, and no DefaultServer, so see if it's the * loopback address */ - if (ipbind_localhost_server && pr_netaddr_loopback(addr)) + if (ipbind_localhost_server && pr_netaddr_is_loopback(addr)) return ipbind_localhost_server->ib_server; return NULL; @@ -863,7 +859,7 @@ */ if (!SocketBindTight) { #ifdef PR_USE_IPV6 - if (ipv6_supported) { + if (pr_netaddr_use_ipv6()) { pr_inet_set_default_family(NULL, AF_INET6); } else { @@ -907,7 +903,7 @@ if (serv->ServerPort) { if (!SocketBindTight) { #ifdef PR_USE_IPV6 - if (ipv6_supported) { + if (pr_netaddr_use_ipv6()) { pr_inet_set_default_family(NULL, AF_INET6); } else { @@ -973,7 +969,7 @@ /* Check to see whether we can actually create an IPv6 socket. */ sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { - ipv6_supported = FALSE; + pr_netaddr_disable_ipv6(); } else { close(sock); diff -urNad proftpd-dfsg-1.3.0~/src/dirtree.c proftpd-dfsg-1.3.0/src/dirtree.c --- proftpd-dfsg-1.3.0~/src/dirtree.c 2006-11-22 19:44:32.000000000 +0100 +++ proftpd-dfsg-1.3.0/src/dirtree.c 2006-11-22 19:44:46.000000000 +0100 @@ -2830,14 +2830,16 @@ const char *ipstr = pr_netaddr_get_ipstr(elts[i]); #ifdef PR_USE_IPV6 - char ipbuf[INET6_ADDRSTRLEN]; - if (pr_netaddr_get_family(elts[i]) == AF_INET) { + if (pr_netaddr_use_ipv6()) { + char *ipbuf = pcalloc(s->pool, INET6_ADDRSTRLEN); + if (pr_netaddr_get_family(elts[i]) == AF_INET) { - /* Create the bind record using the IPv4-mapped IPv6 version of - * this address. - */ - snprintf(ipbuf, sizeof(ipbuf), "::ffff:%s", ipstr); - ipstr = ipbuf; + /* Create the bind record using the IPv4-mapped IPv6 version of + * this address. + */ + snprintf(ipbuf, sizeof(ipbuf), "::ffff:%s", ipstr); + ipstr = ipbuf; + } } #endif /* PR_USE_IPV6 */ diff -urNad proftpd-dfsg-1.3.0~/src/inet.c proftpd-dfsg-1.3.0/src/inet.c --- proftpd-dfsg-1.3.0~/src/inet.c 2006-11-22 19:44:32.000000000 +0100 +++ proftpd-dfsg-1.3.0/src/inet.c 2006-11-22 19:44:46.000000000 +0100 @@ -209,7 +209,11 @@ * support is enabled), otherwise use IPv4. */ #ifdef PR_USE_IPV6 - addr_family = AF_INET6; + if (pr_netaddr_use_ipv6()) + addr_family = AF_INET6; + + else + addr_family = AF_INET; #else addr_family = AF_INET; #endif /* PR_USE_IPV6 */ @@ -292,7 +296,8 @@ pr_netaddr_set_sockaddr_any(&na); #if defined(PR_USE_IPV6) && defined(IPV6_V6ONLY) - if (addr_family == AF_INET6) { + if (pr_netaddr_use_ipv6() && + addr_family == AF_INET6) { int on = 0; # ifdef SOL_IP @@ -1019,7 +1024,11 @@ pr_netaddr_clear(&na); #ifdef PR_USE_IPV6 - pr_netaddr_set_family(&na, AF_INET6); + if (pr_netaddr_use_ipv6()) + pr_netaddr_set_family(&na, AF_INET6); + + else + pr_netaddr_set_family(&na, AF_INET); #else pr_netaddr_set_family(&na, AF_INET); #endif /* PR_USE_IPV6 */ @@ -1044,7 +1053,11 @@ /* "Reset" the pr_netaddr_t struct for the getpeername(2) call. */ #ifdef PR_USE_IPV6 - pr_netaddr_set_family(&na, AF_INET6); + if (pr_netaddr_use_ipv6()) + pr_netaddr_set_family(&na, AF_INET6); + + else + pr_netaddr_set_family(&na, AF_INET); #else pr_netaddr_set_family(&na, AF_INET); #endif /* PR_USE_IPV6 */ diff -urNad proftpd-dfsg-1.3.0~/src/main.c proftpd-dfsg-1.3.0/src/main.c --- proftpd-dfsg-1.3.0~/src/main.c 2006-11-22 19:44:45.000000000 +0100 +++ proftpd-dfsg-1.3.0/src/main.c 2006-11-22 19:44:46.000000000 +0100 @@ -2553,6 +2553,10 @@ "Print version number and exit" }, { "--version-status", "-vv", "Print extended version information and exit" }, + { "--ipv4", "-4", + "Support IPv4 connections only" }, + { "--ipv6", "-6", + "Support IPv6 connections" }, { NULL, NULL, NULL } }; @@ -2574,7 +2578,7 @@ int main(int argc, char *argv[], char **envp) { int optc, show_version = 0; - const char *cmdopts = "D:NVc:d:hlnp:qtv"; + const char *cmdopts = "D:NVc:d:hlnp:qtv46"; mode_t *main_umask = NULL; socklen_t peerlen; struct sockaddr peer; @@ -2658,6 +2662,10 @@ * --configtest * -v report version number * --version + * -4 support IPv4 connections only + * --ipv4 + * -6 support IPv6 connections + * --ipv6 */ opterr = 0; @@ -2755,6 +2763,12 @@ case 'h': show_usage(0); + case 4: + pr_netaddr_disable_ipv6(); + + case 6: + pr_netaddr_enable_ipv6(); + case '?': pr_log_pri(PR_LOG_ERR, "unknown option: %c", (char)optopt); show_usage(1); diff -urNad proftpd-dfsg-1.3.0~/src/netacl.c proftpd-dfsg-1.3.0/src/netacl.c --- proftpd-dfsg-1.3.0~/src/netacl.c 2006-11-22 19:44:45.000000000 +0100 +++ proftpd-dfsg-1.3.0/src/netacl.c 2006-11-22 19:44:46.000000000 +0100 @@ -172,19 +172,20 @@ #ifdef PR_USE_IPV6 case AF_INET6: { - if (acl->masklen > 128) { - errno = EINVAL; - return NULL; - - } else if (pr_netaddr_is_v4mappedv6(acl->addr) == TRUE && - acl->masklen > 32) { - - /* The admin may be trying to use IPv6-style masks on IPv4-mapped - * IPv6 addresses, which of course will not work as expected. - * If the mask is 32 bits or more, warn the admin. - */ - pr_log_pri(PR_LOG_WARNING, "warning: possibly using IPv6-style netmask on IPv4-mapped IPv6 address, which will not work as expected"); - break; + if (pr_netaddr_use_ipv6()) { + if (acl->masklen > 128) { + errno = EINVAL; + return NULL; + + } else if (pr_netaddr_is_v4mappedv6(acl->addr) == TRUE && + acl->masklen > 32) { + /* The admin may be trying to use IPv6-style masks on IPv4-mapped + * IPv6 addresses, which of course will not work as expected. + * If the mask is 32 bits or more, warn the admin. + */ + pr_log_pri(PR_LOG_WARNING, "warning: possibly using IPv6-style netmask on IPv4-mapped IPv6 address, which will not work as expected"); + break; + } } } #endif /* PR_USE_IPV6 */ @@ -194,7 +195,7 @@ } #ifdef PR_USE_IPV6 - } else if (strspn(aclstr, "0123456789ABCDEFabcdef.:") != strlen(aclstr)) { + } else if (pr_netaddr_use_ipv6() && strspn(aclstr, "0123456789ABCDEFabcdef.:") != strlen(aclstr)) { #else } else if (strspn(aclstr, "0123456789.") != strlen(aclstr)) { #endif /* PR_USE_IPV6 */ diff -urNad proftpd-dfsg-1.3.0~/src/netaddr.c proftpd-dfsg-1.3.0/src/netaddr.c --- proftpd-dfsg-1.3.0~/src/netaddr.c 2006-11-22 19:44:45.000000000 +0100 +++ proftpd-dfsg-1.3.0/src/netaddr.c 2006-11-22 19:44:46.000000000 +0100 @@ -43,6 +43,13 @@ /* Do reverse DNS lookups? */ static int reverse_dns = 1; +/* Use IPv6? */ +#ifdef PR_USE_IPV6 +static int use_ipv6 = TRUE; +#else +static int use_ipv6 = FALSE; +#endif /* PR_USE_IPV6 */ + /* Provide replacements for needed functions. */ #if !defined(HAVE_GETNAMEINFO) || defined(PR_USE_GETNAMEINFO) @@ -276,9 +283,6 @@ array_header **addrs) { struct sockaddr_in v4; -#ifdef PR_USE_IPV6 - struct sockaddr_in6 v6; -#endif /* PR_USE_IPV6 */ pr_netaddr_t *na = NULL; int res; @@ -300,23 +304,26 @@ na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t)); #ifdef PR_USE_IPV6 - memset(&v6, 0, sizeof(v6)); - v6.sin6_family = AF_INET6; + if (use_ipv6) { + struct sockaddr_in6 v6; + memset(&v6, 0, sizeof(v6)); + v6.sin6_family = AF_INET6; # ifdef SIN6_LEN - v6.sin6_len = sizeof(struct sockaddr_in6); + v6.sin6_len = sizeof(struct sockaddr_in6); # endif /* SIN6_LEN */ - res = pr_inet_pton(AF_INET6, name, &v6.sin6_addr); - if (res > 0) { - pr_netaddr_set_family(na, AF_INET6); - pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v6); - if (addrs) - *addrs = NULL; + res = pr_inet_pton(AF_INET6, name, &v6.sin6_addr); + if (res > 0) { + pr_netaddr_set_family(na, AF_INET6); + pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v6); + if (addrs) + *addrs = NULL; - pr_log_debug(DEBUG10, "'%s' resolved to IPv6 address %s", name, - pr_netaddr_get_ipstr(na)); - return na; + pr_log_debug(DEBUG10, "'%s' resolved to IPv6 address %s", name, + pr_netaddr_get_ipstr(na)); + return na; + } } #endif /* PR_USE_IPV6 */ @@ -377,7 +384,7 @@ } #ifdef PR_USE_IPV6 - if (addrs) { + if (use_ipv6 && addrs) { /* Do the call again, this time for IPv6 addresses. * * We make two separate getaddrinfo(3) calls, rather than one @@ -454,8 +461,10 @@ #ifdef PR_USE_IPV6 case AF_INET6: - na->na_addr.v6.sin6_family = AF_INET6; - break; + if (use_ipv6) { + na->na_addr.v6.sin6_family = AF_INET6; + break; + } #endif /* PR_USE_IPV6 */ default: @@ -483,7 +492,8 @@ #ifdef PR_USE_IPV6 case AF_INET6: - return sizeof(struct sockaddr_in6); + if (use_ipv6) + return sizeof(struct sockaddr_in6); #endif /* PR_USE_IPV6 */ } @@ -503,7 +513,8 @@ #ifdef PR_USE_IPV6 case AF_INET6: - return sizeof(struct in6_addr); + if (use_ipv6) + return sizeof(struct in6_addr); #endif /* PR_USE_IPV6 */ } @@ -523,7 +534,8 @@ #ifdef PR_USE_IPV6 case AF_INET6: - return (struct sockaddr *) &na->na_addr.v6; + if (use_ipv6) + return (struct sockaddr *) &na->na_addr.v6; #endif /* PR_USE_IPV6 */ } @@ -545,8 +557,10 @@ #ifdef PR_USE_IPV6 case AF_INET6: - memcpy(&(na->na_addr.v6), addr, sizeof(struct sockaddr_in6)); - return 0; + if (use_ipv6) { + memcpy(&(na->na_addr.v6), addr, sizeof(struct sockaddr_in6)); + return 0; + } #endif /* PR_USE_IPV6 */ } @@ -574,12 +588,14 @@ #ifdef PR_USE_IPV6 case AF_INET6: - na->na_addr.v6.sin6_family = AF_INET6; + if (use_ipv6) { + na->na_addr.v6.sin6_family = AF_INET6; #ifdef SIN6_LEN - na->na_addr.v6.sin6_len = sizeof(struct sockaddr_in6); + na->na_addr.v6.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - memcpy(&na->na_addr.v6.sin6_addr, &in6addr_any, sizeof(struct in6_addr)); - return 0; + memcpy(&na->na_addr.v6.sin6_addr, &in6addr_any, sizeof(struct in6_addr)); + return 0; + } #endif /* PR_USE_IPV6 */ } @@ -599,7 +615,8 @@ #ifdef PR_USE_IPV6 case AF_INET6: - return (void *) &na->na_addr.v6.sin6_addr; + if (use_ipv6) + return (void *) &na->na_addr.v6.sin6_addr; #endif /* PR_USE_IPV6 */ } @@ -619,7 +636,8 @@ #ifdef PR_USE_IPV6 case AF_INET6: - return na->na_addr.v6.sin6_port; + if (use_ipv6) + return na->na_addr.v6.sin6_port; #endif /* PR_USE_IPV6 */ } @@ -640,8 +658,10 @@ #ifdef PR_USE_IPV6 case AF_INET6: - na->na_addr.v6.sin6_port = port; - return 0; + if (use_ipv6) { + na->na_addr.v6.sin6_port = port; + return 0; + } #endif /* PR_USE_IPV6 */ } @@ -724,11 +744,13 @@ #ifdef PR_USE_IPV6 case AF_INET6: - res = memcmp(&a->na_addr.v6.sin6_addr, &b->na_addr.v6.sin6_addr, - sizeof(struct in6_addr)); - if (tmp_pool); - destroy_pool(tmp_pool); - return res; + if (use_ipv6) { + res = memcmp(&a->na_addr.v6.sin6_addr, &b->na_addr.v6.sin6_addr, + sizeof(struct in6_addr)); + if (tmp_pool) + destroy_pool(tmp_pool); + return res; + } #endif /* PR_USE_IPV6 */ } @@ -821,15 +843,17 @@ #ifdef PR_USE_IPV6 case AF_INET6: { - /* Make sure that the given number of bits is not more than supported - * for IPv6 addresses (128). - */ - if (bitlen > 128) { - errno = EINVAL; - return -1; - } + if (use_ipv6) { + /* Make sure that the given number of bits is not more than supported + * for IPv6 addresses (128). + */ + if (bitlen > 128) { + errno = EINVAL; + return -1; + } - break; + break; + } } #endif /* PR_USE_IPV6 */ @@ -1029,7 +1053,7 @@ #ifdef PR_USE_IPV6 case AF_INET6: - if (family == AF_INET6) { + if (use_ipv6 && family == AF_INET6) { for (checkaddr = hent->h_addr_list; *checkaddr; ++checkaddr) { if (memcmp(*checkaddr, inaddr, hent->h_length) == 0) { ok = TRUE; @@ -1090,7 +1114,7 @@ return NULL; } -int pr_netaddr_loopback(const pr_netaddr_t *na) { +int pr_netaddr_is_loopback(const pr_netaddr_t *na) { if (!na) { errno = EINVAL; return -1; @@ -1103,7 +1127,6 @@ #ifdef PR_USE_IPV6 case AF_INET6: - /* XXX *sigh* Different platforms implement the IN6_IS_ADDR macros * differently. For example, on Linux, those macros expect to operate * on s6_addr32, while on Solaris, the macros operate on struct in6_addr. @@ -1175,7 +1198,11 @@ return -1; #ifdef PR_USE_IPV6 - case AF_INET6: + case AF_INET6: { + if (!use_ipv6) { + errno = EINVAL; + return -1; + } # ifndef LINUX return IN6_IS_ADDR_V4MAPPED( @@ -1184,6 +1211,7 @@ return IN6_IS_ADDR_V4MAPPED( ((struct in6_addr *) pr_netaddr_get_inaddr(na))->s6_addr32); # endif + } #endif /* PR_USE_IPV6 */ } @@ -1234,3 +1262,22 @@ sstrncpy(sess_remote_name, session.c->remote_name, sizeof(sess_remote_name)); have_sess_remote_addr = TRUE; } + +unsigned char pr_netaddr_use_ipv6(void) { + if (use_ipv6) + return TRUE; + + return FALSE; +} + +void pr_netaddr_disable_ipv6(void) { +#ifdef PR_USE_IPV6 + use_ipv6 = 0; +#endif /* PR_USE_IPV6 */ +} + +void pr_netaddr_enable_ipv6(void) { +#ifdef PR_USE_IPV6 + use_ipv6 = 1; +#endif /* PR_USE_IPV6 */ +}