This patch is generated from the ntlm_ip_cache branch of HEAD in squid
Tue Apr  3 00:20:20 2007 GMT
See http://devel.squid-cache.org/

Index: squid/src/authenticate.c
diff -u squid/src/authenticate.c:1.35 squid/src/authenticate.c:1.34.8.5
--- squid/src/authenticate.c:1.35	Mon Jan  1 14:51:01 2007
+++ squid/src/authenticate.c	Wed Dec 20 01:07:18 2006
@@ -44,6 +44,7 @@
 
 static void authenticateDecodeAuth(const char *proxy_auth, auth_user_request_t * auth_user_request);
 static auth_acl_t authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr);
+static void authenticateAuthUserRequestUnlinkIp(const struct in_addr ipaddr);
 
 /*
  *
@@ -252,12 +253,100 @@
 {
     /* remove the node */
     dlinkDelete(&ipdata->node, &auth_user->ip_list);
+    authenticateAuthUserRequestUnlinkIp(ipdata->ipaddr);
     cbdataFree(ipdata);
     /* catch incipient underflow */
     assert(auth_user->ipcount);
     auth_user->ipcount--;
 }
 
+typedef struct {
+    hash_link hash;		/* must be first */
+    struct in_addr ipaddr;
+    auth_user_request_t *auth_user_request;
+    time_t last_seen;
+} auth_user_request_ip_hash_t;
+MemPool *auth_user_request_ip_pool = NULL;
+hash_table *auth_user_request_ip_hash = NULL;
+
+static unsigned int
+hash_in_addr(const void *a, unsigned int size)
+{
+    const struct in_addr *ipaddr = a;
+    const uint32_t ip = ntohl(ipaddr->s_addr);
+    return ip % size;
+}
+
+static int
+cmp_in_addr(const struct in_addr *a, const struct in_addr *b)
+{
+    const uint32_t ipa = ntohl(a->s_addr);
+    const uint32_t ipb = ntohl(b->s_addr);
+
+    return memcmp(&ipa, &ipb, 4);
+}
+
+static void
+authenticateAuthUserRequestUnlinkIp(const struct in_addr ipaddr)
+{
+    auth_user_request_ip_hash_t *hash_entry;
+
+    if (!auth_user_request_ip_hash)
+	return;
+
+    hash_entry = hash_lookup(auth_user_request_ip_hash, &ipaddr);
+    if (hash_entry) {
+	hash_remove_link(auth_user_request_ip_hash, &hash_entry->hash);
+	authenticateAuthUserRequestUnlock(hash_entry->auth_user_request);
+	memPoolFree(auth_user_request_ip_pool, hash_entry);
+    }
+}
+
+static void
+authenticateAuthUserRequestLinkIp(auth_user_request_t * auth_user_request, const struct in_addr ipaddr)
+{
+    auth_user_request_ip_hash_t *hash_entry;
+
+    if (!Config.authenticateIpShortcircuitTTL)
+	return;
+
+    if (!auth_user_request_ip_hash) {
+	auth_user_request_ip_hash = hash_create((HASHCMP *) cmp_in_addr, 7921, hash_in_addr);
+	auth_user_request_ip_pool = memPoolCreate("auth_user_request_ip_hash_t", sizeof(auth_user_request_ip_hash_t));
+    }
+    authenticateAuthUserRequestUnlinkIp(ipaddr);
+
+    hash_entry = memPoolAlloc(auth_user_request_ip_pool);
+    hash_entry->ipaddr = ipaddr;
+    hash_entry->hash.key = &hash_entry->ipaddr;
+    hash_entry->auth_user_request = auth_user_request;
+    authenticateAuthUserRequestLock(hash_entry->auth_user_request);
+    hash_entry->last_seen = squid_curtime;
+    hash_join(auth_user_request_ip_hash, &hash_entry->hash);
+}
+
+static auth_user_request_t *
+authenticateAuthUserRequestFindByIp(const struct in_addr ipaddr)
+{
+    time_t delta = Config.authenticateIpShortcircuitTTL;
+    auth_user_request_ip_hash_t *hash_entry;
+    auth_user_request_t *auth_user_request = NULL;
+
+    if (!auth_user_request_ip_hash)
+	return NULL;
+
+    hash_entry = hash_lookup(auth_user_request_ip_hash, &ipaddr);
+    if (!hash_entry)
+	return NULL;
+
+    auth_user_request = hash_entry->auth_user_request;
+    if (hash_entry->last_seen + delta < squid_curtime) {
+	authenticateAuthUserRequestUnlinkIp(ipaddr);
+	return NULL;
+    }
+    return hash_entry->auth_user_request;
+}
+
 static void
 authenticateAuthUserRequestSetIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr)
 {
@@ -289,6 +378,8 @@
 	}
     }
 
+    authenticateAuthUserRequestLinkIp(auth_user_request, ipaddr);
+
     if (found)
 	return;
 
@@ -408,10 +499,14 @@
 	return *auth_user_request;
     else if (request && request->auth_user_request)
 	return request->auth_user_request;
-    else if (conn)
+    else if (conn && conn->auth_user_request)
 	return conn->auth_user_request;
-    else
-	return NULL;
+    else {
+	request->auth_user_request = authenticateAuthUserRequestFindByIp(request->client_addr);
+	if (request->auth_user_request)
+	    authenticateAuthUserRequestLock(request->auth_user_request);
+	return request->auth_user_request;
+    }
 }
 
 /* returns one of
Index: squid/src/cf.data.pre
diff -u squid/src/cf.data.pre:1.169 squid/src/cf.data.pre:1.161.8.3
--- squid/src/cf.data.pre:1.169	Sun Feb 25 03:54:34 2007
+++ squid/src/cf.data.pre	Sun Mar 11 15:05:47 2007
@@ -2131,6 +2131,15 @@
 	corporate LAN environment with relatively static address assignments.
 DOC_END
 
+NAME: authenticate_ip_shortcircuit_ttl
+TYPE: time_t
+LOC: Config.authenticateIpShortcircuitTTL
+DEFAULT: 0 seconds
+DOC_START
+	Cache authentication credentials per client IP address for this
+	long. Default is 0 seconds (disabled).
+DOC_END
+
 NAME: external_acl_type
 TYPE: externalAclHelper
 LOC: Config.externalAclHelperList
Index: squid/src/structs.h
diff -u squid/src/structs.h:1.142 squid/src/structs.h:1.136.8.3
--- squid/src/structs.h:1.142	Sun Mar 18 18:53:56 2007
+++ squid/src/structs.h	Mon Mar 26 19:59:44 2007
@@ -563,6 +563,7 @@
     time_t authenticateGCInterval;
     time_t authenticateTTL;
     time_t authenticateIpTTL;
+    time_t authenticateIpShortcircuitTTL;
     char *appendDomain;
     int appendDomainLen;
     char *debugOptions;