diff options
-rw-r--r-- | doc/tinyproxy.conf | 6 | ||||
-rw-r--r-- | src/conns.c | 8 | ||||
-rw-r--r-- | src/conns.h | 10 | ||||
-rw-r--r-- | src/grammar.y | 9 | ||||
-rw-r--r-- | src/reqs.c | 29 | ||||
-rw-r--r-- | src/scanner.l | 3 | ||||
-rw-r--r-- | src/sock.c | 48 | ||||
-rw-r--r-- | src/sock.h | 9 | ||||
-rw-r--r-- | src/tinyproxy.h | 3 |
9 files changed, 93 insertions, 32 deletions
diff --git a/doc/tinyproxy.conf b/doc/tinyproxy.conf index d8af086..b1cc5ce 100644 --- a/doc/tinyproxy.conf +++ b/doc/tinyproxy.conf @@ -34,6 +34,12 @@ Port 8888 #Bind 192.168.0.1 # +# BindSame: If enabled, tinyproxy will bind the outgoing connection to the +# ip address of the incomming connection. +# +#BindSame yes + +# # Timeout: The maximum number of seconds of inactivity a connection is # allowed to have before it is closed by tinyproxy. # diff --git a/src/conns.c b/src/conns.c index c7091a3..c94b245 100644 --- a/src/conns.c +++ b/src/conns.c @@ -1,4 +1,4 @@ -/* $Id: conns.c,v 1.21 2004-02-13 21:27:42 rjkaes Exp $ +/* $Id: conns.c,v 1.22 2004-04-27 18:53:14 rjkaes Exp $ * * Create and free the connection structure. One day there could be * other connection related tasks put here, but for now the header @@ -27,7 +27,8 @@ #include "stats.h" struct conn_s * -initialize_conn(int client_fd, const char* ipaddr, const char* string_addr) +initialize_conn(int client_fd, const char* ipaddr, const char* string_addr, + const char* sock_ipaddr) { struct conn_s *connptr; struct buffer_s *cbuffer, *sbuffer; @@ -71,6 +72,7 @@ initialize_conn(int client_fd, const char* ipaddr, const char* string_addr) /* There is _no_ content length initially */ connptr->content_length.server = connptr->content_length.client = -1; + connptr->server_ip_addr = sock_ipaddr ? safestrdup(sock_ipaddr) : 0; connptr->client_ip_addr = safestrdup(ipaddr); connptr->client_string_addr = safestrdup(string_addr); @@ -122,6 +124,8 @@ destroy_conn(struct conn_s *connptr) if (connptr->error_string) safefree(connptr->error_string); + if (connptr->server_ip_addr) + safefree(connptr->server_ip_addr); if (connptr->client_ip_addr) safefree(connptr->client_ip_addr); if (connptr->client_string_addr) diff --git a/src/conns.h b/src/conns.h index 5d0422a..8b6f69e 100644 --- a/src/conns.h +++ b/src/conns.h @@ -1,4 +1,4 @@ -/* $Id: conns.h,v 1.16 2004-01-26 19:11:51 rjkaes Exp $ +/* $Id: conns.h,v 1.17 2004-04-27 18:53:14 rjkaes Exp $ * * See 'conns.c' for a detailed description. * @@ -54,6 +54,11 @@ struct conn_s { } content_length; /* + * Store the server's IP (for BindSame) + */ + char* server_ip_addr; + + /* * Store the client's IP and hostname information */ char* client_ip_addr; @@ -79,7 +84,8 @@ struct conn_s { * Functions for the creation and destruction of a connection structure. */ extern struct conn_s* initialize_conn(int client_fd, const char* ipaddr, - const char* string_addr); + const char* string_addr, + const char* sock_ipaddr); extern void destroy_conn(struct conn_s *connptr); #endif diff --git a/src/grammar.y b/src/grammar.y index 9f3a74c..72d51b8 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -1,4 +1,4 @@ -/* $Id: grammar.y,v 1.24 2004-01-26 19:11:51 rjkaes Exp $ +/* $Id: grammar.y,v 1.25 2004-04-27 18:53:14 rjkaes Exp $ * * This is the grammar for tinyproxy's configuration file. It needs to be * in sync with scanner.l. If you know more about yacc and lex than I do @@ -51,7 +51,7 @@ int yylex(void); %token KW_FILTER_CASESENSITIVE %token KW_UPSTREAM %token KW_REVERSEPATH KW_REVERSEONLY KW_REVERSEMAGIC KW_REVERSEBASEURL -%token KW_CONNECTPORT KW_BIND +%token KW_CONNECTPORT KW_BIND KW_BINDSAME %token KW_STATHOST %token KW_ALLOW KW_DENY %token KW_ERRORPAGE KW_DEFAULT_ERRORPAGE @@ -250,6 +250,11 @@ statement log_message(LOG_WARNING, "The 'Bind' directive can not be used with transparent proxy support. Ignoring the directive."); #endif } + | KW_BINDSAME yesno + { + log_message(LOG_INFO, "Binding outgoing connections to incoming IP"); + config.bindsame = $2; + } | KW_VIA_PROXY_NAME string { log_message(LOG_INFO, "Setting \"Via\" proxy name to: %s", $2); @@ -1,4 +1,4 @@ -/* $Id: reqs.c,v 1.111 2004-02-13 21:27:42 rjkaes Exp $ +/* $Id: reqs.c,v 1.112 2004-04-27 18:53:14 rjkaes Exp $ * * This is where all the work in tinyproxy is actually done. Incoming * connections have a new child created for them. The child then @@ -645,7 +645,8 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders) free_request_struct(request); return NULL; - } + } else if (ret == 2) + request->protocol[0] = 0; /* * FIXME: We need to add code for the simple HTTP/0.9 style GET @@ -1111,7 +1112,7 @@ remove_connection_headers(hashmap_t hashofheaders) /* Advance ptr to the next token */ ptr += strlen(ptr) + 1; - while (*ptr == '\0') + while (ptr < data + len && *ptr == '\0') ptr++; } @@ -1609,7 +1610,7 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request) } connptr->server_fd = - opensock(cur_upstream->host, cur_upstream->port); + opensock(cur_upstream->host, cur_upstream->port, connptr->server_ip_addr); if (connptr->server_fd < 0) { log_message(LOG_WARNING, @@ -1674,15 +1675,22 @@ handle_connection(int fd) struct request_s *request = NULL; hashmap_t hashofheaders = NULL; - char peer_ipaddr[PEER_IP_LENGTH]; - char peer_string[PEER_STRING_LENGTH]; + char sock_ipaddr[IP_LENGTH]; + char peer_ipaddr[IP_LENGTH]; + char peer_string[HOSTNAME_LENGTH]; getpeer_information(fd, peer_ipaddr, peer_string); - log_message(LOG_CONN, "Connect (file descriptor %d): %s [%s]", - fd, peer_string, peer_ipaddr); + if (config.bindsame) + getsock_ip(fd, sock_ipaddr); + + log_message(LOG_CONN, config.bindsame ? + "Connect (file descriptor %d): %s [%s] at [%s]" : + "Connect (file descriptor %d): %s [%s]", + fd, peer_string, peer_ipaddr, sock_ipaddr); - connptr = initialize_conn(fd, peer_ipaddr, peer_string); + connptr = initialize_conn(fd, peer_ipaddr, peer_string, + config.bindsame ? sock_ipaddr : 0); if (!connptr) { close(fd); return; @@ -1748,7 +1756,8 @@ handle_connection(int fd) goto send_error; } } else { - connptr->server_fd = opensock(request->host, request->port); + connptr->server_fd = opensock(request->host, request->port, + connptr->server_ip_addr); if (connptr->server_fd < 0) { indicate_http_error(connptr, 500, "Unable to connect", "detail", PACKAGE " was unable to connect to the remote web server.", diff --git a/src/scanner.l b/src/scanner.l index 8418ca0..3107b31 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -1,4 +1,4 @@ -/* $Id: scanner.l,v 1.23 2004-01-26 19:11:51 rjkaes Exp $ +/* $Id: scanner.l,v 1.24 2004-04-27 18:53:14 rjkaes Exp $ * * This builds the scanner for the tinyproxy configuration file. This * file needs to stay in sync with grammar.y. If someone knows lex and yacc @@ -58,6 +58,7 @@ static struct keyword keywords[] = { { "deny", KW_DENY }, { "connectport", KW_CONNECTPORT }, { "bind", KW_BIND }, + { "bindsame", KW_BINDSAME }, { "viaproxyname", KW_VIA_PROXY_NAME }, { "stathost", KW_STATHOST }, { "errorfile", KW_ERRORPAGE }, @@ -1,4 +1,4 @@ -/* $Id: sock.c,v 1.40 2004-02-18 20:18:53 rjkaes Exp $ +/* $Id: sock.c,v 1.41 2004-04-27 18:53:14 rjkaes Exp $ * * Sockets are created and destroyed here. When a new connection comes in from * a client, we need to copy the socket and the create a second socket to the @@ -71,7 +71,7 @@ bind_socket(int sockfd, const char* addr) * independent implementation (mostly for IPv4 and IPv6 addresses.) */ int -opensock(const char* host, int port) +opensock(const char* host, int port, const char* bind_to) { int sockfd, n; struct addrinfo hints, *res, *ressave; @@ -100,7 +100,12 @@ opensock(const char* host, int port) continue; /* ignore this one */ /* Bind to the specified address */ - if (config.bind_address) { + if (bind_to) { + if (bind_socket(sockfd, bind_to) < 0) { + close(sockfd); + continue; /* can't bind, so try again */ + } + } else if (config.bind_address) { if (bind_socket(sockfd, config.bind_address) < 0) { close(sockfd); continue; /* can't bind, so try again */ @@ -199,13 +204,36 @@ listen_sock(uint16_t port, socklen_t* addrlen) } /* + * Takes a socket descriptor and returns the socket's IP address. + */ +int +getsock_ip(int fd, char* ipaddr) +{ + struct sockaddr_storage name; + int namelen = sizeof(name); + + assert(fd >= 0); + + if (getsockname(fd, (struct sockaddr *) &name, &namelen) != 0) { + log_message(LOG_ERR, "getsock_ip: getsockname() error: %s", + strerror(errno)); + return -1; + } + + if (get_ip_string((struct sockaddr *)&name, ipaddr, IP_LENGTH) == NULL) + return -1; + + return 0; +} + +/* * Return the peer's socket information. */ int getpeer_information(int fd, char* ipaddr, char* string_addr) { - struct sockaddr sa; - size_t salen = sizeof(struct sockaddr); + struct sockaddr_storage sa; + size_t salen = sizeof(sa); assert(fd >= 0); assert(ipaddr != NULL); @@ -213,17 +241,17 @@ getpeer_information(int fd, char* ipaddr, char* string_addr) /* Set the strings to default values */ ipaddr[0] = '\0'; - strlcpy(string_addr, "[unknown]", PEER_STRING_LENGTH); + strlcpy(string_addr, "[unknown]", HOSTNAME_LENGTH); /* Look up the IP address */ - if (getpeername(fd, &sa, &salen) != 0) + if (getpeername(fd, (struct sockaddr *)&sa, &salen) != 0) return -1; - if (get_ip_string(&sa, ipaddr, PEER_IP_LENGTH) == NULL) + if (get_ip_string((struct sockaddr *)&sa, ipaddr, IP_LENGTH) == NULL) return -1; /* Get the full host name */ - return getnameinfo(&sa, salen, - string_addr, PEER_STRING_LENGTH, + return getnameinfo((struct sockaddr *)&sa, salen, + string_addr, HOSTNAME_LENGTH, NULL, 0, 0); } @@ -1,4 +1,4 @@ -/* $Id: sock.h,v 1.12 2004-02-18 20:18:53 rjkaes Exp $ +/* $Id: sock.h,v 1.13 2004-04-27 18:53:14 rjkaes Exp $ * * See 'sock.c' for a detailed description. * @@ -20,17 +20,18 @@ #define TINYPROXY_SOCK_H /* The IP length is set to 48, since IPv6 can be that long */ -#define PEER_IP_LENGTH 48 -#define PEER_STRING_LENGTH 1024 +#define IP_LENGTH 48 +#define HOSTNAME_LENGTH 1024 #define MAXLINE (1024 * 4) -extern int opensock(const char* host, int port); +extern int opensock(const char* host, int port, const char* bind_to); extern int listen_sock(uint16_t port, socklen_t* addrlen); extern int socket_nonblocking(int sock); extern int socket_blocking(int sock); +extern int getsock_ip(int fd, char* ipaddr); extern int getpeer_information(int fd, char* ipaddr, char* string_addr); #endif diff --git a/src/tinyproxy.h b/src/tinyproxy.h index ad02120..256b9e7 100644 --- a/src/tinyproxy.h +++ b/src/tinyproxy.h @@ -1,4 +1,4 @@ -/* $Id: tinyproxy.h,v 1.43 2004-01-26 19:11:51 rjkaes Exp $ +/* $Id: tinyproxy.h,v 1.44 2004-04-27 18:53:14 rjkaes Exp $ * * See 'tinyproxy.c' for a detailed description. * @@ -80,6 +80,7 @@ struct config_s { char *pidpath; unsigned int idletimeout; char* bind_address; + unsigned int bindsame; /* * The configured name to use in the HTTP "Via" header field. |