============================================================ --- src/HttpHeader.c f130fccd6139140980f19965058577fb573780f7 +++ src/HttpHeader.c ad0e2fa0c182a0de43098501794c580de94bcd8d @@ -105,6 +105,7 @@ {"Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr}, {"Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr}, {"Proxy-Connection", HDR_PROXY_CONNECTION, ftStr}, + {"Proxy-support", HDR_PROXY_SUPPORT, ftStr}, {"Public", HDR_PUBLIC, ftStr}, {"Range", HDR_RANGE, ftPRange}, {"Referer", HDR_REFERER, ftStr}, @@ -151,6 +152,7 @@ HDR_IF_MATCH, HDR_IF_NONE_MATCH, HDR_LINK, HDR_PRAGMA, HDR_PROXY_CONNECTION, + HDR_PROXY_SUPPORT, HDR_TRANSFER_ENCODING, HDR_UPGRADE, HDR_VARY, ============================================================ --- src/client_side.c 612eaa9339b03fb38a570b1f7c846f2da9d19a50 +++ src/client_side.c aeb1c49f1a704cceb4928f31ac6df0b91c200cad @@ -373,6 +373,7 @@ new_request->http_ver = old_request->http_ver; httpHeaderAppend(&new_request->header, &old_request->header); new_request->client_addr = old_request->client_addr; + new_request->client_port = old_request->client_port; new_request->my_addr = old_request->my_addr; new_request->my_port = old_request->my_port; new_request->flags = old_request->flags; @@ -1032,7 +1033,7 @@ if (request->range) request->flags.range = 1; } - if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION)) + if ((httpHeaderHas(req_hdr, HDR_AUTHORIZATION)) || (request->flags.pinned)) request->flags.auth = 1; if (request->login[0] != '\0') request->flags.auth = 1; @@ -1442,8 +1443,12 @@ (value[4] == '\0' || value[4] == ' ')) || (strncasecmp(value, "Negotiate", 9) == 0 && - (value[9] == '\0' || value[9] == ' '))) - httpHeaderDelAt(hdr, pos); + (value[9] == '\0' || value[9] == ' '))) { + httpHeaderPutStr(hdr, HDR_PROXY_SUPPORT, "Session-Based-Authentication"); + httpHeaderPutStr(hdr, HDR_CONNECTION, "Proxy-support"); + request->flags.pinned=1; + break; + } } } } @@ -3202,6 +3207,7 @@ safe_free(http->log_uri); http->log_uri = xstrdup(urlCanonicalClean(request)); request->client_addr = conn->peer.sin_addr; + request->client_port = conn->peer.sin_port; request->my_addr = conn->me.sin_addr; request->my_port = ntohs(conn->me.sin_port); request->http_ver = http->http_ver; ============================================================ --- src/enums.h 6689def91d90a86446f75e526b7a15306ac61594 +++ src/enums.h d3225c7b17f9312bef8509d7dd1284df1f0fcf98 @@ -245,6 +245,7 @@ #if X_ACCELERATOR_VARY HDR_X_ACCELERATOR_VARY, #endif + HDR_PROXY_SUPPORT, HDR_OTHER, HDR_ENUM_END } http_hdr_type; ============================================================ --- src/forward.c eabf7a764371d5d1f1de54c194248c210bec17b5 +++ src/forward.c bde01cf37e23444aea4910eed79e76d3371277fb @@ -143,6 +150,8 @@ return 0; if (fwdState->request->flags.body_sent) return 0; + if (fwdState->request->flags.pinned) + return 0; return 1; } @@ -350,6 +359,14 @@ int ftimeout = Config.Timeout.forward - (squid_curtime - fwdState->start); struct in_addr outgoing; unsigned short tos; + struct in_addr *client_addr=NULL; + u_short client_port=0; + + if(fwdState->request->flags.pinned) { + client_addr=&fwdState->request->client_addr; + client_port=fwdState->request->client_port; + } + assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); @@ -372,7 +398,7 @@ ftimeout = 5; if (ftimeout < ctimeout) ctimeout = ftimeout; - if ((fd = pconnPop(host, port)) >= 0) { + if ((fd = pconnPop(host, port, client_addr, client_port)) >= 0) { if (fwdCheckRetriable(fwdState)) { debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); fwdState->server_fd = fd; ============================================================ --- src/http.c 70d4f23441904ca38b3b064cd5bf45b744af1370 +++ src/http.c 69d4e2cd7969e575f5cdba81916aab1f9b2c6223 @@ -564,6 +564,8 @@ int bin; int clen; size_t read_sz = SQUID_TCP_SO_RCVBUF; + struct in_addr *client_addr=NULL; + u_short client_port=0; #if DELAY_POOLS delay_id delay_id; #endif @@ -579,6 +581,11 @@ else delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz); #endif + if ( httpState->request->flags.pinned ) { + client_addr=&httpState->request->client_addr; + client_port=httpState->request->client_port; + } + errno = 0; statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, read_sz); @@ -739,9 +752,9 @@ comm_remove_close_handler(fd, httpStateFree, httpState); fwdUnregister(fd, httpState->fwd); if (request->flags.accelerated && Config.Accel.single_host && Config.Accel.host) - pconnPush(fd, Config.Accel.host, Config.Accel.port); + pconnPush(fd, Config.Accel.host, Config.Accel.port, client_addr, client_port); else - pconnPush(fd, request->host, request->port); + pconnPush(fd, request->host, request->port, client_addr, client_port); fwdComplete(httpState->fwd); httpState->fd = -1; httpStateFree(fd, httpState); ============================================================ --- src/pconn.c b92717711418c48f60d127e43fea65752a667d66 +++ src/pconn.c 5f83c46e535d572c2a6d6f55389e635926c3feee @@ -49,7 +49,6 @@ static PF pconnRead; static PF pconnTimeout; -static const char *pconnKey(const char *host, u_short port); static hash_table *table = NULL; static struct _pconn *pconnNew(const char *key); static void pconnDelete(struct _pconn *p); @@ -58,12 +57,17 @@ static MemPool *pconn_data_pool = NULL; static MemPool *pconn_fds_pool = NULL; -static const char * -pconnKey(const char *host, u_short port) +#define PCONN_KEYLEN (SQUIDHOSTNAMELEN + 30) + +static inline const int +pconnKey(char *buf, const char *peer, u_short port, struct in_addr *client_address, u_short client_port) { - LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN + 10); - snprintf(buf, SQUIDHOSTNAMELEN + 10, "%s.%d", host, (int) port); - return buf; + if ( client_address == NULL ) { + return snprintf(buf, PCONN_KEYLEN, "%s.%d", peer, (int) port); + }else{ + return snprintf(buf, PCONN_KEYLEN, "%s.%d.%s.%d", + peer, (int) port, inet_ntoa(*client_address), (int) client_port); + } } static struct _pconn * @@ -184,11 +188,11 @@ } void -pconnPush(int fd, const char *host, u_short port) +pconnPush(int fd, const char *peer, u_short port, struct in_addr *client_address, u_short client_port) { struct _pconn *p; int *old; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); + LOCAL_ARRAY(char, key, PCONN_KEYLEN); LOCAL_ARRAY(char, desc, FD_DESC_SZ); if (fdUsageHigh()) { debug(48, 3) ("pconnPush: Not many unused FDs\n"); @@ -199,7 +203,7 @@ return; } assert(table != NULL); - strcpy(key, pconnKey(host, port)); + pconnKey(key, peer, port, client_address, client_port); p = (struct _pconn *) hash_lookup(table, key); if (p == NULL) p = pconnNew(key); @@ -217,20 +221,20 @@ p->fds[p->nfds++] = fd; commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0); commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p); - snprintf(desc, FD_DESC_SZ, "%s idle connection", host); + snprintf(desc, FD_DESC_SZ, "%s idle connection", peer); fd_note(fd, desc); debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key); } int -pconnPop(const char *host, u_short port) +pconnPop(const char *peer, u_short port, struct in_addr *client_address, u_short client_port) { struct _pconn *p; hash_link *hptr; int fd = -1; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); + LOCAL_ARRAY(char, key, PCONN_KEYLEN); assert(table != NULL); - strcpy(key, pconnKey(host, port)); + pconnKey(key, peer, port, client_address, client_port); hptr = hash_lookup(table, key); if (hptr != NULL) { p = (struct _pconn *) hptr; ============================================================ --- src/protos.h 24cb1a4562e33e16ac98068a665abba386b418af +++ src/protos.h d924404fa81b7d01e6af2836d2ff9e49c5ddabcd @@ -1139,8 +1146,8 @@ extern int errorReservePageId(const char *page_name); extern ErrorState *errorCon(err_type type, http_status); -extern void pconnPush(int, const char *host, u_short port); -extern int pconnPop(const char *host, u_short port); +extern void pconnPush(int, const char *peer, u_short port, struct in_addr *client_address, u_short client_port); +extern int pconnPop(const char *peer, u_short port, struct in_addr *client_address, u_short client_port); extern void pconnInit(void); extern int asnMatchIp(void *, struct in_addr); ============================================================ --- src/structs.h 825043409b63de2a3a51d8fb1a0af6faeb9e34eb +++ src/structs.h 8c514b042f35f6fd32b0a73cf21a9643cf2d6cd4 @@ -1647,6 +1663,7 @@ unsigned int body_sent:1; unsigned int reset_tcp:1; unsigned int must_keepalive:1; + unsigned int pinned:1; /* If set, this request is tightly tied to a client-side connection */ }; struct _link_list { @@ -1692,6 +1709,7 @@ int imslen; int max_forwards; /* these in_addr's could probably be sockaddr_in's */ + in_port_t client_port; struct in_addr client_addr; struct in_addr my_addr; unsigned short my_port;