---------------------
PatchSet 634 
Date: 2000/10/15 06:06:37
Author: rbcollins
Branch: ntlm
Tag: (none) 
Log:
Fixed some nasty bugs. helpers are no longer referenced after authentication completes. No more stuck helpers! experimental CHALLENGE-AUTHENTICATION caching (use --enable-ntlm-auth-caching to try it out.

Members: 
	ntlm_auth_modules/fakeauth/fakeauth_auth.c:1.1.2.2->1.1.2.3 
	src/acl.c:1.1.1.3.12.19->1.1.1.3.12.20 
	src/authenticate.c:1.1.1.3.12.13->1.1.1.3.12.14 
	src/client_side.c:1.1.1.3.4.1.2.22->1.1.1.3.4.1.2.23 
	src/enums.h:1.1.1.3.12.10->1.1.1.3.12.11 
	src/helper.c:1.1.1.3.12.9->1.1.1.3.12.10 
	src/structs.h:1.1.1.3.4.1.2.18->1.1.1.3.4.1.2.19 
	src/typedefs.h:1.1.1.3.12.9->1.1.1.3.12.10 

Index: squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/ntlm_auth_modules/fakeauth/Attic/fakeauth_auth.c,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -r1.1.2.2 -r1.1.2.3
--- squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c	3 Aug 2000 22:24:34 -0000	1.1.2.2
+++ squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c	15 Oct 2000 06:06:37 -0000	1.1.2.3
@@ -227,6 +227,11 @@
 
 	if ((p = strchr(buf, '\n')) != NULL)
 	    *p = '\0';		/* strip \n */
+            if(strncasecmp(buf,"RESET",5)==0){
+                printf("RESET OK\n");
+                }
+            else
+            {
 
 	    ntlmMakeChallenge(&chal);
             fmt = "NTLM %s";
@@ -252,20 +257,22 @@
 		printf(ERR);
 	    } else */ 
 	    if(fgets(buf, 256, stdin) == NULL) exit(0);
+            if ((p = strchr(buf, '\n')) != NULL)
+                *p = '\0';          /* strip \n */
 	    if(strncasecmp(buf,"RESET",5)==0){
 		printf("RESET OK\n");
-}else
-{
-            cleartext=(char *)uudecode(buf);
-	    if(ntlmDecodeAuth((struct ntlm_authenticate *)cleartext, user, 256)){
-	        printf("ERR %s\n",user);
-	    }
-	    else
-	    {
-	        printf("OK %s\n",user);
-	    }
-}
-	    
-	}
+                }
+            else {
+                cleartext=(char *)uudecode(buf);
+  	        if(ntlmDecodeAuth((struct ntlm_authenticate *)cleartext, user, 256)){
+	            printf("ERR %s\n",user);
+	            }
+	        else
+	        {
+	            printf("OK %s\n",user);
+	            }
+                }
+         }
+	 }
     exit(0);
 }
Index: squid/src/acl.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/acl.c,v
retrieving revision 1.1.1.3.12.19
retrieving revision 1.1.1.3.12.20
diff -u -r1.1.1.3.12.19 -r1.1.1.3.12.20
--- squid/src/acl.c	13 Oct 2000 12:45:36 -0000	1.1.1.3.12.19
+++ squid/src/acl.c	15 Oct 2000 06:06:38 -0000	1.1.1.3.12.20
@@ -1,6 +1,6 @@
 
 /*
- * $Id: acl.c,v 1.1.1.3.12.19 2000/10/13 12:45:36 rbcollins Exp $
+ * $Id: acl.c,v 1.1.1.3.12.20 2000/10/15 06:06:38 rbcollins Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -1515,13 +1515,15 @@
             debug(28,0)("Username to be used is %s\n",authentry->authuser);
             checklist->conn->auth_state=AUTHENTICATE_STATE_DONE;
             xstrncpy(checklist->conn->authuser,authentry->authuser,USER_IDENT_SZ); 
-            authenticateNTLMStart("RESET", aclLookupProxyNTLMAuthDone, checklist, checklist->conn->authhelper);
+assert(checklist);
+            authenticateNTLMStart("RESET", aclLookupProxyNTLMAuthDone, checklist, checklist->conn->authhelper);            
             return; /* the rest of this function applies to cache misses */
           }
         }
 #endif
         debug(28,6)("aclLookupProxyStatefulAuthStart: Asking NTLM authenticator '%d' on FD '%d'\n",checklist->conn->authhelper,checklist->conn->fd);
     }
