]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
External acl extensions:
authorhno <>
Mon, 7 Jul 2003 03:43:36 +0000 (03:43 +0000)
committerhno <>
Mon, 7 Jul 2003 03:43:36 +0000 (03:43 +0000)
%SRCPORT, %MYPORT, %MYADDR
New format tags for matching client TCP connection details

grace=N
defines a grace period on external acl cache entries. If the entry has less
then the grace period left when being refercenced then a new lookup is
initiated but without waiting for the reply.

src/cf.data.pre
src/client_side.cc
src/client_side_request.cc
src/external_acl.cc
src/structs.h

index c19ba96c748c6e5810767b59cf2bc20efd90e436..dd61e387cd136b24e55ac823b9d96002c7f2ef8c 100644 (file)
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.327 2003/07/01 20:42:27 wessels Exp $
+# $Id: cf.data.pre,v 1.328 2003/07/06 21:43:36 hno Exp $
 #
 #
 # SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -1767,17 +1767,23 @@ DOC_START
                        helpers who can only process a single request at a
                        time.
          cache=n       result cache size, 0 is unbounded (default)
+         grace=n       Percentage remaining of TTL where a refresh of a
+                       cached entry should be initiated without needing to
+                       wait for a new reply. (default 0 for no grace period)
        
        FORMAT specifications
 
          %LOGIN        Authenticated user login name
          %IDENT        Ident user name
          %SRC          Client IP
+         %SRCPORT      Client source port
          %DST          Requested host
          %PROTO        Requested protocol
          %PORT         Requested port
          %PATH         Requested URL path
          %METHOD       Request method
+         %MYADDR       Squid interface address
+         %MYPORT       Squid http_port number
          %USER_CERT_xx SSL User certificate attribute xx
          %USER_CA_xx   SSL User certificate CA attribute xx
          %{Header}     HTTP request header
index 889d33874e36a54c21d330c7614ec82929fea654..0960176effa2134435fafc0a32997f9ebb7c872a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.644 2003/06/27 22:32:30 hno Exp $
+ * $Id: client_side.cc,v 1.645 2003/07/06 21:43:36 hno Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -2128,6 +2128,7 @@ clientProcessRequest(ConnStateData *conn, ClientSocketContext *context, method_t
     request->flags.internal = http->flags.internal;
     setLogUri (http, urlCanonicalClean(request));
     request->client_addr = conn->peer.sin_addr;
+    request->client_port = ntohs(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;
index b487d3b5f9cc021aba091f0e919c007cfc44674c..ed122aae685c733c146439832837d1774452fbaf 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side_request.cc,v 1.24 2003/06/27 22:32:31 hno Exp $
+ * $Id: client_side_request.cc,v 1.25 2003/07/06 21:43:36 hno Exp $
  * 
  * DEBUG: section 85    Client-side Request Routines
  * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
@@ -758,6 +758,7 @@ clientRedirectDone(void *data, char *result)
         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;
index 33c6c4771a94779b4c6a3b49c3d4189a35f8a3b2..f1cccfef7abd2d0b0bf9383c0f8141b79824fffe 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: external_acl.cc,v 1.46 2003/06/27 22:32:31 hno Exp $
+ * $Id: external_acl.cc,v 1.47 2003/07/06 21:43:36 hno Exp $
  *
  * DEBUG: section 82    External ACL
  * AUTHOR: Henrik Nordstrom, MARA Systems AB
@@ -65,6 +65,7 @@ typedef struct _external_acl_format external_acl_format;
 static char *makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data);
 static void external_acl_cache_delete(external_acl * def, external_acl_entry * entry);
 static int external_acl_entry_expired(external_acl * def, external_acl_entry * entry);
+static int external_acl_grace_expired(external_acl * def, external_acl_entry * entry);
 static void external_acl_cache_touch(external_acl * def, external_acl_entry * entry);
 static external_acl_entry *external_acl_cache_add(external_acl * def, const char *key, ExternalACLEntryData const &data);
 
@@ -87,6 +88,8 @@ public:
 
     int negative_ttl;
 
+    int grace;
+
     char *name;
 
     external_acl_format *format;
@@ -121,6 +124,9 @@ struct _external_acl_format
         EXT_ACL_IDENT,
 #endif
         EXT_ACL_SRC,
+        EXT_ACL_SRCPORT,
+        EXT_ACL_MYADDR,
+        EXT_ACL_MYPORT,
         EXT_ACL_DST,
         EXT_ACL_PROTO,
         EXT_ACL_PORT,
@@ -220,6 +226,8 @@ parse_externalAclHelper(external_acl ** list)
             a->concurrency = atoi(token + 12);
         } else if (strncmp(token, "cache=", 6) == 0) {
             a->cache_size = atoi(token + 6);
+        } else if (strncmp(token, "grace=", 6) == 0) {
+            a->grace = atoi(token + 6);
         } else {
             break;
         }
