]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Error page triggering. ip cache documentation.
authorkostas <>
Fri, 17 Oct 1997 01:22:35 +0000 (01:22 +0000)
committerkostas <>
Fri, 17 Oct 1997 01:22:35 +0000 (01:22 +0000)
13 files changed:
TODO
doc/Programming-Guide/prog-guide.sgml
errors/English/ERR_DNS_FAIL
include/util.h
src/defines.h
src/enums.h
src/errorpage.cc
src/gopher.cc
src/mime.cc
src/squid.h
src/store_dir.cc
src/tools.cc
src/wais.cc

diff --git a/TODO b/TODO
index 5dd289e27cfdd12ef20300d3175c5dd9ebfeb599..33cb95287128a01e270158fb78a34a9f1dcac02d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,5 @@
++ s/sprintf/snprintf/g
+
 
 + Write the text for all the error message files
 + we don't properly handle the HTTP/1.1 'Connection' header
@@ -5,7 +7,6 @@
 + make USE_PROXY_AUTH standard
 + Incorporate Pelletier's latest retry patch for 1.1
 + FTP PUT
-+ s/sprintf/snprintf/g
 + be more persistent in forwarding requests; return fewer error pages
 + AS # routing
 + Send full HTTP requests in ICP messages
index 0968edd0483cd7e00ae34ec33f60e5254b91470a..1b66c3f0a5f3bcc2e8a9c23d07b71e3fa3cceeb2 100644 (file)
@@ -298,6 +298,50 @@ chapter.
 <!-- %%%% Chapter : IP CACHE %%%% -->
 <sect>IP Cache
 
+<P>
+The IP cache is a built-in component of squid providing
+Hostname to IP-Number translation functionality and managing 
+the involved data-structures . It usually 
+doesn't block on a request except for special cases where this
+is desired (explained below).
+The data structure used for storing name-address mappings
+is a small hashtable (<em>static hash_table *ip_table</em>),
+where structures of type <em>ipcache_entry</em> whose most
+interesting members are:
+<verb>
+struct _ipcache_entry {
+char *name;
+time_t lastref;
+ipcache_addrs addrs;
+struct _ip_pending *pending_head;
+char *error_message;
+unsigned char locks;
+ipcache_status_t status:3;
+}
+</verb>
+
+Main functionality
+is provided through calls to:
+<descrip>
+<tag>ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerdata)
+</tag>
+where <em/name/ is the name of the host to resolve, <em/handler/ is a 
+pointer to the function to be called when the reply from the IP cache (or
+the DNS if the IP cache misses) and <em/handlerdata/ is information that
+is passed to the handler and does not affect the IP cache.
+<tag>ipcache_gethostbyname(const char *name,int flags)</tag>
+is different in that
+it only checks if an entry exists in it's data-structures and does not by
+default contact the DNS, unless this is requested, by setting the <em/flags/ to
+<em/IP_BLOCKING_LOOKUP/ or <em/IP_LOOKUP_IF_MISS/.
+<tag>ipcache_init()</tag> is called from <em/mainInitialize()/ after disk
+initialization and prior to the reverse fqdn cache initialization
+<tag>ipcache_restart()</tag> is called to clear the IP cache's data structures,
+cancel all pending requests. Currently, it is only called from
+<em/mainReconfigure/.
+</descrip>
+
+
 <!-- %%%% Chapter : SERVER PROTOCOLS %%%% -->
 <sect>Server Protocols
 <sect1>HTTP
index c0f8c60ddcbd2c5e954336081a2c55836fe1f518..ba17979e145fc3e2db1eac819713341c937d96f5 100644 (file)
@@ -23,6 +23,7 @@ The dnsserver returned:
 <P>
 This means that:
 <PRE>
-    @LONG_DESCRIPTION@
+ The cache was not able to resolve the hostname presented in the URL. 
+ Check if the address is correct. 
 </PRE>
 
index f77044283abba5d3d3433d5944ae7aaea1d70281..32d8c6e4539fb06144bd0ea32ee8f4eef44b13b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: util.h,v 1.31 1997/07/16 20:31:53 wessels Exp $
+ * $Id: util.h,v 1.32 1997/10/16 19:22:36 kostas Exp $
  *
  * AUTHOR: Harvest Derived
  *
