#
# squid acl marking patch.
# Writed by Alex Petrov <sysman@sysman.net>
# 
# Short description: this patch allow to add marking for user requestes passed thru 
#			some acl's by adding some chars in access.log.
#
# Oriented for squid-2.4STABLE6
# Also tested&work with minor changes on squid-2.3/squid-2.4.
#
# use
# cd squid-2.4STABLE6/src
# patch -p0 <../../squid-2.4STABLE6_aclmark.patch
#
#
--- /dev/null	Mon Jul 18 02:46:18 1994
+++ ../README.aclmark	Sat May 25 19:14:26 2002
@@ -0,0 +1,46 @@
+Marking ACL's for SQUID Internet Object Cache
+http://squid.nlanr.net/Squid/
+Writed by Alex Petrov , sysman@sysman.net
+--------------------------------------------------------------------------
+General propose is to add marking in squid access.log for some
+destination/source ip/subnets on-the-fly, if they pass thru some acls.
+For example my proxy used for accessing INET,Intranet, and
+some neighbors-nets (local ISP zone with many different subnets,
+low cost subnets & etc...) and I want just to see in logs
+some marking for what zones.
+	It much faster instead of dns backward resolving during
+access.log parse and more effective to keep knowledge about 
+'which ip-zone it belongs to' after month time,
+then some hosts are deleted, or dns downed.
+This solutions just mark for me all that I need at once.
+For example 'O' is our intranet, 'V' branch intranet,
+'L' latvian subnets,'C' no-costs neighbors and soo on.
+My acl look like.  
+
+squid.conf
+acl dst OUR_subnet-mark:O "/etc/squid/acl/outnet.acl"
+acl dst VN_net-mark:V 192.168.0.0/16
+acl dst LV_only+mark:L "/etc/squid/acl/lvsquid.acl"
+acl dst regions+mark:C 10.1.1.0/24 10.2.2.0/24 10.3.3.0/24 172.16.14.0/24
+
+access.log
+989268720.679      0 172.16.16.16 TCP_MISS/404 562 GET http://www.docs.ournet/stat/ -#O DIRECT/www.docs.ournet text/html
+989268720.679      0 172.16.16.16 TCP_MISS/200 790 GET http://www.google.com/search? -#- DIRECT/www.google.com text/xml
+989268721.679      0 172.16.16.16 TCP_MISS/200 1642 GET http://www.vita.gov.lv -#V DIRECT/www.vita.gov.lv image/gif
+989268722.349      0 172.16.16.16 TCP_MISS/200 1644 GET http://www.saldus.raj/traffic/ -#C DIRECT/www.saldus.raj image/gif
+989268722.212      0 172.16.16.16 TCP_MISS/302 270 GET http://www.latnet.lv/ -#L DIRECT/www.latnet.lv text/html
+
+
+Marking acl samples:
+acl src name+mark:C ip ip ip
+#
+# mark if keyword in acl name
+# name+mark:c or name-mark:c 
+# where:
+# '-'  just mark if match acl.
+# '+'  mark & accept acl.
+#  c   marking charaster.
+#
+acl dst name+mark:L lvonly.ips
+acl dst name-mark:I intranet.ips
+#
--- access_log.c.orig	Fri Jan 12 02:51:44 2001
+++ access_log.c	Sat May 25 18:18:11 2002
@@ -190,7 +190,7 @@ accessLogSquid(AccessLogEntry * al)
 	client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
     if (client == NULL)
 	client = inet_ntoa(al->cache.caddr);
