summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/tinyproxy.conf6
-rw-r--r--src/conns.c8
-rw-r--r--src/conns.h10
-rw-r--r--src/grammar.y9
-rw-r--r--src/reqs.c29
-rw-r--r--src/scanner.l3
-rw-r--r--src/sock.c48
-rw-r--r--src/sock.h9
-rw-r--r--src/tinyproxy.h3
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);
diff --git a/src/reqs.c b/src/reqs.c
index e03d6c4..d577867 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -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 },
diff --git a/src/sock.c b/src/sock.c
index 7380b23..265c03d 100644
--- a/src/sock.c
+++ b/src/sock.c
@@ -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);
}
diff --git a/src/sock.h b/src/sock.h
index 78191ea..b0c1a96 100644
--- a/src/sock.h
+++ b/src/sock.h
@@ -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.