summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--etc/tinyproxy.conf.in7
-rw-r--r--src/conf-tokens.c3
-rw-r--r--src/conf-tokens.h1
-rw-r--r--src/conf.c8
-rw-r--r--src/conf.h1
-rw-r--r--src/conns.c5
-rw-r--r--src/conns.h8
-rw-r--r--src/reqs.c12
-rw-r--r--src/sock.c15
-rw-r--r--src/sock.h3
10 files changed, 54 insertions, 9 deletions
diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in
index 06f5480..5a170c2 100644
--- a/etc/tinyproxy.conf.in
+++ b/etc/tinyproxy.conf.in
@@ -43,6 +43,13 @@ Port 8888
#BindSame yes
#
+# BindIPv4Mapped: If enabled, tinyproxy will bind the outgoing IPv6
+# connection to the IPv4 address of the incoming connection using
+# the mapping.
+#
+#BindIPv4Mapped 2001:0db8::ffff:0:0
+
+#
# Timeout: The maximum number of seconds of inactivity a connection is
# allowed to have before it is closed by tinyproxy.
#
diff --git a/src/conf-tokens.c b/src/conf-tokens.c
index bad7013..4ca38e3 100644
--- a/src/conf-tokens.c
+++ b/src/conf-tokens.c
@@ -57,7 +57,8 @@ config_directive_find (register const char *str, register size_t len)
{"logfile", CD_logfile},
{"basicauth", CD_basicauth},
{"addheader", CD_addheader},
- {"maxrequestsperchild", CD_maxrequestsperchild}
+ {"maxrequestsperchild", CD_maxrequestsperchild},
+ {"bindipv4mapped", CD_bindipv4mapped},
};
for(i=0;i<sizeof(wordlist)/sizeof(wordlist[0]);++i) {
diff --git a/src/conf-tokens.h b/src/conf-tokens.h
index d9f03cd..7188dbf 100644
--- a/src/conf-tokens.h
+++ b/src/conf-tokens.h
@@ -42,6 +42,7 @@ CD_reversemagic,
CD_reversepath,
CD_upstream,
CD_loglevel,
+CD_bindipv4mapped,
};
struct config_directive_entry { const char* name; enum config_directive value; };
diff --git a/src/conf.c b/src/conf.c
index 1a78816..7a23245 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -117,6 +117,7 @@ static HANDLE_FUNC (handle_allow);
static HANDLE_FUNC (handle_basicauth);
static HANDLE_FUNC (handle_anonymous);
static HANDLE_FUNC (handle_bind);
+static HANDLE_FUNC (handle_bindipv4mapped);
static HANDLE_FUNC (handle_bindsame);
static HANDLE_FUNC (handle_connectport);
static HANDLE_FUNC (handle_defaulterrorfile);
@@ -216,6 +217,7 @@ struct {
STDCONF (deny, "(" "(" IPMASK "|" IPV6MASK ")" "|" ALNUM ")",
handle_deny),
STDCONF (bind, "(" IP "|" IPV6 ")", handle_bind),
+ STDCONF (bindipv4mapped, "(" IPV6 ")", handle_bindipv4mapped),
/* other */
STDCONF (basicauth, ALNUM WS ALNUM, handle_basicauth),
STDCONF (errorfile, INT WS STR, handle_errorfile),
@@ -289,6 +291,7 @@ void free_config (struct config_s *conf)
safefree (conf->stathost);
safefree (conf->user);
safefree (conf->group);
+ safefree (conf->bind_ipv4mapped);
stringlist_free(conf->basicauth_list);
stringlist_free(conf->listen_addrs);
stringlist_free(conf->bind_addrs);
@@ -845,6 +848,11 @@ static HANDLE_FUNC (handle_listen)
return 0;
}
+static HANDLE_FUNC (handle_bindipv4mapped)
+{
+ return set_string_arg(&conf->bind_ipv4mapped, line, &match[2]);
+}
+
static HANDLE_FUNC (handle_errorfile)
{
/*
diff --git a/src/conf.h b/src/conf.h
index 9914049..a7c5a0c 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -70,6 +70,7 @@ struct config_s {
unsigned int idletimeout;
sblist *bind_addrs;
unsigned int bindsame;
+ char *bind_ipv4mapped;
/*
* The configured name to use in the HTTP "Via" header field.
diff --git a/src/conns.c b/src/conns.c
index 19aaa49..921cdf6 100644
--- a/src/conns.c
+++ b/src/conns.c
@@ -39,7 +39,8 @@ 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,
+ const char *sock_ipaddr_mapped)
{
struct buffer_s *cbuffer, *sbuffer;
@@ -59,6 +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->client_ip_addr = safestrdup (ipaddr);
update_stats (STAT_OPEN);
diff --git a/src/conns.h b/src/conns.h
index 9618efb..c702fed 100644
--- a/src/conns.h
+++ b/src/conns.h
@@ -62,6 +62,11 @@ struct conn_s {
char *server_ip_addr;
/*
+ * Store the server's mapped IP (for BindSame)
+ */
+ char *server_ip_addr_mapped;
+
+ /*
* Store the client's IP information
*/
char *client_ip_addr;
@@ -93,7 +98,8 @@ 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,
+ const char *sock_ipaddr_mapped);
extern void conn_destroy_contents (struct conn_s *connptr);
#endif
diff --git a/src/reqs.c b/src/reqs.c
index 977af6b..f5c804a 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -1381,7 +1381,7 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
connptr->server_fd =
opensock (cur_upstream->host, cur_upstream->port,
- connptr->server_ip_addr);
+ connptr->server_ip_addr, NULL);
if (connptr->server_fd < 0) {
log_message (LOG_WARNING,
@@ -1530,6 +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 peer_ipaddr[IP_LENGTH];
getpeer_information (addr, peer_ipaddr, sizeof(peer_ipaddr));
@@ -1537,13 +1538,17 @@ 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);
+
log_message (LOG_CONN, config->bindsame ?
"Connect (file descriptor %d): %s at [%s]" :
"Connect (file descriptor %d): %s",
fd, peer_ipaddr, sock_ipaddr);
if(!conn_init_contents (connptr, peer_ipaddr,
- config->bindsame ? sock_ipaddr : NULL)) {
+ config->bindsame ? sock_ipaddr : NULL,
+ config->bind_ipv4mapped ? sock_ipaddr_mapped : NULL)) {
close (fd);
return;
}
@@ -1683,7 +1688,8 @@ e401:
}
} else {
connptr->server_fd = opensock (request->host, request->port,
- connptr->server_ip_addr);
+ connptr->server_ip_addr,
+ connptr->server_ip_addr_mapped);
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 70169a6..f9d6a89 100644
--- a/src/sock.c
+++ b/src/sock.c
@@ -113,7 +113,7 @@ bind_socket_list (int sockfd, sblist *addresses, int family)
* the getaddrinfo() library function, which allows for a protocol
* independent implementation (mostly for IPv4 and IPv6 addresses.)
*/
-int opensock (const char *host, int port, const char *bind_to)
+int opensock (const char *host, int port, const char *bind_to, const char *bind_to_alt)
{
int sockfd, n;
struct addrinfo hints, *res, *ressave;
@@ -151,7 +151,10 @@ int opensock (const char *host, int port, const char *bind_to)
/* Bind to the specified address */
if (bind_to) {
if (bind_socket (sockfd, bind_to,
- res->ai_family) < 0) {
+ res->ai_family) < 0 &&
+ (!bind_to_alt ||
+ bind_socket (sockfd, bind_to_alt,
+ res->ai_family) < 0)) {
close (sockfd);
continue; /* can't bind, so try again */
}
@@ -382,6 +385,14 @@ int getsock_ip (int fd, char *ipaddr)
return 0;
}
+int getmapped_ip (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 the peer's socket information.
*/
diff --git a/src/sock.h b/src/sock.h
index aee5bf5..15ab4df 100644
--- a/src/sock.h
+++ b/src/sock.h
@@ -50,13 +50,14 @@ union sockaddr_union {
struct sockaddr_in6 v6;
};
-extern int opensock (const char *host, int port, const char *bind_to);
+extern int opensock (const char *host, int port, const char *bind_to, const char *bind_to_alt);
extern int listen_sock (const char *addr, uint16_t port, sblist* listen_fds);
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 void getpeer_information (union sockaddr_union *addr, char *ipaddr, size_t ipaddr_len);
#endif