@@ -295,6 +303,12 @@ parse_externalAclHelper(external_acl ** list)
 
         else if (strcmp(token, "%SRC") == 0)
             format->type = _external_acl_format::EXT_ACL_SRC;
+        else if (strcmp(token, "%SRCPORT") == 0)
+            format->type = _external_acl_format::EXT_ACL_SRCPORT;
+        else if (strcmp(token, "%MYADDR") == 0)
+            format->type = _external_acl_format::EXT_ACL_MYADDR;
+        else if (strcmp(token, "%MYPORT") == 0)
+            format->type = _external_acl_format::EXT_ACL_MYPORT;
         else if (strcmp(token, "%DST") == 0)
             format->type = _external_acl_format::EXT_ACL_DST;
         else if (strcmp(token, "%PROTO") == 0)
@@ -363,12 +377,18 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl
         if (node->negative_ttl != node->ttl)
             storeAppendPrintf(sentry, " negative_ttl=%d", node->negative_ttl);
 
+        if (node->grace)
+            storeAppendPrintf(sentry, " grace=%d", node->grace);
+
         if (node->children != DEFAULT_EXTERNAL_ACL_CHILDREN)
             storeAppendPrintf(sentry, " children=%d", node->children);
 
         if (node->concurrency)
             storeAppendPrintf(sentry, " concurrency=%d", node->concurrency);
 
