diff options
-rw-r--r-- | etc/tinyproxy.conf.in | 7 | ||||
-rw-r--r-- | src/conf-tokens.c | 3 | ||||
-rw-r--r-- | src/conf-tokens.h | 1 | ||||
-rw-r--r-- | src/conf.c | 8 | ||||
-rw-r--r-- | src/conf.h | 1 | ||||
-rw-r--r-- | src/conns.c | 5 | ||||
-rw-r--r-- | src/conns.h | 8 | ||||
-rw-r--r-- | src/reqs.c | 12 | ||||
-rw-r--r-- | src/sock.c | 15 | ||||
-rw-r--r-- | src/sock.h | 3 |
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; }; @@ -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) { /* @@ -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 @@ -1368,7 +1368,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, @@ -1517,6 +1517,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)); @@ -1524,13 +1525,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; } @@ -1670,7 +1675,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", @@ -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. */ @@ -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 |