+assert(checklist);
     authenticateNTLMStart(sent_string, aclLookupProxyNTLMAuthDone, checklist, checklist->conn->authhelper);
 }
 #endif /*NTLM*/
@@ -2142,6 +2144,7 @@
 
         debug(28,0)("aclLookupProxyNTLMAuthDone: returned RESET OK from helper in state done - assuming this was a cache hit.\n");
              }
+          checklist->conn->authhelper= NULL;
     break;
     case AUTHENTICATE_STATE_NEGOTIATE:
         xstrncpy(checklist->conn->authchallenge,result,NTLM_CHALLENGE_SZ);
@@ -2192,7 +2195,7 @@
 		 debug(28,6)("aclLookupProxyNTLMAuthDone: failed NTLM authentication on FD:%d error '%s'\n",checklist->conn->fd,result);
              }
 	 assert(checklist->conn->authhelper);
-	checklist->conn->authhelper=0; /*clear the handler*/
+	 checklist->conn->authhelper=0; /*clear the handler*/
      break;
      }
     aclCheck(checklist);
Index: squid/src/authenticate.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/authenticate.c,v
retrieving revision 1.1.1.3.12.13
retrieving revision 1.1.1.3.12.14
diff -u -r1.1.1.3.12.13 -r1.1.1.3.12.14
--- squid/src/authenticate.c	13 Oct 2000 12:45:37 -0000	1.1.1.3.12.13
+++ squid/src/authenticate.c	15 Oct 2000 06:06:38 -0000	1.1.1.3.12.14
@@ -1,6 +1,6 @@
 
 /*
- * $Id: authenticate.c,v 1.1.1.3.12.13 2000/10/13 12:45:37 rbcollins Exp $
+ * $Id: authenticate.c,v 1.1.1.3.12.14 2000/10/15 06:06:38 rbcollins Exp $
  *
  * DEBUG: section 29    Authenticator
  * AUTHOR: Duane Wessels
@@ -60,6 +60,7 @@
 static helper *authenticators = NULL;
 #endif
 #ifdef USE_NTLM
+static HLPSCB authenticateNTLMHandleReply;
 static void authenticateStatefulStateFree(authenticateStatefulStateData * r);
 static statefulhelper *ntlmauthenticators = NULL;
 #endif
@@ -87,52 +88,66 @@
 #endif
 
 #ifdef USE_NTLM
-static int
+static stateful_helper_callback_t
 authenticateNTLMHandleReply(void *data, void * lastserver, char *reply)
 /*note: this is not as clean as it should be. the callback NTLMAuthDone should
  * be returning the value for Morerequests. */
 {
     authenticateStatefulStateData *r = data;
-    int valid,morerequests=0;
+    int valid;
+    stateful_helper_callback_t result = S_HELPER_UNKNOWN;
+    void *nextserver=NULL;
     char *t = NULL;
     debug(29, 5) ("authenticateNTLMHandleReply: Helper: '%d' {%s}\n", lastserver, reply ? reply : "<NULL>");
     if (reply) {
         if (strncasecmp(reply, "CH ", 3) == 0) {
 	    reply += 3;
-	    morerequests=1;
+	    result=S_HELPER_RESERVE;
+            nextserver=lastserver;
 	    debug(29,4)("authenticateNTLMHandleReply: helper '%d'\n",lastserver);
         } 
 	else if (strncasecmp(reply, "OK ", 3) == 0) {
-        /*give aclNTLM the full header - they must know when it's ok, and 'ERR' _could_ collide with valid domain */
-	/* we're finished, leave release the helper*/
-	morerequests=0;
+            /*give aclNTLM the full header - they must know when it's ok, and 'ERR' _could_ collide with valid domain */
+	    /* we're finished, leave release the helper*/
+	    result=S_HELPER_RELEASE;
         } 
 	else if (strncasecmp(reply, "RESET OK", 8) == 0) {
-        /* Helper successfully reset */
-	/* note a reset request returning here MUST NOT set morerequests=1*/
-	morerequests=0;
+            /* Helper successfully reset */
+	    /* note a reset request returning here MUST NOT reserve the helper */
+	    result=S_HELPER_RELEASE;
         } 
 	else if (strncasecmp(reply, "ERR", 3) == 0) {
        {
-            morerequests=0; /*some error has occured. no more requests */
+            result=S_HELPER_RELEASE; /*some error has occured. no more requests */
             if ((t = strchr(reply, ' ')))/* strip after a space */
 		    *t = '\0';
             }
         } else 
 	{
-		debug(29, 1) ("authenticateNTLMHandleReply: Unsupported helper response, '%s'\n", reply);
-   	//	fatal("unknown helper response");
-	    }
+	    debug(29, 1) ("authenticateNTLMHandleReply: Unsupported helper response, '%s'\n", reply);
+   	//	fatal("unknown stateful helper response"); //
+	}
 
 	if (*reply == '\0')
 	    reply = NULL;
     }