@@ -133,6 +133,7 @@ extern const char *mkrfc1123 _PARAMS((time_t));
 extern char *uudecode _PARAMS((const char *));
 extern char *xstrdup _PARAMS((const char *));
 extern const char *xstrerror _PARAMS((void));
+extern const char *xbstrerror _PARAMS((int));
 extern int tvSubMsec _PARAMS((struct timeval, struct timeval));
 extern int tvSubUsec _PARAMS((struct timeval, struct timeval));
 extern char *xstrncpy _PARAMS((char *, const char *, size_t));
index 83b21d44a9a39b41174d37a6c15c23c19814fc5b..488dca748dc3e44aba4f89f4aac62fe850a9c577 100644 (file)
 #define AUTH_MSG_SZ 4096
 #define HTTP_REPLY_BUF_SZ 4096
 
+#if !defined(ERROR_BUF_SZ) && defined(MAX_URL)
+#define ERROR_BUF_SZ (MAX_URL << 2)
+#endif
+
 #define HTTP_PROXYING          (1<<0)
 #define HTTP_KEEPALIVE         (1<<1)
index ab8d6b050a04d0a91fefad144d5c8d58816c9453..69ea369be957febcd65e55fa9c97cd3f388eda9e 100644 (file)
@@ -22,6 +22,7 @@ typedef enum {
 
 typedef enum {
     ERR_NONE,
+    ERR_NO_CLIENTS,
     ERR_READ_TIMEOUT,
     ERR_LIFETIME_EXP,
     ERR_READ_ERROR,
index 9b4728ca427842c12cb1193847ff29960cddebf1..0f5fdbaa04c3b55b0c6c5c2cf3b15eaf1d37390f 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: errorpage.cc,v 1.71 1997/10/14 18:24:32 wessels Exp $
+ * $Id: errorpage.cc,v 1.72 1997/10/16 19:22:38 kostas Exp $
  *
  * DEBUG: section 4     Error Generation
  * AUTHOR: Duane Wessels
@@ -131,7 +131,13 @@ errorConvert(char token, ErrorState * err)
        p=buf;
        break;
     case 'E':
-       snprintf(buf, CVT_BUF_SZ, "(%d) %s", err->errno, xstrerror());
+       snprintf(buf, CVT_BUF_SZ, "(%d) %s", err->errno,xbstrerror(err->errno));
+       break;
+    case 'w':
+       snprintf(buf, CVT_BUF_SZ, "%s",Config.adminEmail);
+       break;
+    case 'h':
+       snprintf(buf, CVT_BUF_SZ, "%s", getMyHostname());
        break;
 /*
  * e - errno                                   x
@@ -142,10 +148,10 @@ errorConvert(char token, ErrorState * err)
  * I - server IP address
  * i - client IP address
  * L - HREF link for more info/contact
- * w - cachemgr email address
- * h - cache hostname
+ * w - cachemgr email address                  x
+ * h - cache hostname                          x
  * d - seconds elapsed since request received
- * p - URL port #
+ * p - URL port #                              x
  */
     default:
        p = "%UNKNOWN%";
@@ -157,8 +163,6 @@ errorConvert(char token, ErrorState * err)
     return p;
 }
 
-#define ERROR_BUF_SZ (MAX_URL<<2)
-
 static char *
 errorBuildBuf(ErrorState * err, int *len)
 {
index b8ca98fe82acae3bde813ba1e40404f91a28f3f8..6dd5cfa43cbef0f6e3ff864762c7cadaa7593e5e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: gopher.cc,v 1.94 1997/10/14 16:56:04 wessels Exp $
+ * $Id: gopher.cc,v 1.95 1997/10/16 19:22:38 kostas Exp $
  *
  * DEBUG: section 10    Gopher
  * AUTHOR: Harvest Derived
@@ -650,8 +650,17 @@ gopherTimeout(int fd, void *data)
 {
     GopherStateData *gopherState = data;
     StoreEntry *entry = gopherState->entry;
+    ErrorState *err;
+
     debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, entry->url);
-    assert(!ERR_READ_TIMEOUT);
+       /* was assert */
+    if (entry->object_len == 0)  {
+       err=xcalloc(1,sizeof(ErrorState));
+       err->type=ERR_READ_TIMEOUT;
+       err->http_status=HTTP_GATEWAY_TIMEOUT;
+       err->url=gopherState->request;
+       errorAppendEntry(entry, err);
+    }
     storeAbort(entry, 0);
     comm_close(fd);
 }
@@ -721,12 +730,26 @@ gopherReadReply(int fd, void *data)
                gopherReadReply,
                data, 0);
        } else {
-           assert(!ERR_READ_ERROR);
-           storeAbort(entry, 0);
-           comm_close(fd);
+                       /* was  assert */
+               ErrorState *err;
+               err=xcalloc(1,sizeof(ErrorState));
+               err->type=ERR_READ_ERROR;
+               err->errno=errno;
+               err->http_status=HTTP_INTERNAL_SERVER_ERROR;
+               err->url = entry->url;
+               errorAppendEntry(entry, err);
+               storeAbort(entry, 0);
+               comm_close(fd);
        }
     } else if (len == 0 && entry->mem_obj->e_current_len == 0) {
-       assert(!ERR_ZERO_SIZE_OBJECT);
+               /* was assert */        
+        ErrorState *err;
+        err=xcalloc(1,sizeof(ErrorState));
+        err->type=ERR_ZERO_SIZE_OBJECT;
+       err->errno = errno;
+        err->http_status=HTTP_SERVICE_UNAVAILABLE;
+       err->url=gopherState->request;
+        errorAppendEntry(entry, err);
        storeAbort(entry, 0);
        comm_close(fd);
     } else if (len == 0) {
@@ -764,7 +787,17 @@ gopherSendComplete(int fd, char *buf, int size, int errflag, void *data)
     debug(10, 5) ("gopherSendComplete: FD %d size: %d errflag: %d\n",
        fd, size, errflag);
     if (errflag) {
-       assert(!ERR_CONNECT_FAIL);
+               /* was assert */
+        ErrorState *err;
+        err=xcalloc(1,sizeof(ErrorState));
+        err->type=ERR_CONNECT_FAIL;
+       err->errno=errno;
+       err->host = xstrdup(gopherState->host);
+       err->port = gopherState->port;
+        err->http_status=HTTP_SERVICE_UNAVAILABLE;
+        err->url=entry->url;
+        errorAppendEntry(entry, err);
+
        storeAbort(entry, 0);
        comm_close(fd);
        if (buf)
@@ -839,6 +872,7 @@ gopherStart(StoreEntry * entry)
 {
     char *url = entry->url;
     GopherStateData *gopherState = CreateGopherStateData();
+    ErrorState *err;
     int fd;
     storeLockObject(entry);
     gopherState->entry = entry;
@@ -846,7 +880,14 @@ gopherStart(StoreEntry * entry)
     /* Parse url. */
     if (gopher_url_parser(url, gopherState->host, &gopherState->port,
            &gopherState->type_id, gopherState->request)) {
-       assert(!ERR_INVALID_URL);
+               /* was assert */
+                ErrorState *err;
+                err=xcalloc(1,sizeof(ErrorState));
+                err->type=ERR_INVALID_URL;
+                err->http_status=HTTP_BAD_REQUEST;
+                err->url=url;
+                errorAppendEntry(entry, err);
+
        storeAbort(entry, 0);
        gopherStateFree(-1, gopherState);
        return;
@@ -860,13 +901,39 @@ gopherStart(StoreEntry * entry)
        url);
     if (fd == COMM_ERROR) {
        debug(10, 4) ("gopherStart: Failed because we're out of sockets.\n");
-       assert(!ERR_SOCKET_FAILURE);
+               /* was assert */
+                err=xcalloc(1,sizeof(ErrorState));
+                err->type=ERR_SOCKET_FAILURE;
+               err->errno=errno;
+                err->http_status=HTTP_INTERNAL_SERVER_ERROR;
+               if (entry && entry->url)
+                       err->url=entry->url;
+                errorAppendEntry(entry, err);
+
        storeAbort(entry, 0);
        gopherStateFree(-1, gopherState);
        return;
     }
     comm_add_close_handler(fd, gopherStateFree, gopherState);
     storeRegisterAbort(entry, gopherAbort, gopherState);
+
+    /* check if IP is already in cache. It must be. 
+     * It should be done before this route is called. 
+     * Otherwise, we cannot check return code for connect. */
+    if (!ipcache_gethostbyname(gopherState->host, 0)) {
+       debug(10, 4) ("gopherStart: Called without IP entry in ipcache. OR lookup failed.\n");
+       /* was assert */
+        err=xcalloc(1,sizeof(ErrorState));
+        err->type=ERR_DNS_FAIL;
+       err->http_status = HTTP_SERVICE_UNAVAILABLE;
+        err->dnsserver_msg = xstrdup(dns_error_message);
+        err->url=entry->url;
+        errorAppendEntry(entry, err);
+       storeAbort(entry, 0);
+       comm_close(fd);
+       return;
+    }
+
     if (((gopherState->type_id == GOPHER_INDEX) || (gopherState->type_id == GOPHER_CSO))
        && (strchr(gopherState->request, '?') == NULL)) {
        /* Index URL without query word */
@@ -899,13 +966,31 @@ static void
 gopherConnectDone(int fd, int status, void *data)
 {
     GopherStateData *gopherState = data;
+    StoreEntry *entry = gopherState->entry;
+
+       ErrorState *err;
     if (status == COMM_ERR_DNS) {
        debug(10, 4) ("gopherConnectDone: Unknown host: %s\n", gopherState->host);
-       assert(!ERR_DNS_FAIL);
+       /* was assert */
+        err=xcalloc(1,sizeof(ErrorState));
+        err->type=ERR_DNS_FAIL;
+       err->dnsserver_msg = xstrdup(dns_error_message);
+        err->http_status=HTTP_SERVICE_UNAVAILABLE;
+        err->url=entry->url;
+        errorAppendEntry(entry, err);
        storeAbort(gopherState->entry, 0);
        comm_close(fd);
     } else if (status != COMM_OK) {
-       assert(!ERR_CONNECT_FAIL);
+       /* was assert */
+        ErrorState *err;
+        err=xcalloc(1,sizeof(ErrorState));
+        err->type=ERR_CONNECT_FAIL;
+        err->http_status=HTTP_SERVICE_UNAVAILABLE;
+       err->errno= errno;
+       err->host = xstrdup(gopherState->host);
+       err->port = gopherState->port;
+        err->url=entry->url;
+        errorAppendEntry(entry, err);
        storeAbort(gopherState->entry, 0);
        comm_close(fd);
     } else {
index df66e8a2232ace6cbac6b218f2e7f9c252b14620..4e8907fb2d6f2ec6184642bfc64630584ba94091 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: mime.cc,v 1.38 1997/10/13 22:09:16 kostas Exp $
+ * $Id: mime.cc,v 1.39 1997/10/16 19:22:39 kostas Exp $
  *
  * DEBUG: section 25    MIME Parsing
  * AUTHOR: Harvest Derived
@@ -223,7 +223,7 @@ mk_mime_hdr(char *result, const char *type, int size, time_t ttl, time_t lmt)
        /* NOTE: don't know size of result thus didn't change
           to snprintf(). Should be done sometime! */
 
-    sprintf(result, "Server: %s/%s\r\n%s%s%sContent-Type: %s\r\n%s",
+    snprintf(result, MAX_MIME, "Server: %s/%s\r\n%s%s%sContent-Type: %s\r\n%s",
        appname,
        version_string,
        date,
index 8b687525240d8b45eb9c289dbc2b1dd26a48e1e1..23577d6157402a2c73bf325eacb7a8c0eb676a36 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: squid.h,v 1.129 1997/07/16 20:32:16 wessels Exp $
+ * $Id: squid.h,v 1.130 1997/10/16 19:22:40 kostas Exp $
  *
  * AUTHOR: Duane Wessels
  *
 #define BUFSIZ  4096           /* make reasonable guess */
 #endif
 
+
 #ifndef SA_RESTART
 #define SA_RESTART 0
 #endif
index 494f56170004c7e2c38bdbfe9fc0c8976f2d378e..aebf9b7451299a347c5477f66aa559f38779af2b 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir.cc,v 1.28 1997/10/13 22:09:23 kostas Exp $
+ * $Id: store_dir.cc,v 1.29 1997/10/16 19:22:41 kostas Exp $
  *
  * DEBUG: section 47    Store Directory Routines
  * AUTHOR: Duane Wessels
@@ -82,9 +82,10 @@ storeVerifyOrCreateDir(const char *path)
     safeunlink(path, 1);
     if (mkdir(path, 0777) < 0) {
        if (errno != EEXIST) {    
-         /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
-               change to snprintf()  ... yet */
-           sprintf(tmp_error_buf, "Failed to create swap directory %s: %s",
+         /* NOTE: couldn't figure size of tmp_error_buf, assumed
+               ERROR_BUF_SZ */
+           snprintf(tmp_error_buf, ERROR_BUF_SZ,
+               "Failed to create swap directory %s: %s",
                path,
                xstrerror());
            fatal(tmp_error_buf);
@@ -92,9 +93,9 @@ storeVerifyOrCreateDir(const char *path)
     }
     debug(47, 1) ("Created directory %s\n", path);
     if (stat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) {
-          /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
-                change to snprintf()  ... yet */
-       sprintf(tmp_error_buf,
+          /* NOTE: couldn't figure size of tmp_error_buf, assumed
+                ERROR_BUF_SZ */
+       snprintf(tmp_error_buf, ERROR_BUF_SZ, 
            "Failed to create directory %s: %s", path, xstrerror());
        fatal(tmp_error_buf);
     }
index bcbd98f7c64ff968a820476db2798d909a2fccb1..243262c3ea546608ecdfc87756f54765b0168dd4 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: tools.cc,v 1.121 1997/10/13 22:09:24 kostas Exp $
+ * $Id: tools.cc,v 1.122 1997/10/16 19:22:41 kostas Exp $
  *
  * DEBUG: section 21    Misc Functions
  * AUTHOR: Harvest Derived
@@ -250,6 +250,7 @@ PrintRusage(void)
 #endif /* HAVE_GETRUSAGE */
 }
 
+
 void
 death(int sig)
 {
@@ -658,9 +659,10 @@ setMaxFD(void)
        if (rl.rlim_cur > rl.rlim_max)
            Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
        if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
-          /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
-                change to snprintf()  ... yet */
-           sprintf(tmp_error_buf, "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
+          /* NOTE: couldn't figure size of tmp_error_buf, thus 
+                 assuming ERROR_BUF_SZ */
+           snprintf(tmp_error_buf, ERROR_BUF_SZ, 
+                       "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
            fatal_dump(tmp_error_buf);
        }
     }
@@ -672,9 +674,10 @@ setMaxFD(void)
        if (rl.rlim_cur > rl.rlim_max)
            Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
        if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
-          /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
-                change to snprintf()  ... yet */
-           sprintf(tmp_error_buf, "setrlimit: RLIMIT_OFILE: %s", xstrerror());
+          /* NOTE: couldn't figure size of tmp_error_buf, thus
+                assuming ERROR_BUF_SZ  */
+           snprintf(tmp_error_buf, ERROR_BUF_SZ, 
+                       "setrlimit: RLIMIT_OFILE: %s", xstrerror());
            fatal_dump(tmp_error_buf);
        }
     }
@@ -689,9 +692,10 @@ setMaxFD(void)
     } else if (rl.rlim_max > rl.rlim_cur) {
        rl.rlim_cur = rl.rlim_max;      /* set it to the max */
        if (setrlimit(RLIMIT_DATA, &rl) < 0) {
-          /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
-                change to snprintf()  ... yet */
-           sprintf(tmp_error_buf, "setrlimit: RLIMIT_DATA: %s", xstrerror());
+          /* NOTE: couldn't figure size of tmp_error_buf, thus d
+                assuming ERROR_BUF_SZ  */
+           snprintf(tmp_error_buf, ERROR_BUF_SZ, 
+                       "setrlimit: RLIMIT_DATA: %s", xstrerror());
            fatal_dump(tmp_error_buf);
        }
     }
@@ -702,9 +706,10 @@ setMaxFD(void)
     } else if (rl.rlim_max > rl.rlim_cur) {
        rl.rlim_cur = rl.rlim_max;      /* set it to the max */
        if (setrlimit(RLIMIT_VMEM, &rl) < 0) {
-          /* NOTE: couldn't figure size of tmp_error_buf, thus didn't
-                change to snprintf()  ... yet */
-           sprintf(tmp_error_buf, "setrlimit: RLIMIT_VMEM: %s", xstrerror());
+          /* NOTE: couldn't figure size of tmp_error_buf, thus 
+                assuming ERROR_BUF_SZ  */
+           snprintf(tmp_error_buf, ERROR_BUF_SZ, 
+                       "setrlimit: RLIMIT_VMEM: %s", xstrerror());
            fatal_dump(tmp_error_buf);
        }
     }
index 0cf694a2397da858002225f509605c5325d1988c..a9dd3dc61174b2d36ae2b0ecd61445b9eadfe346 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: wais.cc,v 1.82 1997/10/14 18:31:28 wessels Exp $
+ * $Id: wais.cc,v 1.83 1997/10/16 19:22:42 kostas Exp $
  *
  * DEBUG: section 24    WAIS Relay
  * AUTHOR: Harvest Derived
@@ -142,9 +142,16 @@ static void
 waisTimeout(int fd, void *data)
 {
     WaisStateData *waisState = data;
+    ErrorState *err;
     StoreEntry *entry = waisState->entry;
     debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, entry->url);
-    assert(!ERR_READ_TIMEOUT);
+       /* was assert */
+    err = xcalloc(1, sizeof(ErrorState));
+    err->type = ERR_READ_TIMEOUT;
+    err->http_status = HTTP_GATEWAY_TIMEOUT;
+    err->request = urlParse(METHOD_CONNECT, waisState->request);
+    errorAppendEntry(entry, err);
+
     storeAbort(entry, 0);
     comm_close(fd);
 }
@@ -164,13 +171,26 @@ waisReadReply(int fd, void *data)
     int off;
     int bin;
     if (protoAbortFetch(entry)) {
-       assert(!ERR_CLIENT_ABORT);
+       /* was assert */
+       ErrorState *err;
+       err = xcalloc(1, sizeof(ErrorState));
+       err->type = ERR_CLIENT_ABORT;
+       err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+       err->request = urlParse(METHOD_CONNECT, waisState->request);
+       errorAppendEntry(entry, err);
        storeAbort(entry, 0);
        comm_close(fd);
        return;
     }
     if (entry->flag & DELETE_BEHIND && !storeClientWaiting(entry)) {
        /* we can terminate connection right now */
+       /* was assert */
+        ErrorState *err;
+        err = xcalloc(1, sizeof(ErrorState));
+        err->type = ERR_NO_CLIENTS;
+        err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+        err->request = urlParse(METHOD_CONNECT, waisState->request);
+        errorAppendEntry(entry, err);
        storeAbort(entry, 0);
        comm_close(fd);
        return;
@@ -218,14 +238,30 @@ waisReadReply(int fd, void *data)
            commSetSelect(fd, COMM_SELECT_READ,
                waisReadReply, waisState, 0);
        } else {
+               ErrorState *err;
            BIT_RESET(entry->flag, ENTRY_CACHABLE);
            storeReleaseRequest(entry);
-           assert(!ERR_READ_ERROR);
+       /* was assert */
+
+            err = xcalloc(1, sizeof(ErrorState));
+            err->type = ERR_READ_ERROR;
+            err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+            err->request = urlParse(METHOD_CONNECT, waisState->request);
+            errorAppendEntry(entry, err);
+
            storeAbort(entry, 0);
            comm_close(fd);
        }
     } else if (len == 0 && entry->mem_obj->e_current_len == 0) {
-       assert(!ERR_ZERO_SIZE_OBJECT);
+               /* was assert */
+            ErrorState *err;
+            err = xcalloc(1, sizeof(ErrorState));
+            err->type = ERR_ZERO_SIZE_OBJECT;
+            err->errno = errno;
+            err->http_status = HTTP_SERVICE_UNAVAILABLE;
+            err->request = urlParse(METHOD_CONNECT, waisState->request);
+            errorAppendEntry(entry, err);
+
        storeAbort(entry, 0);
        comm_close(fd);
     } else if (len == 0) {
@@ -252,7 +288,17 @@ waisSendComplete(int fd, char *buf, int size, int errflag, void *data)
     debug(24, 5) ("waisSendComplete: FD %d size: %d errflag: %d\n",
        fd, size, errflag);
     if (errflag) {
-       assert(!ERR_CONNECT_FAIL);
+       /* was assert */
+            ErrorState *err;
+            err = xcalloc(1, sizeof(ErrorState));
+            err->type = ERR_CONNECT_FAIL;
+            err->errno=errno;
+            err->host =xstrdup(waisState->relayhost);
+            err->port = waisState->relayport;
+            err->http_status = HTTP_SERVICE_UNAVAILABLE;
+            err->request = urlParse(METHOD_CONNECT, waisState->request);
+            errorAppendEntry(entry, err);
+
        storeAbort(entry, 0);
        comm_close(fd);
     } else {
@@ -307,8 +353,15 @@ waisStart(request_t * request, StoreEntry * entry)
     method_t method = request->method;
     debug(24, 3) ("waisStart: \"%s %s\"\n", RequestMethodStr[method], url);
     if (!Config.Wais.relayHost) {
+        ErrorState *err;
        debug(24, 0) ("waisStart: Failed because no relay host defined!\n");
-       assert(!ERR_NO_RELAY);
+       /* was assert */
+        err = xcalloc(1, sizeof(ErrorState));
+        err->type = ERR_NO_RELAY;
+        err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+        err->request = urlParse(METHOD_CONNECT, waisState->request);
+        errorAppendEntry(entry, err);
+
        storeAbort(entry, 0);
        return;
     }
@@ -319,8 +372,14 @@ waisStart(request_t * request, StoreEntry * entry)
        COMM_NONBLOCKING,
        url);
     if (fd == COMM_ERROR) {
+        ErrorState *err;
        debug(24, 4) ("waisStart: Failed because we're out of sockets.\n");
-       assert(!ERR_SOCKET_FAILURE);
+       /* was assert */
+        err = xcalloc(1, sizeof(ErrorState));
+        err->type = ERR_SOCKET_FAILURE;
+        err->http_status = HTTP_INTERNAL_SERVER_ERROR;
+        err->request = urlParse(METHOD_CONNECT, waisState->request);
+        errorAppendEntry(entry, err);
        storeAbort(entry, 0);
        return;
     }
@@ -348,12 +407,29 @@ static void
 waisConnectDone(int fd, int status, void *data)
 {
     WaisStateData *waisState = data;
+    char *request = waisState->request;
+    ErrorState *err;
+
     if (status == COMM_ERR_DNS) {
-       assert(!ERR_DNS_FAIL);
+       /* was assert */
+        err = xcalloc(1, sizeof(ErrorState));
+        err->type = ERR_DNS_FAIL;
+        err->http_status = HTTP_SERVICE_UNAVAILABLE;
+        err->dnsserver_msg = xstrdup(dns_error_message);
+        err->request = urlParse(METHOD_CONNECT, request);
+        errorAppendEntry(waisState->entry, err);
        storeAbort(waisState->entry, 0);
        comm_close(fd);
     } else if (status != COMM_OK) {
-       assert(!ERR_CONNECT_FAIL);
+       /* was assert */
+        err = xcalloc(1, sizeof(ErrorState));
+        err->type = ERR_CONNECT_FAIL;
+        err->http_status = HTTP_SERVICE_UNAVAILABLE;
+        err->errno = errno;
+        err->host = xstrdup(waisState->relayhost);
+        err->port = waisState->relayport;
+        err->request = urlParse(METHOD_CONNECT, request);
+        errorAppendEntry(waisState->entry, err);
        storeAbort(waisState->entry, 0);
        comm_close(fd);
     } else {