Hi.
There are two patches in attachment that add new functionality to
squid. Both patches are used in my company.

1.
First patch (file zph_tos_acl.patch) is the extension of patch
available here http://www.it-academy.bg/zph/ used for setting TOS
value dependent of cache HIT/MISS. Attached patch extends
functionality, by allowing editing of TOS value in ACLs. This allows
setting TOS based on HIT/MISS at parent squid using information from
header. Example:

acl peer_hit rep_header X-Cache
HIT[[:space:]]from[[:space:]]proxy.domain.com
zph_tos_acl 8
zph_tos_acl_match allow peer_hit

where:
zph_tos_acl <tos> - set TOS <tos> if acl zph_tos_acl_match
matches.

I also attach original patch (file squid-2.6.12-ToS_Hit_ToS_Preserve.patch)
from http://www.it-academy.bg/zph/ bacause website is no longer available.

2.
Second patch extends functionality of squid running as a parent and
using tproxy extension.

In case of connection to parent squid, source address is the address of
other squid making connection to parent.

Patch allows using data from header X-Forwarded-For in analogous way
as in case of acl_uses_indirect_client,
delay_pool_uses_indirect_client and log_uses_indirect_client.

New options are:
outgoing_tos_uses_indirect_client - use address from header
X-Forwarded-For for tcp_outgoing_tos,
outgoing_address_uses_indirect_client - use address from header
X-Forwarded-For for tcp_outgoing_address,
tproxy_uses_indirect_client - use address from header X-Forwarded-For
as source address in case of using tproxy. Patch is in file 
follow_xff-tproxy.patch.

Attached patches are in production use at ISP company for few
weeks now and have worked reliably ever since.

-- 
cheers,
Krzysztof Mościcki
diff -uNr squid-2.6.STABLE13.orig/src/cf.data.pre squid-2.6.STABLE13/src/cf.data.pre
--- squid-2.6.STABLE13.orig/src/cf.data.pre	2007-04-24 23:30:03.000000000 +0200
+++ squid-2.6.STABLE13/src/cf.data.pre	2007-06-22 18:46:24.174880872 +0200
@@ -2933,6 +2933,42 @@
 	direct client address in the access log.
 DOC_END
 
+NAME: outgoing_tos_uses_indirect_client
+COMMENT: on|off
+TYPE: onoff
+IFDEF: FOLLOW_X_FORWARDED_FOR
+DEFAULT: on
+LOC: Config.onoff.outgoing_tos_uses_indirect_client
+DOC_START
+	Controls whether the indirect client address
+	(see follow_x_forwarded_for) is used instead of the
+	direct client address in the tcp_outgoing_tos.
+DOC_END
+
+NAME: outgoing_address_uses_indirect_client
+COMMENT: on|off
+TYPE: onoff
+IFDEF: FOLLOW_X_FORWARDED_FOR
+DEFAULT: on
+LOC: Config.onoff.outgoing_address_uses_indirect_client
+DOC_START
+	Controls whether the indirect client address
+	(see follow_x_forwarded_for) is used instead of the
+	direct client address in the tcp_outgoing_address.
+DOC_END
+
+NAME: tproxy_uses_indirect_client
+COMMENT: on|off
+TYPE: onoff
+IFDEF: FOLLOW_X_FORWARDED_FOR && LINUX_TPROXY
+DEFAULT: on
+LOC: Config.onoff.tproxy_uses_indirect_client
+DOC_START
+	Controls whether the indirect client address
+	(see follow_x_forwarded_for) is used instead of the
+	direct client address for spoofing tproxy address.
+DOC_END
+
 NAME: http_access
 TYPE: acl_access
 LOC: Config.accessList.http
