diff options
Diffstat (limited to 'src/reqs.c')
-rw-r--r-- | src/reqs.c | 93 |
1 files changed, 90 insertions, 3 deletions
@@ -61,9 +61,11 @@ #ifdef UPSTREAM_SUPPORT # define UPSTREAM_CONFIGURED() (config.upstream_list != NULL) # define UPSTREAM_HOST(host) upstream_get(host, config.upstream_list) +# define UPSTREAM_IS_HTTP(conn) (conn->upstream_proxy != NULL && conn->upstream_proxy->type == HTTP_TYPE) #else # define UPSTREAM_CONFIGURED() (0) # define UPSTREAM_HOST(host) (NULL) +# define UPSTREAM_IS_HTTP(up) (0) #endif /* @@ -853,10 +855,10 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders) /* * Don't send headers if there's already an error, if the request was * a stats request, or if this was a CONNECT method (unless upstream - * proxy is in use.) + * http proxy is in use.) */ if (connptr->server_fd == -1 || connptr->show_stats - || (connptr->connect_method && (connptr->upstream_proxy == NULL))) { + || (connptr->connect_method && ! UPSTREAM_IS_HTTP(connptr))) { log_message (LOG_INFO, "Not sending client headers to remote machine"); return 0; @@ -1265,6 +1267,88 @@ static void relay_connection (struct conn_s *connptr) return; } +static int +connect_to_upstream_proxy(struct conn_s *connptr, struct request_s *request) +{ + int len; + char buff[512]; /* won't use more than 7 + 255 */ + unsigned short port; + struct hostent *host; + struct upstream *cur_upstream = connptr->upstream_proxy; + + log_message(LOG_CONN, + "Established connection to %s proxy \"%s\" using file descriptor %d.", + proxy_type_name(cur_upstream->type), cur_upstream->host, connptr->server_fd); + + if (cur_upstream->type == SOCKS4_TYPE) { + + buff[0] = 4; /* socks version */ + buff[1] = 1; /* connect command */ + port = htons(request->port); + memcpy(&buff[2], &port, 2); /* dest port */ + host = gethostbyname(request->host); + memcpy(&buff[4], host->h_addr_list[0], 4); /* dest ip */ + buff[8] = 0; /* user */ + if (9 != safe_write(connptr->server_fd, buff, 9)) + return -1; + if (8 != safe_read(connptr->server_fd, buff, 8)) + return -1; + if (buff[0]!=0 || buff[1]!=90) + return -1; + + } else if (cur_upstream->type == SOCKS5_TYPE) { + + /* init */ + buff[0] = 5; /* socks version */ + buff[1] = 1; /* number of methods */ + buff[2] = 0; /* no auth method */ + if (3 != safe_write(connptr->server_fd, buff, 3)) + return -1; + if (2 != safe_read(connptr->server_fd, buff, 2)) + return -1; + if (buff[0]!=5 || buff[1]!=0) + return -1; + /* connect */ + buff[0] = 5; /* socks version */ + buff[1] = 1; /* connect */ + buff[2] = 0; /* reserved */ + buff[3] = 3; /* domainname */ + len=strlen(request->host); + if(len>255) + return -1; + buff[4] = len; /* length of domainname */ + memcpy(&buff[5], request->host, len); /* dest ip */ + port = htons(request->port); + memcpy(&buff[5+len], &port, 2); /* dest port */ + if (7+len != safe_write(connptr->server_fd, buff, 7+len)) + return -1; + if (4 != safe_read(connptr->server_fd, buff, 4)) + return -1; + if (buff[0]!=5 || buff[1]!=0) + return -1; + switch(buff[3]) { + case 1: len=4; break; /* ip v4 */ + case 4: len=16; break; /* ip v6 */ + case 3: /* domainname */ + if (1 != safe_read(connptr->server_fd, buff, 1)) + return -1; + len = buff[0]; /* max = 255 */ + break; + default: return -1; + } + if (2+len != safe_read(connptr->server_fd, buff, 2+len)) + return -1; + } else { + return -1; + } + + if (connptr->connect_method) + return 0; + + return establish_http_connection(connptr, request); +} + + /* * Establish a connection to the upstream proxy server. */ @@ -1308,6 +1392,9 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request) return -1; } + if (cur_upstream->type != HTTP_TYPE) + return connect_to_upstream_proxy(connptr, request); + log_message (LOG_CONN, "Established connection to upstream proxy \"%s\" " "using file descriptor %d.", @@ -1527,7 +1614,7 @@ void handle_connection (int fd) goto fail; } - if (!(connptr->connect_method && (connptr->upstream_proxy == NULL))) { + if (!connptr->connect_method || UPSTREAM_IS_HTTP(connptr)) { if (process_server_headers (connptr) < 0) { update_stats (STAT_BADCONN); goto fail; |