summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/conf-tokens.c1
-rw-r--r--src/conf-tokens.h1
-rw-r--r--src/conf.c8
-rw-r--r--src/conf.h1
-rw-r--r--src/conns.c6
-rw-r--r--src/conns.h6
-rw-r--r--src/reqs.c18
-rw-r--r--src/sock.c16
-rw-r--r--src/sock.h3
9 files changed, 47 insertions, 13 deletions
diff --git a/src/conf-tokens.c b/src/conf-tokens.c
index 4ca38e3..edfcedf 100644
--- a/src/conf-tokens.c
+++ b/src/conf-tokens.c
@@ -59,6 +59,7 @@ config_directive_find (register const char *str, register size_t len)
{"addheader", CD_addheader},
{"maxrequestsperchild", CD_maxrequestsperchild},
{"bindipv4mapped", CD_bindipv4mapped},
+ {"bindipv6mapped", CD_bindipv6mapped},
};
for(i=0;i<sizeof(wordlist)/sizeof(wordlist[0]);++i) {
diff --git a/src/conf-tokens.h b/src/conf-tokens.h
index 7188dbf..e99f0de 100644
--- a/src/conf-tokens.h
+++ b/src/conf-tokens.h
@@ -43,6 +43,7 @@ CD_reversepath,
CD_upstream,
CD_loglevel,
CD_bindipv4mapped,
+CD_bindipv6mapped,
};
struct config_directive_entry { const char* name; enum config_directive value; };
diff --git a/src/conf.c b/src/conf.c
index 7a23245..c883da1 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -118,6 +118,7 @@ static HANDLE_FUNC (handle_basicauth);
static HANDLE_FUNC (handle_anonymous);
static HANDLE_FUNC (handle_bind);
static HANDLE_FUNC (handle_bindipv4mapped);
+static HANDLE_FUNC (handle_bindipv6mapped);
static HANDLE_FUNC (handle_bindsame);
static HANDLE_FUNC (handle_connectport);
static HANDLE_FUNC (handle_defaulterrorfile);
@@ -218,6 +219,7 @@ struct {
handle_deny),
STDCONF (bind, "(" IP "|" IPV6 ")", handle_bind),
STDCONF (bindipv4mapped, "(" IPV6 ")", handle_bindipv4mapped),
+ STDCONF (bindipv6mapped, "(" IP ")", handle_bindipv6mapped),
/* other */
STDCONF (basicauth, ALNUM WS ALNUM, handle_basicauth),
STDCONF (errorfile, INT WS STR, handle_errorfile),
@@ -292,6 +294,7 @@ void free_config (struct config_s *conf)
safefree (conf->user);
safefree (conf->group);
safefree (conf->bind_ipv4mapped);
+ safefree (conf->bind_ipv6mapped);
stringlist_free(conf->basicauth_list);
stringlist_free(conf->listen_addrs);
stringlist_free(conf->bind_addrs);
@@ -853,6 +856,11 @@ static HANDLE_FUNC (handle_bindipv4mapped)
return set_string_arg(&conf->bind_ipv4mapped, line, &match[2]);
}
+static HANDLE_FUNC (handle_bindipv6mapped)
+{
+ return set_string_arg(&conf->bind_ipv6mapped, line, &match[2]);
+}
+
static HANDLE_FUNC (handle_errorfile)
{
/*
diff --git a/src/conf.h b/src/conf.h
index a7c5a0c..572aeb1 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -71,6 +71,7 @@ struct config_s {
sblist *bind_addrs;
unsigned int bindsame;
char *bind_ipv4mapped;
+ char *bind_ipv6mapped;
/*
* The configured name to use in the HTTP "Via" header field.
diff --git a/src/conns.c b/src/conns.c
index 921cdf6..feac522 100644
--- a/src/conns.c
+++ b/src/conns.c
@@ -40,7 +40,7 @@ void conn_struct_init(struct conn_s *connptr) {
int conn_init_contents (struct conn_s *connptr, const char *ipaddr,
const char *sock_ipaddr,
- const char *sock_ipaddr_mapped)
+ const char *sock_ipaddr_alt)
{
struct buffer_s *cbuffer, *sbuffer;
@@ -60,8 +60,8 @@ int conn_init_contents (struct conn_s *connptr, const char *ipaddr,
connptr->server_ip_addr = (sock_ipaddr ?
safestrdup (sock_ipaddr) : NULL);
- connptr->server_ip_addr_mapped = (sock_ipaddr_mapped ?
- safestrdup (sock_ipaddr_mapped) : NULL);
+ connptr->server_ip_addr_alt = (sock_ipaddr_alt ?
+ safestrdup (sock_ipaddr_alt) : NULL);
connptr->client_ip_addr = safestrdup (ipaddr);
update_stats (STAT_OPEN);
diff --git a/src/conns.h b/src/conns.h
index c702fed..36082f2 100644
--- a/src/conns.h
+++ b/src/conns.h
@@ -62,9 +62,9 @@ struct conn_s {
char *server_ip_addr;
/*
- * Store the server's mapped IP (for BindSame)
+ * Store the server's alternative IP (for BindIPv4/6Mapped)
*/
- char *server_ip_addr_mapped;
+ char *server_ip_addr_alt;
/*
* Store the client's IP information
@@ -99,7 +99,7 @@ extern void conn_struct_init(struct conn_s *connptr);
/* second stage initializiation, sets up buffers and connection details */
extern int conn_init_contents (struct conn_s *connptr, const char *ipaddr,
const char *sock_ipaddr,
- const char *sock_ipaddr_mapped);
+ const char *sock_ipaddr_alt);
extern void conn_destroy_contents (struct conn_s *connptr);
#endif
diff --git a/src/reqs.c b/src/reqs.c
index f5c804a..da23405 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -1530,7 +1530,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
orderedmap hashofheaders = NULL;
char sock_ipaddr[IP_LENGTH];
- char sock_ipaddr_mapped[IP_LENGTH];
+ char sock_ipaddr_alt[IP_LENGTH]="";
char peer_ipaddr[IP_LENGTH];
getpeer_information (addr, peer_ipaddr, sizeof(peer_ipaddr));
@@ -1538,8 +1538,16 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
if (config->bindsame)
getsock_ip (fd, sock_ipaddr);
- if (config->bind_ipv4mapped)
- getmapped_ip (config->bind_ipv4mapped, sock_ipaddr, sock_ipaddr_mapped);
+ switch (SOCKADDR_UNION_AF(addr)) {
+ case AF_INET:
+ if (config->bind_ipv4mapped)
+ getmapped_ipv6 (config->bind_ipv4mapped, sock_ipaddr, sock_ipaddr_alt);
+ break;
+ case AF_INET6:
+ if (config->bind_ipv6mapped)
+ getmapped_ipv4 (config->bind_ipv6mapped, sock_ipaddr, sock_ipaddr_alt);
+ break;
+ }
log_message (LOG_CONN, config->bindsame ?
"Connect (file descriptor %d): %s at [%s]" :
@@ -1548,7 +1556,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr)
if(!conn_init_contents (connptr, peer_ipaddr,
config->bindsame ? sock_ipaddr : NULL,
- config->bind_ipv4mapped ? sock_ipaddr_mapped : NULL)) {
+ sock_ipconfig_alt[0] ? sock_ipaddr_alt : NULL)) {
close (fd);
return;
}
@@ -1689,7 +1697,7 @@ e401:
} else {
connptr->server_fd = opensock (request->host, request->port,
connptr->server_ip_addr,
- connptr->server_ip_addr_mapped);
+ connptr->server_ip_addr_alt);
if (connptr->server_fd < 0) {
indicate_http_error (connptr, 500, "Unable to connect",
"detail",
diff --git a/src/sock.c b/src/sock.c
index f9d6a89..b11babb 100644
--- a/src/sock.c
+++ b/src/sock.c
@@ -385,11 +385,25 @@ int getsock_ip (int fd, char *ipaddr)
return 0;
}
-int getmapped_ip (const char *ipv4mapped_conf, const char *ipaddr, char *ipaddr_mapped)
+int getmapped_ipv4 (const char *ipv6mapped_conf, const char *ipaddr, char *ipaddr_mapped)
+{
+ struct in6_addr addr6;
+ struct in_addr addr;
+
+ memset(&addr6, 0, sizeof(addr6));
+ if ( inet_pton(AF_INET6, ipaddr, &addr6) < 0 )
+ return -1;
+
+ memcpy(&addr, addr6.s6_addr + 12, sizeof(&addr));
+ return inet_ntop(AF_INET, &addr, ipaddr_mapped, IP_LENGTH) == NULL ? -1 : 0;
+}
+
+int getmapped_ipv6 (const char *ipv4mapped_conf, const char *ipaddr, char *ipaddr_mapped)
{
memset(ipaddr_mapped, 0, IP_LENGTH);
strncpy(ipaddr_mapped, ipv4mapped_conf, IP_LENGTH-1);
strncat(ipaddr_mapped, ipaddr, IP_LENGTH-1-strlen(ipaddr_mapped));
+ return 0;
}
diff --git a/src/sock.h b/src/sock.h
index 15ab4df..170dc3c 100644
--- a/src/sock.h
+++ b/src/sock.h
@@ -57,7 +57,8 @@ extern int socket_nonblocking (int sock);
extern int socket_blocking (int sock);
extern int getsock_ip (int fd, char *ipaddr);
-extern int getmapped_ip (const char *ipv4mapped_conf, const char *ipaddr, char *ipaddr_mapped);
+extern int getmapped_ipv6 (const char *ipv4mapped_conf, const char *ipaddr, char *ipaddr_mapped);
+extern int getmapped_ipv4 (const char *ipv6mapped_conf, const char *ipaddr, char *ipaddr_mapped);
extern void getpeer_information (union sockaddr_union *addr, char *ipaddr, size_t ipaddr_len);
#endif