diff -uNr squid-2.6.STABLE13.orig/src/forward.c squid-2.6.STABLE13/src/forward.c
--- squid-2.6.STABLE13.orig/src/forward.c	2007-04-17 11:35:17.000000000 +0200
+++ squid-2.6.STABLE13/src/forward.c	2007-06-22 18:51:01.275836354 +0200
@@ -424,6 +424,11 @@
     aclCheck_t ch;
     memset(&ch, '\0', sizeof(aclCheck_t));
     if (request) {
+#if FOLLOW_X_FORWARDED_FOR
+	    if (Config.onoff.outgoing_address_uses_indirect_client)
+	        ch.src_addr = request->indirect_client_addr;
+	    else
+#endif /* FOLLOW_X_FORWARDED_FOR */
 	ch.src_addr = request->client_addr;
 	ch.my_addr = request->my_addr;
 	ch.my_port = request->my_port;
@@ -438,6 +443,11 @@
     aclCheck_t ch;
     memset(&ch, '\0', sizeof(aclCheck_t));
     if (request) {
+#if FOLLOW_X_FORWARDED_FOR
+	    if (Config.onoff.outgoing_tos_uses_indirect_client)
+	        ch.src_addr = request->indirect_client_addr;
+	    else
+#endif /* FOLLOW_X_FORWARDED_FOR */
 	ch.src_addr = request->client_addr;
 	ch.my_addr = request->my_addr;
 	ch.my_port = request->my_port;
@@ -590,6 +600,11 @@
 #if LINUX_TPROXY
 	if (fwdState->request->flags.tproxy) {
 
+#if FOLLOW_X_FORWARDED_FOR
+	    if (Config.onoff.tproxy_uses_indirect_client)
+	        itp.v.addr.faddr = fwdState->request->indirect_client_addr;
+	    else
+#endif /* FOLLOW_X_FORWARDED_FOR */
 	    itp.v.addr.faddr.s_addr = fwdState->src.sin_addr.s_addr;
 	    itp.v.addr.fport = 0;
 
diff -uNr squid-2.6.STABLE13.orig/src/structs.h squid-2.6.STABLE13/src/structs.h
--- squid-2.6.STABLE13.orig/src/structs.h	2007-04-27 01:11:51.000000000 +0200
+++ squid-2.6.STABLE13/src/structs.h	2007-06-22 18:46:24.178213976 +0200
@@ -678,6 +678,11 @@
 	int acl_uses_indirect_client;
 	int delay_pool_uses_indirect_client;
 	int log_uses_indirect_client;
+	int outgoing_tos_uses_indirect_client;
+	int outgoing_address_uses_indirect_client;
+#if LINUX_TPROXY
+	int tproxy_uses_indirect_client;
+#endif
 #endif
     } onoff;
     acl *aclList;
diff -Nru squid-2.6.STABLE12.orig/src/cf.data.pre squid-2.6.STABLE12/src/cf.data.pre
--- squid-2.6.STABLE12.orig/src/cf.data.pre	2007-03-21 19:43:48.000000000 +0200
+++ squid-2.6.STABLE12/src/cf.data.pre	2007-03-21 19:44:08.000000000 +0200
@@ -3193,6 +3193,64 @@
 	to off when using this directive in such configurations.
 DOC_END
 
+NAME: zph_tos_local
+TYPE: int
+DEFAULT: 0
+LOC: Config.zph_tos_local
+DOC_START
+	Allows you to select a TOS/Diffserv value to mark local hits. Read above
+	(tcp_outgoing_tos) for details/requirements about TOS.
+	Default: 0 (disabled).
+DOC_END
+
+NAME: zph_tos_peer
+TYPE: int
+DEFAULT: 0
+LOC: Config.zph_tos_peer
+DOC_START
+	Allows you to select a TOS/Diffserv value to mark peer hits. Read above
+	(tcp_outgoing_tos) for details/requirements about TOS.
+	Default: 0 (disabled).
+DOC_END
+
+NAME: zph_tos_parent
+COMMENT: on|off
+TYPE: onoff
+LOC: Config.onoff.zph_tos_parent
+DEFAULT: on
+DOC_START
+	Set this to off if you want only sibling hits to be marked.
+	If set to on (default), parent hits are being marked too.
+DOC_END
+
+NAME: zph_preserve_miss_tos
+COMMENT: on|off
+TYPE: onoff
+LOC: Config.onoff.zph_preserve_miss_tos
+DEFAULT: on
+DOC_START
+	If set to on (default), any HTTP response towards clients will
+	have the TOS value of the response comming from the remote
+	server masked with the value of zph_preserve_miss_tos_mask.
+	For this to work correctly, you will need to patch your linux
+	kernel with the TOS preserving ZPH patch.
+	Has no effect under FreeBSD, works only under linux ZPH patched
+	kernels.
+DOC_END
+
+NAME: zph_preserve_miss_tos_mask
+TYPE: int
+DEFAULT: 255
+LOC: Config.zph_preserve_miss_tos_mask
+DOC_START
+	Allows you to mask certain bits in the TOS received from the
+	remote server, before copying the value to the TOS send towards
+	clients.
+	See zph_preserve_miss_tos for details.
+	
+	Default: 255 (TOS from server is not changed).
+DOC_END
+
 NAME: tcp_outgoing_address
 TYPE: acl_address
 DEFAULT: none
diff -Nru squid-2.6.STABLE12.orig/src/client_side.c squid-2.6.STABLE12/src/client_side.c
--- squid-2.6.STABLE12.orig/src/client_side.c	2007-03-21 19:43:48.000000000 +0200
+++ squid-2.6.STABLE12/src/client_side.c	2007-03-21 19:44:08.000000000 +0200
@@ -2621,6 +2621,55 @@
 	return;
     }
     assert(http->out.offset == 0);
+	
+	if ( Config.zph_tos_local || Config.zph_tos_peer ||
+         (Config.onoff.zph_preserve_miss_tos && Config.zph_preserve_miss_tos_mask) )
+    {
+       int need_change = 0;
+       int hit = 0;
+       int tos = 0;
+       int tos_old = 0;
+       int tos_len = sizeof(tos_old);
+       int res;
+                   
+       if (Config.zph_tos_local && isTcpHit(http->log_type)) {     /* local hit */
+           hit = 1;
+           tos = Config.zph_tos_local;
+       } else if (Config.zph_tos_peer &&
+           (http->request->hier.code == SIBLING_HIT ||             /* sibling hit */
+           (Config.onoff.zph_tos_parent &&
+           http->request->hier.code == PARENT_HIT))) {             /* parent hit */
+           hit = 1;
+           tos = Config.zph_tos_peer;
+       }
+       if (http->request->flags.proxy_keepalive) {
+           if (getsockopt(fd, IPPROTO_IP, IP_TOS, &tos_old, &tos_len) < 0) {
+               debug(33, 1) ("ZPH: getsockopt(IP_TOS) on FD %d: %s\n", fd, xstrerror());
+           } else if (hit && tos_old != tos) {     /* HIT: 1-st request, or previous was MISS, */
+               need_change = 1;                    /* or local/parent hit change */
+           } else if (!hit && (tos_old ||  /* MISS: previous was HIT */
+                            Config.onoff.zph_preserve_miss_tos)) { /* TOS copying is on */
+#if defined(_SQUID_LINUX_)			    
+                   if ( Config.onoff.zph_preserve_miss_tos ) {
+                     tos = (entry->mem_obj != NULL) ?
+                           (entry->mem_obj->recvTOS & Config.zph_preserve_miss_tos_mask):0;
+                   } else tos = 0;
+#else
+		    tos = 0;
+#endif		   
+               need_change = 1;
+           } 
+       } else if (hit) {                           /* no keepalive */
+           need_change = 1;
+       }
+       if (need_change) {
+           if (!hit) enter_suid(); /* Setting TOS bit6-7 is privilleged */
+           res = setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+           if (!hit) leave_suid(); /* Setting bit5-7 is privilleged */
+           if ( res < 0)
+               debug(33, 1) ("ZPH: setsockopt(IP_TOS) on FD %d: %s\n", fd, xstrerror());
+       }
+    }
     rep = http->reply = clientBuildReply(http, buf, size);
     if (!rep) {
 	/* Forward as HTTP/0.9 body with no reply */
diff -Nru squid-2.6.STABLE12.orig/src/http.c squid-2.6.STABLE12/src/http.c
--- squid-2.6.STABLE12.orig/src/http.c	2007-03-13 00:27:09.000000000 +0200
+++ squid-2.6.STABLE12/src/http.c	2007-03-21 19:44:08.000000000 +0200
@@ -1373,6 +1373,53 @@
     peer *p = httpState->peer;
     CWCB *sendHeaderDone;
     int fd = httpState->fd;
+    
+#if defined(_SQUID_LINUX_)    
+/* ZPH patch starts here (M.Stavrev 25-05-2005)
+ * Retrieve connection peer's TOS value (which its SYN_ACK TCP segment
+ * was encapsulated into an IP packet)
+ */
+    int tos, tos_len;
+    if ( entry && entry->mem_obj ) { // Is this check necessary ? Seems not, but
+				 // have no time to investigate further.
+	    entry->mem_obj->recvTOS = 0;
+	    tos = 1;
+	    tos_len = sizeof(tos);
+	 	if ( setsockopt(fd,SOL_IP, IP_RECVTOS, &tos, tos_len) == 0 ) {
+		    unsigned char buf[128];
+		    int len = 128;
+		    if (getsockopt(fd, SOL_IP, IP_PKTOPTIONS, buf, &len) == 0)
+		    {
+		    	/* Parse the PKTOPTIONS structure to locate the TOS data message
+		    	 * prepared in the kernel by the ZPH incoming TCP TOS preserving
+		    	 * patch. In 99,99% the TOS should be located at buf[12], but
+		    	 * let's do it the right way.
+		    	 */
+		    	unsigned char * p = buf;
+		    	while ( p-buf < len ) {
+		    		struct cmsghdr * o = (struct cmsghdr*)p;
+		    		if ( o->cmsg_len <= 0 || o->cmsg_len > 52 )
+		    		   break;
+		    		if ( o->cmsg_level == SOL_IP && o->cmsg_type == IP_TOS ) {
+	    			   entry->mem_obj->recvTOS = (unsigned char)(*(int*)
+			    	   						(p + sizeof(struct cmsghdr)));
+				       debug(11, 5) ("ZPH: Incomming TOS=%d on FD %d\n",
+				       			entry->mem_obj->recvTOS, fd );
+			    	   break;
+		    		}
+		    		p += o->cmsg_len;
+		    	}
+		    } else {
+		    	debug(11, 5) ("ZPH: getsockopt(IP_PKTOPTIONS) on FD %d: %s\n",
+		    				 fd, xstrerror());
+		    }
+		} else {
+	    	debug(11, 5) ("ZPH: setsockopt(IP_RECVTOS) on FD %d: %s\n",
+	    					 fd, xstrerror());
+		}
+    }
+/* ZPH patch ends here */    
+#endif
 
     debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", fd, httpState);
 
diff -Nru squid-2.6.STABLE12.orig/src/structs.h squid-2.6.STABLE12/src/structs.h
--- squid-2.6.STABLE12.orig/src/structs.h	2007-02-27 03:20:01.000000000 +0200
+++ squid-2.6.STABLE12/src/structs.h	2007-03-21 19:44:08.000000000 +0200
@@ -669,6 +669,8 @@
 	int relaxed_header_parser;
 	int accel_no_pmtu_disc;
 	int global_internal_static;
+	int zph_tos_parent;
+	int zph_preserve_miss_tos;	
 	int httpd_suppress_version_string;
 	int via;
 	int check_hostnames;
@@ -793,6 +795,9 @@
     int sleep_after_fork;	/* microseconds */
     time_t minimum_expiry_time;	/* seconds */
     external_acl *externalAclHelperList;
+	int zph_tos_local;
+   	int zph_tos_peer;
+	int zph_preserve_miss_tos_mask;    
     errormap *errorMapList;
 #if USE_SSL
     struct {
@@ -1724,6 +1729,9 @@
     const char *vary_encoding;
     StoreEntry *ims_entry;
     time_t refresh_timestamp;
+#if defined(_SQUID_LINUX_)    
+    unsigned char recvTOS; /* ZPH patch - stores remote server's TOS */
+#endif	
 };
 
 struct _StoreEntry {
diff -uNr squid-2.6.STABLE12.zph.orig/src/cf.data.pre squid-2.6.STABLE12.zph/src/cf.data.pre
--- squid-2.6.STABLE12.zph.orig/src/cf.data.pre	2007-05-16 11:49:31.000000000 +0200
+++ squid-2.6.STABLE12.zph/src/cf.data.pre	2007-05-16 11:55:57.000000000 +0200
@@ -3243,6 +3243,30 @@
 	Default: 255 (TOS from server is not changed).
 DOC_END
 
+NAME: zph_tos_acl
+TYPE: int
+DEFAULT: 0
+LOC: Config.zph_tos_acl
+DOC_START
+	Allows you to select a TOS/Diffserv value to mark if zph_tos_acl_match
+	is matched.
+	Read above (tcp_outgoing_tos) for details/requirements about TOS.
+	Default: 0 (disabled).
+DOC_END
+
+NAME: zph_tos_acl_match
+TYPE: acl_access
+LOC: Config.accessList.zph_tos_acl_match
+DEFAULT: none
+DEFAULT_IF_NONE: deny all
+DOC_START
+	Replies to client requests with TOS/Diffser if acl-s is matched.
+
+	acl peer_hit rep_header X-Cache HIT[[:space:]]from[[:space:]]domain\.com
+	zph_tos_acl 8
+	zph_tos_acl_match allow peer_hit
+DOC_END
+
 NAME: tcp_outgoing_address
 TYPE: acl_address
 DEFAULT: none
diff -uNr squid-2.6.STABLE12.zph.orig/src/client_side.c squid-2.6.STABLE12.zph/src/client_side.c
--- squid-2.6.STABLE12.zph.orig/src/client_side.c	2007-05-16 11:49:31.000000000 +0200
+++ squid-2.6.STABLE12.zph/src/client_side.c	2007-05-21 18:25:14.365218536 +0200
@@ -2621,8 +2621,18 @@
 	return;
     }
     assert(http->out.offset == 0);
-	
-	if ( Config.zph_tos_local || Config.zph_tos_peer ||
+    rep = http->reply = clientBuildReply(http, buf, size);
+    if (!rep) {
+	/* Forward as HTTP/0.9 body with no reply */
+	MemBuf mb;
+	memBufDefInit(&mb);
+	memBufAppend(&mb, buf, size);
+	http->out.offset += body_size;
+	comm_write_mbuf(http->conn->fd, mb, clientWriteComplete, http);
+	return;
+    }
+    
+	if ( Config.zph_tos_local || Config.zph_tos_acl || Config.zph_tos_peer ||
          (Config.onoff.zph_preserve_miss_tos && Config.zph_preserve_miss_tos_mask) )
     {
        int need_change = 0;
@@ -2635,7 +2645,17 @@
        if (Config.zph_tos_local && isTcpHit(http->log_type)) {     /* local hit */
            hit = 1;
            tos = Config.zph_tos_local;
-       } else if (Config.zph_tos_peer &&
+       } else if (Config.zph_tos_acl) {
+	       aclCheck_t *ch;
+	       ch = clientAclChecklistCreate(Config.accessList.zph_tos_acl_match, http);
+	       ch->reply = http->reply;
+	       if (aclCheckFast(Config.accessList.zph_tos_acl_match, ch)) {	/* acl hit */
+		       hit = 1;
+		       tos = Config.zph_tos_acl;
+	       }
+	       aclChecklistFree(ch);
+       }
+       if (!hit && Config.zph_tos_peer &&
            (http->request->hier.code == SIBLING_HIT ||             /* sibling hit */
            (Config.onoff.zph_tos_parent &&
            http->request->hier.code == PARENT_HIT))) {             /* parent hit */
@@ -2670,16 +2690,6 @@
                debug(33, 1) ("ZPH: setsockopt(IP_TOS) on FD %d: %s\n", fd, xstrerror());
        }
     }
-    rep = http->reply = clientBuildReply(http, buf, size);
-    if (!rep) {
-	/* Forward as HTTP/0.9 body with no reply */
-	MemBuf mb;
-	memBufDefInit(&mb);
-	memBufAppend(&mb, buf, size);
-	http->out.offset += body_size;
-	comm_write_mbuf(http->conn->fd, mb, clientWriteComplete, http);
-	return;
-    }
     if (Config.onoff.log_mime_hdrs) {
 	safe_free(http->al.headers.reply);
 	http->al.headers.reply = xcalloc(rep->hdr_sz + 1, 1);
diff -uNr squid-2.6.STABLE12.zph.orig/src/structs.h squid-2.6.STABLE12.zph/src/structs.h
--- squid-2.6.STABLE12.zph.orig/src/structs.h	2007-05-16 11:49:31.000000000 +0200
+++ squid-2.6.STABLE12.zph/src/structs.h	2007-05-16 11:55:57.000000000 +0200
@@ -705,6 +705,7 @@
 	acl_access *reply;
 	acl_address *outgoing_address;
 	acl_tos *outgoing_tos;
+	acl_tos *zph_tos_acl_match;
 #if USE_HTCP
 	acl_access *htcp;
 	acl_access *htcp_clr;
@@ -797,7 +798,8 @@
     external_acl *externalAclHelperList;
 	int zph_tos_local;
    	int zph_tos_peer;
-	int zph_preserve_miss_tos_mask;    
+	int zph_preserve_miss_tos_mask;
+	int zph_tos_acl;
     errormap *errorMapList;
 #if USE_SSL
     struct {

Reply via email to