From: hno <> Date: Mon, 7 Jul 2003 03:43:36 +0000 (+0000) Subject: External acl extensions: X-Git-Tag: SQUID_3_0_PRE1~64 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=47b0c1fad722ca9a31e3f7d87703db7ecb712f17;p=thirdparty%2Fsquid.git External acl extensions: %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. --- diff --git a/src/cf.data.pre b/src/cf.data.pre index c19ba96c74..dd61e387cd 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -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 diff --git a/src/client_side.cc b/src/client_side.cc index 889d33874e..0960176eff 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -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; diff --git a/src/client_side_request.cc b/src/client_side_request.cc index b487d3b5f9..ed122aae68 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -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; diff --git a/src/external_acl.cc b/src/external_acl.cc index 33c6c4771a..f1cccfef7a 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -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(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(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(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(node->data); - for (node = def->queue.head; node; node = node->next) { - externalAclState *oldstate = static_cast(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(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 diff --git a/src/structs.h b/src/structs.h index ad999f6dac..5dbe32f22a 100644 --- a/src/structs.h +++ b/src/structs.h @@ -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;