+        if (node->cache)
+            storeAppendPrintf(sentry, " cache=%d", node->cache_size);
+
         for (format = node->format; format; format = format->next) {
             switch (format->type) {
 
@@ -395,6 +415,9 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl
 #endif
 
                 DUMP_EXT_ACL_TYPE(SRC);
+                DUMP_EXT_ACL_TYPE(SRCPORT);
+                DUMP_EXT_ACL_TYPE(MYADDR);
+                DUMP_EXT_ACL_TYPE(MYPORT);
                 DUMP_EXT_ACL_TYPE(DST);
                 DUMP_EXT_ACL_TYPE(PROTO);
                 DUMP_EXT_ACL_TYPE(PORT);
@@ -560,6 +583,8 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
 
         key = makeExternalAclKey(ch, acl);
 
+        ch->auth_user_request = NULL;
+
         if (!key) {
             /* Not sufficient data to process */
             return -1;
@@ -567,24 +592,22 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
 
         entry = static_cast<external_acl_entry *>(hash_lookup(acl->def->cache, key));
 
-        if (entry && external_acl_entry_expired(acl->def, entry)) {
-            /* Expired entry, ignore */
-            debug(82, 2) ("external_acl_cache_lookup: '%s' = expired\n", key);
-            entry = NULL;
-        }
-
-        ch->auth_user_request = NULL;
-    }
-
-    if (!entry || entry->result == -1) {
-        debug(82, 2) ("aclMatchExternal: %s(\"%s\") = lookup needed\n", acl->def->name, key);
-
-        if (acl->def->theHelper->stats.queue_size >= acl->def->theHelper->n_running)
-            debug(82, 1) ("aclMatchExternal: '%s' queue overload. Request rejected.\n", acl->def->name);
-        else
-            ch->changeState (ExternalACLLookup::Instance());
+        if (!entry || external_acl_grace_expired(acl->def, entry)) {
+            debug(82, 2) ("aclMatchExternal: %s(\"%s\") = lookup needed\n", acl->def->name, key);
 
-        return 0;
+            if (acl->def->theHelper->stats.queue_size <= acl->def->theHelper->n_running) {
+                ch->changeState (ExternalACLLookup::Instance());
+                return -1;
+            } else {
+                if (!entry) {
+                    debug(82, 1) ("aclMatchExternal: '%s' queue overload. Request rejected '%s'.\n", acl->def->name, key);
+                    return -1;
+                } else {
+                    debug(82, 1) ("aclMatchExternal: '%s' queue overload. Using stale result. '%s'.\n", acl->def->name, key);
+                    /* Fall thru to processing below */
+                }
+            }
+        }
     }
 
     external_acl_cache_touch(acl->def, entry);
@@ -678,6 +701,20 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
             str = inet_ntoa(ch->src_addr);
             break;
 
+        case _external_acl_format::EXT_ACL_SRCPORT:
+            snprintf(buf, sizeof(buf), "%d", request->client_port);
+            str = buf;
+            break;
+
+        case _external_acl_format::EXT_ACL_MYADDR:
+            str = inet_ntoa(request->my_addr);
+            break;
+
+        case _external_acl_format::EXT_ACL_MYPORT:
+            snprintf(buf, sizeof(buf), "%d", request->my_port);
+            str = buf;
+            break;
+
         case _external_acl_format::EXT_ACL_DST:
             str = request->host;
             break;
@@ -792,6 +829,19 @@ external_acl_entry_expired(external_acl * def, external_acl_entry * entry)
         return 0;
 }
 
+static int
+external_acl_grace_expired(external_acl * def, external_acl_entry * entry)
+{
+    int ttl;
+    ttl = entry->result == 1 ? def->ttl : def->negative_ttl;
+    ttl = (ttl * (100 - def->grace)) / 100;
+
+    if (entry->date + ttl < squid_curtime)
+        return 1;
+    else
+        return 0;
+}
+
 static external_acl_entry *
 external_acl_cache_add(external_acl * def, const char *key, ExternalACLEntryData const & data)
 {
@@ -941,7 +991,7 @@ externalAclHandleReply(void *data, char *reply)
         void *cbdata;
         cbdataReferenceDone(state->def);
 
-        if (cbdataReferenceValidDone(state->callback_data, &cbdata))
+        if (state->callback && cbdataReferenceValidDone(state->callback_data, &cbdata))
             state->callback(cbdata, entry);
 
         next = state->queue;
@@ -959,6 +1009,9 @@ ACLExternal::ExternalAclLookup(ACLChecklist * ch, ACLExternal * me, EAH * callba
     external_acl_data *acl = static_cast<external_acl_data *>(me->data);
     external_acl *def = acl->def;
     externalAclState *state;
+    dlink_node *node;
+    externalAclState *oldstate = NULL;
+    bool graceful = 0;
 
     if (acl->def->require_auth) {
         int ti;
@@ -982,63 +1035,77 @@ ACLExternal::ExternalAclLookup(ACLChecklist * ch, ACLExternal * me, EAH * callba
     debug(82, 2) ("externalAclLookup: lookup in '%s' for '%s'\n", def->name, key);
     external_acl_entry *entry = static_cast<external_acl_entry *>(hash_lookup(def->cache, key));
 
-    state = cbdataAlloc(externalAclState);
-    state->def = cbdataReference(def);
-    state->callback = callback;
-    state->callback_data = cbdataReference(callback_data);
-    state->key = xstrdup(key);
+    if (entry && external_acl_entry_expired(def, entry))
+        entry = NULL;
 
-    if (entry && !external_acl_entry_expired(def, entry)) {
-        if (entry->result == -1) {
-            /* There is a pending lookup. Hook into it */
-            dlink_node *node;
+    /* Check for a pending lookup to hook into */
+    for (node = def->queue.head; node; node = node->next) {
+        externalAclState *oldstatetmp = static_cast<externalAclState *>(node->data);
 
-            for (node = def->queue.head; node; node = node->next) {
-                externalAclState *oldstate = static_cast<externalAclState *>(node->data);
+        if (strcmp(key, oldstatetmp->key) == 0) {
+            oldstate = oldstatetmp;
+            break;
+        }
+    }
 
-                if (strcmp(state->key, oldstate->key) == 0) {
-                    state->queue = oldstate->queue;
-                    oldstate->queue = state;
-                    return;
-                }
-            }
-        } else {
-            /* There is a cached valid result.. use it */
-            /* This should not really happen, but what the heck.. */
+    if (entry && external_acl_grace_expired(def, entry)) {
+        if (oldstate) {
             callback(callback_data, entry);
-            cbdataFree(state);
             return;
+        } else {
+            graceful = 1;
         }
     }
 
-    /* Check for queue overload */
-    if (def->theHelper->stats.queue_size >= def->theHelper->n_running) {
-        int result = -1;
-        external_acl_entry *entry = static_cast<external_acl_entry *>(hash_lookup(def->cache, key));
-        debug(82, 1) ("externalAclLookup: '%s' queue overload\n", def->name);
+    if (!graceful && entry && !external_acl_grace_expired(def, entry)) {
+        /* Should not really happen, but why not.. */
+        callback(callback_data, entry);
+        return;
+    }
 
-        if (entry)
-            result = entry->result;
+    /* No pending lookup found. Sumbit to helper */
+    state = cbdataAlloc(externalAclState);
 
-        cbdataFree(state);
+    state->def = cbdataReference(def);
 
-        callback(callback_data, entry);
+    state->key = xstrdup(key);
 
-        return;
+    if (!graceful) {
+        state->callback = callback;
+        state->callback_data = cbdataReference(callback_data);
     }
 
-    /* Send it off to the helper */
-    memBufDefInit(&buf);
+    if (oldstate) {
+        /* Hook into pending lookup */
+        state->queue = oldstate->queue;
+        oldstate->queue = state;
+    } else {
+        /* Check for queue overload */
+
+        if (def->theHelper->stats.queue_size >= def->theHelper->n_running) {
+            debug(82, 1) ("externalAclLookup: '%s' queue overload\n", def->name);
+            cbdataFree(state);
+            callback(callback_data, entry);
+            return;
+        }
+
+        /* Send it off to the helper */
+        memBufDefInit(&buf);
 
-    memBufPrintf(&buf, "%s\n", key);
+        memBufPrintf(&buf, "%s\n", key);
 
-    helperSubmit(def->theHelper, buf.buf, externalAclHandleReply, state);
+        helperSubmit(def->theHelper, buf.buf, externalAclHandleReply, state);
 
-    external_acl_cache_add(def, key, ExternalACLEntryData());
+        dlinkAdd(state, &state->list, &def->queue);
 
-    dlinkAdd(state, &state->list, &def->queue);
+        memBufClean(&buf);
+    }
 
-    memBufClean(&buf);
+    if (graceful) {
+        /* No need to wait during grace period */
+        callback(callback_data, entry);
+        return;
+    }
 }
 
 static void
index ad999f6dac82ff0677061bebdd6d9f4e02a5252e..5dbe32f22a86d7791a42e832a9218ec9be9e1999 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.467 2003/07/01 20:42:28 wessels Exp $
+ * $Id: structs.h,v 1.468 2003/07/06 21:43:36 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -1694,6 +1694,7 @@ public:
 
     struct in_addr my_addr;
     unsigned short my_port;
+    unsigned short client_port;
     HttpHeader header;
     ConnStateData *body_connection;    /* used by clientReadBody() */
     int content_length;