+    else
+    {
+        fatal("authenticateNTLMHandleReply: called with no result string\n");
+    }
     valid = cbdataValid(r->data);
     cbdataUnlock(r->data);
     if (valid)
-	r->handler(r->data, lastserver, reply);
+	r->handler(r->data, nextserver, reply);
+    else
+    {
+        debug(29,1) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%d'.\n",lastserver);
+        result=S_HELPER_RELEASE;
+    }
+//    cbdataUnlock(r->data);
     authenticateStatefulStateFree(r);
-    return morerequests;
+    debug(29,5)("NTLM HandleReply, telling stateful helper : %d\n",result);
+    return result;
 }
 #endif
 
@@ -205,8 +220,9 @@
 {
     authenticateStatefulStateData *r = NULL;
     char buf[8192];
-/*    assert(auth_user);*/
+    assert(proxy_auth);
     assert(handler);
+    assert(data);
     debug(29, 5) ("authenticateNTLMStart: '%s'\n", proxy_auth);
     if (Config.Program.ntlmauthenticate == NULL) {
         debug(29, 5) ("authenticateNTLMStart: no NTLM program specified:'%s'\n", proxy_auth);
Index: squid/src/client_side.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v
retrieving revision 1.1.1.3.4.1.2.22
retrieving revision 1.1.1.3.4.1.2.23
diff -u -r1.1.1.3.4.1.2.22 -r1.1.1.3.4.1.2.23
--- squid/src/client_side.c	13 Oct 2000 12:45:37 -0000	1.1.1.3.4.1.2.22
+++ squid/src/client_side.c	15 Oct 2000 06:06:38 -0000	1.1.1.3.4.1.2.23
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.c,v 1.1.1.3.4.1.2.22 2000/10/13 12:45:37 rbcollins Exp $
+ * $Id: client_side.c,v 1.1.1.3.4.1.2.23 2000/10/15 06:06:38 rbcollins Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -793,20 +793,17 @@
     cbdataFree(http);
 }
 
-#if defined (USE_NTLM) /* || defined (USE_BASIC) etc */
+#if defined (USE_NTLM) /* || defined (USE_DIGEST) etc */
 /* This just releases the stateful helper used by a connection */
 static void
 connStateFreeHelperDone(void * data, void * lastserver, char * result)
 {
-    ConnStateData *connState = data;
-    assert(!data);
-    if (result && (strncasecmp(result, "OK", 2) != 0)){
+    ConnCloseHelperData *r = data;
+    assert(r); /* if we don't have data, then we are making a memory leak */
+    if (result && (strncasecmp(result, "RESET OK", 2) != 0)){
         debug(33,1)("connStateFreeHelperDone: error resetting stateful helper, result '%s'.\n",result);
     }
-#ifdef USE_NTLM
-    connState->authhelper=0;
-#endif
-    connStateFree(connState->fd,data);
+    cbdataFree(r);
 }
 #endif
 
@@ -820,8 +817,13 @@
     assert(connState != NULL);
 #ifdef USE_NTLM
     if (connState->authhelper){
-        debug(33,4)("connStateFree: FD %d releasing helper %d.\n",fd,connState->authhelper);
-	authenticateNTLMStart("RESET",connStateFreeHelperDone,connState,connState->authhelper);
+        ConnCloseHelperData *r;
+        debug(33,1)("connStateFree: FD %d releasing helper %d.\n",fd,connState->authhelper);
+        r=xcalloc(1, sizeof(ConnCloseHelperData));
+        cbdataAdd(r, cbdataXfree, 0);
+
+        authenticateNTLMStart("RESET",connStateFreeHelperDone,r,connState->authhelper);
+        connState->authhelper=NULL;
 	}
 #endif
     clientdbEstablished(connState->peer.sin_addr, -1);	/* decrement */
Index: squid/src/enums.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/enums.h,v
retrieving revision 1.1.1.3.12.10
retrieving revision 1.1.1.3.12.11
diff -u -r1.1.1.3.12.10 -r1.1.1.3.12.11
--- squid/src/enums.h	13 Oct 2000 12:45:37 -0000	1.1.1.3.12.10
+++ squid/src/enums.h	15 Oct 2000 06:06:38 -0000	1.1.1.3.12.11
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.1.1.3.12.10 2000/10/13 12:45:37 rbcollins Exp $
+ * $Id: enums.h,v 1.1.1.3.12.11 2000/10/15 06:06:38 rbcollins Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -517,6 +517,13 @@
 #endif
 } auth_state_t;
 
+/* stateful helper callback response codes */
+typedef enum {
+    S_HELPER_UNKNOWN,
+    S_HELPER_RESERVE,
+    S_HELPER_RELEASE
+} stateful_helper_callback_t;
+
 #if SQUID_SNMP
 enum {
     SNMP_C_VIEW,
Index: squid/src/helper.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/helper.c,v
retrieving revision 1.1.1.3.12.9
retrieving revision 1.1.1.3.12.10
diff -u -r1.1.1.3.12.9 -r1.1.1.3.12.10
--- squid/src/helper.c	9 Oct 2000 22:15:58 -0000	1.1.1.3.12.9
+++ squid/src/helper.c	15 Oct 2000 06:06:38 -0000	1.1.1.3.12.10
@@ -1,6 +1,6 @@
 
 /*
- * $Id: helper.c,v 1.1.1.3.12.9 2000/10/09 22:15:58 rbcollins Exp $
+ * $Id: helper.c,v 1.1.1.3.12.10 2000/10/15 06:06:38 rbcollins Exp $
  *
  * DEBUG: section 29    Helper process maintenance
  * AUTHOR: Harvest Derived?
@@ -181,6 +181,7 @@
 	srv = memAllocate(MEM_HELPER_STATEFUL_SERVER);
 	cbdataAdd(srv, memFree, MEM_HELPER_STATEFUL_SERVER);
 	srv->flags.alive = 1;
+        srv->flags.reserved = 0;
 	srv->index = k;
 	srv->rfd = rfd;
 	srv->wfd = wfd;
@@ -246,6 +247,7 @@
     r->buf = xstrdup(buf);
     cbdataLock(r->data);
     if (lastserver){
+        debug(29,5)("StatefulSubmit with lastserver %d\n",lastserver);
 	helperStatefulDispatch(lastserver, r);
     }
     else
@@ -265,7 +267,7 @@
  * manage the state in the helper
  */
 {
-    helper * hlp = srv->parent;
+    statefulhelper * hlp = srv->parent;
     helper_stateful_request * r;
     r = srv->request;
     if (r != NULL) {
@@ -278,7 +280,9 @@
         srv->request = NULL;
     }
     helperKickQueue(hlp);
+    debug(29,1)("helperStatefulReset reset helper %s #%d\n",hlp->id_name,srv->index+1);
     srv->flags.busy = 0;
+    srv->flags.reserved=0;
 }
 
 void
@@ -356,13 +360,14 @@
     for (link = hlp->servers.head; link; link = link->next) {
         srv = link->data;
         tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time);
-        storeAppendPrintf(sentry, "%7d\t%7d\t%11d\t%c%c%c%c\t%7.3f\t%7d\t%s\n",
+        storeAppendPrintf(sentry, "%7d\t%7d\t%11d\t%c%c%c%c%c\t%7.3f\t%7d\t%s\n",
             srv->index + 1,
             srv->rfd,
             srv->stats.uses,
             srv->flags.alive ? 'A' : ' ',
             srv->flags.busy ? 'B' : ' ',
             srv->flags.closing ? 'C' : ' ',
+            srv->flags.reserved ? 'R': ' ',
             srv->flags.shutdown ? 'S' : ' ',
             tt < 0.0 ? 0.0 : tt,
             (int) srv->offset,
@@ -429,6 +434,11 @@
 		hlp->id_name, srv->index + 1);
 	    continue;
 	}
+        if (srv->flags.reserved) {
+            debug(34, 3) ("helperStatefulShutdown: %s #%d is RESERVED.\n",
+                hlp->id_name, srv->index + 1);
+            continue;
+        }
 	srv->flags.closing = 1;
 	comm_close(srv->wfd);
 	srv->wfd = -1;
@@ -448,7 +458,7 @@
 helper *
 helperStatefulCreate(const char *name)
 {
-    helper *hlp = memAllocate(MEM_HELPER_STATEFUL);
+    statefulhelper *hlp = memAllocate(MEM_HELPER_STATEFUL);
     cbdataAdd(hlp, memFree, MEM_HELPER_STATEFUL);
     hlp->id_name = name;
     return hlp;
@@ -632,9 +642,27 @@
 	/* end of reply found */
 	debug(29, 3) ("helperStatefulHandleRead: end of reply found\n");
 	*t = '\0';
-	if (cbdataValid(r->data))
-	    if(!(r->callback(r->data,srv, srv->buf))) /*if non-zero reserve helper */
-	    	srv->flags.busy = 0;
+	if (cbdataValid(r->data)){
+	    switch((r->callback(r->data,srv, srv->buf))){ /*if non-zero reserve helper */
+	         case S_HELPER_UNKNOWN:
+                     fatal("helperStatefulHandleRead: either a non-state aware callback was give to the stateful helper routines, or an uninitialised callback response was recieved.\n");
+                     break;
+                 case S_HELPER_RELEASE:
+                     srv->flags.reserved = 0;
+                     debug(29, 5)("StatefulHandleRead: releasing %s #%d\n",hlp->id_name, srv->index+1);
+                     break;
+                 case S_HELPER_RESERVE:
+                     srv->flags.reserved = 1;
+                     debug(29, 5)("StatefulHandleRead: reserving %s #%d\n",hlp->id_name, srv->index+1);
+                     break;
+                 default:
+                     fatal("helperStatefulHandleRead: unknown stateful helper callback result.\n");
+                 }
+             
+            }
+        else
+        {debug(29,1)("StatefulHandleRead: no callback data registered\n");}
+        srv->flags.busy = 0;
 	srv->offset = 0;
 	helperStatefulRequestFree(r);
 	srv->request = NULL;
@@ -674,7 +702,7 @@
 }
 
 static void
-StatefulEnqueue(helper * hlp, helper_stateful_request * r)
+StatefulEnqueue(statefulhelper * hlp, helper_stateful_request * r)
 {
     dlink_node *link = memAllocate(MEM_DLINK_NODE);
     dlinkAddTail(r, link, &hlp->queue);
@@ -752,6 +780,8 @@
 	srv = n->data;
 	if (srv->flags.busy)
 	    continue;
+        if (srv->flags.reserved)
+            continue;
 	if (!srv->flags.alive)
 	    continue;
     	return srv;
@@ -792,13 +822,14 @@
 static void
 helperStatefulDispatch(helper_stateful_server * srv, helper_stateful_request * r)
 {
-    helper *hlp = srv->parent;
+    statefulhelper *hlp = srv->parent;
         if (!cbdataValid(r->data)) {
 	debug(29, 1) ("helperStatefulDispatch: invalid callback data\n");
 	helperStatefulRequestFree(r);
 	return;
     }
     /* we keep ourselves busy when we're in a state request. */
+   debug(29,9)("helperStatefulDispatch busying helper %s #%d\n",hlp->id_name,srv->index+1);
     srv->flags.busy = 1;
     srv->request = r;
     srv->dispatch_time = current_time;
Index: squid/src/structs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/structs.h,v
retrieving revision 1.1.1.3.4.1.2.18
retrieving revision 1.1.1.3.4.1.2.19
diff -u -r1.1.1.3.4.1.2.18 -r1.1.1.3.4.1.2.19
--- squid/src/structs.h	13 Oct 2000 12:45:37 -0000	1.1.1.3.4.1.2.18
+++ squid/src/structs.h	15 Oct 2000 06:06:38 -0000	1.1.1.3.4.1.2.19
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.1.1.3.4.1.2.18 2000/10/13 12:45:37 rbcollins Exp $
+ * $Id: structs.h,v 1.1.1.3.4.1.2.19 2000/10/15 06:06:38 rbcollins Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -950,6 +950,11 @@
     } defer;
 };
 
+/* this is an ugly hack. We need to pass callback data to NTLMStart, when we reset a stateful helper being used when a comms interruption occurs during the negotiate-challenge-authenticate transactions */
+struct _ConnCloseHelperData {
+   int dummy;
+};
+
 struct _ipcache_addrs {
     struct in_addr *in_addrs;
     unsigned char *bad_mask;
@@ -1885,7 +1890,13 @@
     dlink_node link;
     helper *parent;
     helper_stateful_request *request;
-    struct _helper_flags flags;
+    struct _helper_stateful_flags {
+        unsigned int alive:1;
+        unsigned int busy:1;
+        unsigned int closing:1;
+        unsigned int shutdown:1;
+        unsigned int reserved:1;
+    } flags;
     struct {
 	int uses;
     } stats;
Index: squid/src/typedefs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v
retrieving revision 1.1.1.3.12.9
retrieving revision 1.1.1.3.12.10
diff -u -r1.1.1.3.12.9 -r1.1.1.3.12.10
--- squid/src/typedefs.h	13 Oct 2000 12:45:38 -0000	1.1.1.3.12.9
+++ squid/src/typedefs.h	15 Oct 2000 06:06:38 -0000	1.1.1.3.12.10
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.1.1.3.12.9 2000/10/13 12:45:38 rbcollins Exp $
+ * $Id: typedefs.h,v 1.1.1.3.12.10 2000/10/15 06:06:38 rbcollins Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -106,6 +106,7 @@
 typedef struct _icpUdpData icpUdpData;
 typedef struct _clientHttpRequest clientHttpRequest;
 typedef struct _ConnStateData ConnStateData;
+typedef struct _ConnCloseHelperData ConnCloseHelperData;
 typedef struct _ipcache_addrs ipcache_addrs;
 typedef struct _domain_ping domain_ping;
 typedef struct _domain_type domain_type;
@@ -135,6 +136,7 @@
 typedef struct _SwapDir SwapDir;
 typedef struct _request_flags request_flags;
 typedef struct _helper_flags helper_flags;
+typedef struct _helper_stateful_flags helper_stateful_flags;
 typedef struct _http_state_flags http_state_flags;
 typedef struct _request_t request_t;
 typedef struct _AccessLogEntry AccessLogEntry;
@@ -235,7 +237,7 @@
 typedef void SIGHDLR(int sig);
 typedef void STVLDCB(void *, int, int);
 typedef void HLPCB(void *, char *buf);
-typedef int HLPSCB(void *, void * lastserver, char *buf);
+typedef stateful_helper_callback_t HLPSCB(void *, void * lastserver, char *buf);
 typedef void HLPCMDOPTS(int *argc, char **argv);
 typedef void IDNSCB(void *, rfc1035_rr *, int);
 