-    logfilePrintf(logfile, "%9d.%03d %6d %s %s/%03d %d %s %s %s %s%s/%s %s",
+    logfilePrintf(logfile, "%9d.%03d %6d %s %s/%03d %d %s %s %s#%c %s%s/%s %s",
 	(int) current_time.tv_sec,
 	(int) current_time.tv_usec / 1000,
 	al->cache.msec,
@@ -201,6 +201,8 @@ accessLogSquid(AccessLogEntry * al)
 	al->private.method_str,
 	al->url,
 	al->cache.ident,
+	al->acl_mark,		/* acl_mark char , trying to save compatibility 
+				   with old log format ident userid can use '#' RFC1413*/
 	al->hier.ping.timedout ? "TIMEOUT_" : "",
 	hier_strings[al->hier.code],
 	al->hier.host,
--- acl.c.orig	Tue Aug 21 08:55:47 2001
+++ acl.c	Sat May 25 18:24:17 2002
@@ -1,4 +1,3 @@
-
 /*
  * $Id: acl.c,v 1.225.2.8 2001/08/21 05:55:47 wessels Exp $
  *
@@ -661,6 +660,11 @@ aclParseAclLine(acl ** head)
     LOCAL_ARRAY(char, aclname, ACL_NAME_SZ);
     squid_acl acltype;
     int new_acl = 0;
+			/* acl mark values added by sysman@sysman.net */
+    char *aclmark = NULL;
+    char mark_state;	/* ACL mark state [-/+] */
+    char mark_char;	/* marking charaster */
+    int mark_flag = 0;	/* 0 inactive(def), 1 - only mark, 2 - mark + pass acl */
 
     /* snarf the ACL name */
     if ((t = strtok(NULL, w_space)) == NULL) {
@@ -670,6 +674,34 @@ aclParseAclLine(acl ** head)
 	return;
     }
     xstrncpy(aclname, t, ACL_NAME_SZ);
+
+   /* **************************************************
+      provide mark functionality , check ACLNAME for -/+ marks 
+      marking format acl name+mark:C , where C marking char 
+      name+mark , just mark if acl match ,
+      name-mark mark if acl and applay ACL.
+      added by sysman@sysman.net , please read README.aclmark
+    */
+
+    if( (aclmark = (char *) strchr((char *) t,'+')) != NULL  ||
+        (aclmark = (char *) strchr((char *) t,'-')) != NULL ) 
+     {
+      xmemcpy(&mark_state, (char *) aclmark, 1);
+      (void) *aclmark++;
+
+     if( strncmp(aclmark,"mark",4) == 0 ) 
+      if(  (aclmark=(char *) strrchr((char *) t,':')) != NULL )
+        {
+         (void) *aclmark++; 
+         if( aclmark != NULL )
+	    { xmemcpy(&mark_char, (char *) aclmark, 1);
+              if(mark_state=='-') mark_flag = 1; /* just mark  */
+              if(mark_state=='+') mark_flag = 2; /* mark + acl */
+	    }
+	
+        }
+     } 			/* End acl marking parse  */
+
     /* snarf the ACL type */
     if ((t = strtok(NULL, w_space)) == NULL) {
 	debug(28, 0) ("%s line %d: %s\n",
@@ -690,6 +722,13 @@ aclParseAclLine(acl ** head)
 	A->type = acltype;
 	A->cfgline = xstrdup(config_input_line);
 	new_acl = 1;
+	if (mark_flag!=0)	/* of marking active */
+	{
+	 A->mark_flag=mark_flag;
+	 A->mark_char=mark_char;
+	 debug(28, 3) ("aclParseAclLine: acl_mark %c, marking by character [%c]\n",
+	                  mark_state,mark_char);
+	}
     } else {
 	if (acltype != A->type) {
 	    debug(28, 0) ("aclParseAclLine: ACL '%s' already exists with different type, skipping.\n", A->name);
@@ -1330,6 +1369,8 @@ aclMatchAcl(acl * ae, aclCheck_t * check
     const char *header;
     const char *browser;
     int k;
+    int aclresult;		/* acl mark addon */
+
     if (!ae)
 	return 0;
     switch (ae->type) {
@@ -1354,7 +1395,21 @@ aclMatchAcl(acl * ae, aclCheck_t * check
     debug(28, 3) ("aclMatchAcl: checking '%s'\n", ae->cfgline);
     switch (ae->type) {
     case ACL_SRC_IP:
-	return aclMatchIp(&ae->data, checklist->src_addr);
+	aclresult=aclMatchIp(&ae->data, checklist->src_addr);
+       if(ae->mark_flag==0)    /* if no marking, then work just like always */
+        return aclresult;
+
+                       /* make acl marking */
+        if(aclresult) { 
+                        checklist->request->acl_mark = ae->mark_char;
+                        debug(28, 3) ("aclMatchAcl: SRC acl marked '%c'\n",ae->mark_char);
+
+                        if(ae->mark_flag==1) aclresult=0;      
+                           /* if just mark+ , then SRC ACL always deny,
+                              else lets the ACL working like always */
+                      }
+
+        return aclresult;
 	/* NOTREACHED */
     case ACL_MY_IP:
 	return aclMatchIp(&ae->data, checklist->my_addr);
@@ -1363,8 +1418,18 @@ aclMatchAcl(acl * ae, aclCheck_t * check
 	ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS);
 	if (ia) {
 	    for (k = 0; k < (int) ia->count; k++) {
-		if (aclMatchIp(&ae->data, ia->in_addrs[k]))
-		    return 1;
+		aclresult=aclMatchIp(&ae->data, ia->in_addrs[k]);
+		if (ae->mark_flag==0) 
+		      return aclresult;		/* like always */
+		
+		else { if(aclresult)
+			{
+			 checklist->request->acl_mark = ae->mark_char;
+	 	         debug(28, 3) ("aclMatchAcl: DST acl marked '%c'\n",ae->mark_char);
+			}
+		         if(ae->mark_flag==2) return aclresult; 
+			/* if mark+acl then true, else look more for acls */
+		     }
 	    }
 	    return 0;
 	} else if (checklist->state[ACL_DST_IP] == ACL_LOOKUP_NONE) {
--- cf.data.pre.orig	Wed Apr  4 10:01:12 2001
+++ cf.data.pre	Sat May 25 18:25:15 2002
@@ -1633,6 +1633,11 @@ DOC_START
 	acl aclname src      addr1-addr2/netmask ... (range of addresses)
 	acl aclname dst      ip-address/netmask ... (URL host's IP address)
 	acl aclname myip     ip-address/netmask ... (local socket IP address)
+	  # acl mark feature.
+	  # allow to add char mark in access.log if REUQEST pass some acl
+	  # read more in README.aclmark
+	acl aclname+mark:c src/dst ip-address/netmask # if pass acl mark request by letter 'c'
+	acl aclname-mark:c src/dst ip-address/netmask # if match acl just mark, and ignore acl
 
 	acl aclname srcdomain   .foo.com ...    # reverse lookup, client IP
 	acl aclname dstdomain   .foo.com ...    # Destination server from URL
--- client_side.c.orig	Sat Apr 21 02:21:41 2001
+++ client_side.c	Sat May 25 18:29:22 2002
@@ -1,4 +1,3 @@
-
 /*
  * $Id: client_side.c,v 1.512.2.10 2001/04/20 23:21:41 hno Exp $
  *
@@ -153,6 +152,7 @@ clientAclChecklistCreate(const acl_acces
     ch = aclChecklistCreate(acl,
 	http->request,
 	conn->ident);
+    http->request->acl_mark=0;
 #if USE_IDENT
     /*
      * hack for ident ACL. It needs to get full addresses, and a
@@ -739,6 +739,8 @@ httpRequestFree(void *data)
 	    http->al.http.version = request->http_ver;
 	    http->al.headers.request = xstrdup(mb.buf);
 	    http->al.hier = request->hier;
+	     http->al.acl_mark = ( request->acl_mark==0 ? '-' : request->acl_mark );
+/*	     debug(33, 5) ("httpRequestFree: acl_mark = %c\n",http->al.acl_mark); */
 	    if (request->user_ident[0])
 		http->al.cache.ident = request->user_ident;
 	    else
--- structs.h.orig	Mon Oct  8 18:22:03 2001
+++ structs.h	Sat May 25 18:27:42 2002
@@ -120,6 +120,8 @@ struct _acl {
     squid_acl type;
     void *data;
     char *cfgline;
+    char mark_char;	// marking added by SysMan@sysman.net
+    int mark_flag;	// marking README.aclmark
     acl *next;
 };
 
@@ -154,6 +156,7 @@ struct _aclCheck_t {
 #endif
     PF *callback;
     void *callback_data;
+    char acl_mark;		/* mark by SysMan */
 };
 
 struct _wordlist {
@@ -843,6 +846,7 @@ struct _HierarchyLogEntry {
 
 struct _AccessLogEntry {
     const char *url;
+    char acl_mark;	// added by SysMan
     struct {
 	method_t method;
 	int code;
@@ -1441,6 +1445,7 @@ struct _request_t {
     char login[MAX_LOGIN_SZ];
     char host[SQUIDHOSTNAMELEN + 1];
     char user_ident[USER_IDENT_SZ];	/* from proxy auth or ident server */
+    char acl_mark;			/* acl mark */
     u_short port;
     String urlpath;
     char *canonical;
