]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
merge 1.1.8->1.1.10; just get it to compile
authorwessels <>
Mon, 28 Apr 1997 10:22:55 +0000 (10:22 +0000)
committerwessels <>
Mon, 28 Apr 1997 10:22:55 +0000 (10:22 +0000)
30 files changed:
src/Makefile.in
src/acl.cc
src/cache_cf.cc
src/cachemgr.cc
src/client_db.cc
src/client_side.cc
src/comm.cc
src/disk.cc
src/dns.cc
src/dnsserver.cc
src/fqdncache.cc
src/ftp.cc
src/http.cc
src/icmp.cc
src/ipcache.cc
src/main.cc
src/neighbors.cc
src/net_db.cc
src/peer_select.cc
src/pinger.cc
src/redirect.cc
src/squid.h
src/ssl.cc
src/stat.cc
src/store.cc
src/tools.cc
src/tunnel.cc
src/unlinkd.cc [new file with mode: 0644]
src/url.cc
src/wais.cc

index da4b07c37d7542d6707c5813e6d9cd252cb8b5e8..78d6a187bae19597315754f079beda8111f5f277 100644 (file)
@@ -1,7 +1,7 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.in,v 1.67 1997/04/02 04:39:55 wessels Exp $
+#  $Id: Makefile.in,v 1.68 1997/04/28 04:22:55 wessels Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
@@ -41,12 +41,14 @@ DEFAULT_STORE_LOG       = $(localstatedir)/logs/store.log
 DEFAULT_PID_FILE        = $(localstatedir)/logs/squid.pid
 DEFAULT_SWAP_DIR        = $(localstatedir)/cache
 DEFAULT_PINGER         = $(libexecdir)/pinger
+DEFAULT_UNLINKD                = $(libexecdir)/unlinkd
 
 CC             = @CC@
 MAKEDEPEND     = @MAKEDEPEND@
 INSTALL                = @INSTALL@
 INSTALL_BIN    = @INSTALL_PROGRAM@
 INSTALL_FILE   = @INSTALL_DATA@
+INSTALL_SUID   = @INSTALL_PROGRAM@ -o root -m 4755
 RANLIB         = @RANLIB@
 LN_S           = @LN_S@
 PERL            = @PERL@
@@ -70,7 +72,8 @@ FTPGET_LIBS   = -L../lib -lmiscutil $(XTRA_LIBS)
 PINGER_LIBS    = -L../lib -lmiscutil $(XTRA_LIBS)
 
 PROGS           = squid client
-UTILS           = dnsserver ftpget pinger
+UTILS           = dnsserver ftpget unlinkd
+SUID_UTILS     = pinger
 CGIPROGS       = cachemgr.cgi
 OBJS           = \
                acl.o \
@@ -115,6 +118,7 @@ OBJS                = \
                store_dir.o \
                storetoString.o \
                tools.o \
+               unlinkd.o \
                url.o \
                useragent.o \
                wais.o \
@@ -129,9 +133,10 @@ DEFAULTS        = \
        -DDEFAULT_STORE_LOG=\"$(DEFAULT_STORE_LOG)\" \
        -DDEFAULT_PID_FILE=\"$(DEFAULT_PID_FILE)\" \
        -DDEFAULT_SWAP_DIR=\"$(DEFAULT_SWAP_DIR)\" \
-       -DDEFAULT_PINGER=\"$(DEFAULT_PINGER)\"
+       -DDEFAULT_PINGER=\"$(DEFAULT_PINGER)\" \
+       -DDEFAULT_UNLINKD=\"$(DEFAULT_UNLINKD)\"
 
-all:    squid.conf $(PROGS) $(UTILS) $(CGIPROGS)
+all:    squid.conf $(PROGS) $(UTILS) $(SUID_UTILS) $(CGIPROGS)
 
 $(OBJS): ../include/version.h
 
@@ -156,11 +161,16 @@ ftpget: ftpget.o
 pinger: pinger.o
        $(CC) -o $@ $(LDFLAGS) pinger.o debug.o $(PINGER_LIBS)
 
+unlinkd: unlinkd.c
+       $(CC) $(CFLAGS) -DUNLINK_DAEMON $(srcdir)/unlinkd.c -o $@ $(LDFLAGS)
+
 squid.conf: squid.conf.pre Makefile
        sed "\
        s%@DEFAULT_CONFIG_FILE@%$(DEFAULT_CONFIG_FILE)%g;\
        s%@DEFAULT_FTPGET@%$(DEFAULT_FTPGET)%g;\
        s%@DEFAULT_DNSSERVER@%$(DEFAULT_DNSSERVER)%g;\
+       s%@DEFAULT_UNLINKD@%$(DEFAULT_UNLINKD)%g;\
+       s%@DEFAULT_PINGER@%$(DEFAULT_PINGER)%g;\
        s%@DEFAULT_CACHE_LOG@%$(DEFAULT_CACHE_LOG)%g;\
        s%@DEFAULT_ACCESS_LOG@%$(DEFAULT_ACCESS_LOG)%g;\
        s%@DEFAULT_STORE_LOG@%$(DEFAULT_STORE_LOG)%g;\
@@ -244,8 +254,21 @@ install: all install-mkdirs
                $(INSTALL_FILE) squid.conf $(sysconfdir); \
        fi
 
+install-pinger:
+       @f=pinger; \
+       if test -f $(libexecdir)/$$f; then \
+               echo $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \
+               $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \
+       fi; \
+       echo $(INSTALL_SUID) $$f $(libexecdir); \
+       $(INSTALL_SUID) $$f $(libexecdir) || exit 1; \
+       if test -f $(libexecdir)/-$$f; then \
+               echo $(RM) -f $(libexecdir)/-$$f; \
+               $(RM) -f $(libexecdir)/-$$f; \
+       fi
+
 clean: 
-       -rm -rf *.o *pure_* core $(PROGS) $(UTILS) $(CGIPROGS)
+       -rm -rf *.o *pure_* core $(PROGS) $(UTILS) $(CGIPROGS) $(SUID_UTILS)
 
 realclean:     clean
        -rm -f Makefile squid.conf squid.conf.pre
index 3bba4f25dac7caffaf4f52f3574e3437f256e0de..e22e1a58e9b2af7c67306c741ca87d89febbf4a9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: acl.cc,v 1.90 1997/03/04 05:16:24 wessels Exp $
+ * $Id: acl.cc,v 1.91 1997/04/28 04:22:56 wessels Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -234,16 +234,15 @@ aclParseMethodList(void *curlist)
 static int
 decode_addr(const char *asc, struct in_addr *addr, struct in_addr *mask)
 {
-    u_num32 a = 0;
+    u_num32 a;
     int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
     struct hostent *hp = NULL;
 
     switch (sscanf(asc, "%d.%d.%d.%d", &a1, &a2, &a3, &a4)) {
     case 4:                    /* a dotted quad */
-       if ((a = (u_num32) inet_addr(asc)) != inaddr_none ||
-           !strcmp(asc, "255.255.255.255")) {
-           addr->s_addr = a;
-           /* inet_addr() outputs in network byte order */
+       if (!safe_inet_addr(asc, addr)) {
+           debug(28, 0, "decode_addr: unsafe IP address: '%s'\n", asc);
+           fatal("decode_addr: unsafe IP address");
        }
        break;
     case 1:                    /* a significant bits value for a mask */
@@ -1583,23 +1582,23 @@ networkCompare(struct _acl_ip_data *net, struct _acl_ip_data *data)
 static int
 aclIpNetworkCompare(const void *a, splayNode * n)
 {
-    struct in_addr *A = (struct in_addr *) a;
+    struct in_addr A = *(struct in_addr *) a;
     struct _acl_ip_data *q = n->data;
     struct in_addr B = q->addr1;
     struct in_addr C = q->addr2;
     int rc = 0;
-    A->s_addr &= q->mask.s_addr;       /* apply netmask */
+    A.s_addr &= q->mask.s_addr;        /* apply netmask */
     if (C.s_addr == 0) {       /* single address check */
-       if (ntohl(A->s_addr) > ntohl(B.s_addr))
+       if (ntohl(A.s_addr) > ntohl(B.s_addr))
            rc = 1;
-       else if (ntohl(A->s_addr) < ntohl(B.s_addr))
+       else if (ntohl(A.s_addr) < ntohl(B.s_addr))
            rc = -1;
        else
            rc = 0;
     } else {                   /* range address check */
-       if (ntohl(A->s_addr) > ntohl(C.s_addr))
+       if (ntohl(A.s_addr) > ntohl(C.s_addr))
            rc = 1;
-       else if (ntohl(A->s_addr) < ntohl(B.s_addr))
+       else if (ntohl(A.s_addr) < ntohl(B.s_addr))
            rc = -1;
        else
            rc = 0;
index 8f15e3c194cbbdecf75c34f36a4ee7218faf6a8a..62085c23a28a595aff168f24f43cb62c345f2459 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cache_cf.cc,v 1.180 1997/04/25 22:01:16 wessels Exp $
+ * $Id: cache_cf.cc,v 1.181 1997/04/28 04:22:57 wessels Exp $
  *
  * DEBUG: section 3     Configuration File Parsing
  * AUTHOR: Harvest Derived
@@ -115,11 +115,12 @@ struct SquidConfig Config;
 #define DefaultSwapLowWaterMark  90    /* 90% */
 #define DefaultNetdbHigh       1000    /* counts, not percents */
 #define DefaultNetdbLow                 900
+#define DefaultNetdbPeriod       300   /* 5 minutes */
 
 #define DefaultWaisRelayHost   (char *)NULL
 #define DefaultWaisRelayPort   0
 
-#define DefaultReferenceAge    0       /* disabled */
+#define DefaultReferenceAge    (86400*365)     /* 1 year */
 #define DefaultNegativeTtl     (5 * 60)        /* 5 min */
 #define DefaultNegativeDnsTtl  (2 * 60)        /* 2 min */
 #define DefaultPositiveDnsTtl  (360 * 60)      /* 6 hours */
@@ -152,6 +153,7 @@ struct SquidConfig Config;
 #define DefaultFtpgetOptions   ""
 #define DefaultDnsserverProgram DEFAULT_DNSSERVER
 #define DefaultPingerProgram    DEFAULT_PINGER
+#define DefaultUnlinkdProgram   DEFAULT_UNLINKD
 #define DefaultRedirectProgram  (char *)NULL   /* default NONE */
 #define DefaultEffectiveUser   (char *)NULL    /* default NONE */
 #define DefaultEffectiveGroup  (char *)NULL    /* default NONE */
@@ -185,9 +187,9 @@ struct SquidConfig Config;
 #define DefaultTcpRcvBufsz     0       /* use system default */
 #define DefaultUdpMaxHitObjsz  SQUID_UDP_SO_SNDBUF     /* from configure */
 #define DefaultTcpIncomingAddr INADDR_ANY
-#define DefaultTcpOutgoingAddr inaddr_none
+#define DefaultTcpOutgoingAddr no_addr.s_addr
 #define DefaultUdpIncomingAddr INADDR_ANY
-#define DefaultUdpOutgoingAddr inaddr_none
+#define DefaultUdpOutgoingAddr no_addr.s_addr
 #define DefaultClientNetmask    0xFFFFFFFFul
 #define DefaultPassProxy       NULL
 #define DefaultSslProxy                NULL
@@ -201,6 +203,9 @@ struct SquidConfig Config;
 
 #define DefaultOptionsLogUdp   1       /* on */
 #define DefaultOptionsEnablePurge 0    /* default off */
+#define DefaultOptionsClientDb 1       /* default on */
+#define DefaultOptionsQueryIcmp        0       /* default off */
+
 
 int httpd_accel_mode = 0;      /* for fast access */
 const char *DefaultSwapDir = DEFAULT_SWAP_DIR;
@@ -232,7 +237,6 @@ static void parseDebugOptionsLine _PARAMS((void));
 static void parseEffectiveUserLine _PARAMS((void));
 static void parseErrHtmlLine _PARAMS((void));
 static void parseFtpOptionsLine _PARAMS((void));
-static void parseFtpProgramLine _PARAMS((void));
 static void parseFtpUserLine _PARAMS((void));
 static void parseWordlist _PARAMS((wordlist **));
 static void parseHostAclLine _PARAMS((void));
@@ -250,9 +254,11 @@ static void parseVisibleHostnameLine _PARAMS((void));
 static void parseWAISRelayLine _PARAMS((void));
 static void parseMinutesLine _PARAMS((int *));
 static void parseCachemgrPasswd _PARAMS((void));
-static void parsePathname _PARAMS((char **));
+static void parsePathname _PARAMS((char **, int fatal));
 static void parseProxyLine _PARAMS((peer **));
 static void parseHttpAnonymizer _PARAMS((int *));
+static int parseTimeUnits _PARAMS((const char *unit));
+static void parseTimeLine _PARAMS((int *iptr, const char *units));
 
 static void
 self_destruct(void)
@@ -358,6 +364,10 @@ parseCacheHostLine(void)
            weight = atoi(token + 7);
        } else if (!strncasecmp(token, "ttl=", 4)) {
            mcast_ttl = atoi(token + 4);
+           if (mcast_ttl < 0)
+               mcast_ttl = 0;
+           if (mcast_ttl > 128)
+               mcast_ttl = 128;
        } else if (!strncasecmp(token, "default", 7)) {
            options |= NEIGHBOR_DEFAULT_PARENT;
        } else if (!strncasecmp(token, "round-robin", 11)) {
@@ -549,25 +559,19 @@ parseEffectiveUserLine(void)
 }
 
 static void
-parsePathname(char **path)
+parsePathname(char **path, int fatal)
 {
     char *token;
+    struct stat sb;
     token = strtok(NULL, w_space);
     if (token == NULL)
        self_destruct();
     safe_free(*path);
     *path = xstrdup(token);
-}
-
-static void
-parseFtpProgramLine(void)
-{
-    char *token;
-    token = strtok(NULL, w_space);
-    if (token == NULL)
+    if (fatal && stat(token, &sb) < 0) {
+       debug(50, 1, "parsePathname: %s: %s\n", token, xstrerror());
        self_destruct();
-    safe_free(Config.Program.ftpget);
-    Config.Program.ftpget = xstrdup(token);
+    }
 }
 
 static void
@@ -637,8 +641,8 @@ parseAddressLine(struct in_addr *addr)
     token = strtok(NULL, w_space);
     if (token == NULL)
        self_destruct();
-    if (inet_addr(token) != inaddr_none)
-       (*addr).s_addr = inet_addr(token);
+    if (safe_inet_addr(token, addr) == 1)
+       (void) 0;
     else if ((hp = gethostbyname(token)))      /* dont use ipcache */
        *addr = inaddrFromHostent(hp);
     else
@@ -752,8 +756,8 @@ parseVizHackLine(void)
     token = strtok(NULL, w_space);
     if (token == NULL)
        self_destruct();
-    if (inet_addr(token) != inaddr_none)
-       Config.vizHack.addr.s_addr = inet_addr(token);
+    if (safe_inet_addr(token, &Config.vizHack.addr) == 1)
+       (void) 0;
     else if ((hp = gethostbyname(token)))      /* dont use ipcache */
        Config.vizHack.addr = inaddrFromHostent(hp);
     else
@@ -931,20 +935,20 @@ parseConfigFile(const char *file_name)
            parseCacheDir();
 
        else if (!strcmp(token, "cache_log"))
-           parsePathname(&Config.Log.log);
+           parsePathname(&Config.Log.log, 0);
 
        else if (!strcmp(token, "cache_access_log"))
-           parsePathname(&Config.Log.access);
+           parsePathname(&Config.Log.access, 0);
 
        else if (!strcmp(token, "cache_store_log"))
-           parsePathname(&Config.Log.store);
+           parsePathname(&Config.Log.store, 0);
 
        else if (!strcmp(token, "cache_swap_log"))
-           parsePathname(&Config.Log.swap);
+           parsePathname(&Config.Log.swap, 0);
 
 #if USE_USERAGENT_LOG
        else if (!strcmp(token, "useragent_log"))
-           parsePathname(&Config.Log.useragent);
+           parsePathname(&Config.Log.useragent, 0);
 #endif
 
        else if (!strcmp(token, "logfile_rotate"))
@@ -1028,7 +1032,7 @@ parseConfigFile(const char *file_name)
        else if (!strcmp(token, "client_lifetime"))
            parseMinutesLine(&Config.lifetimeDefault);
        else if (!strcmp(token, "reference_age"))
-           parseMinutesLine(&Config.referenceAge);
+           parseTimeLine(&Config.referenceAge, "minutes");
 
        else if (!strcmp(token, "shutdown_lifetime"))
            parseIntegerValue(&Config.lifetimeShutdown);
@@ -1040,9 +1044,9 @@ parseConfigFile(const char *file_name)
            parseIntegerValue(&Config.connectTimeout);
 
        else if (!strcmp(token, "cache_ftp_program"))
-           parseFtpProgramLine();
+           parsePathname(&Config.Program.ftpget, 1);
        else if (!strcmp(token, "ftpget_program"))
-           parseFtpProgramLine();
+           parsePathname(&Config.Program.ftpget, 1);
 
        else if (!strcmp(token, "cache_ftp_options"))
            parseFtpOptionsLine();
@@ -1050,7 +1054,7 @@ parseConfigFile(const char *file_name)
            parseFtpOptionsLine();
 
        else if (!strcmp(token, "cache_dns_program"))
-           parsePathname(&Config.Program.dnsserver);
+           parsePathname(&Config.Program.dnsserver, 1);
 
        else if (!strcmp(token, "dns_children"))
            parseIntegerValue(&Config.dnsChildren);
@@ -1058,11 +1062,17 @@ parseConfigFile(const char *file_name)
            parseOnOff(&Config.Options.res_defnames);
 
        else if (!strcmp(token, "redirect_program"))
-           parsePathname(&Config.Program.redirect);
+           parsePathname(&Config.Program.redirect, 1);
 
        else if (!strcmp(token, "redirect_children"))
            parseIntegerValue(&Config.redirectChildren);
 
+       else if (!strcmp(token, "pinger_program"))
+           parsePathname(&Config.Program.pinger, 1);
+
+       else if (!strcmp(token, "unlinkd_program"))
+           parsePathname(&Config.Program.unlinkd, 1);
+
 #if USE_PROXY_AUTH
        else if (!strcmp(token, "proxy_auth"))
            parseProxyAuthLine();
@@ -1136,7 +1146,7 @@ parseConfigFile(const char *file_name)
            parseDebugOptionsLine();
 
        else if (!strcmp(token, "pid_filename"))
-           parsePathname(&Config.pidFilename);
+           parsePathname(&Config.pidFilename, 0);
 
        else if (!strcmp(token, "visible_hostname"))
            parseVisibleHostnameLine();
@@ -1177,6 +1187,10 @@ parseConfigFile(const char *file_name)
            parseOnOff(&Config.Options.log_udp);
        else if (!strcmp(token, "http_anonymizer"))
            parseHttpAnonymizer(&Config.Options.anonymizer);
+       else if (!strcmp(token, "client_db"))
+           parseOnOff(&Config.Options.client_db);
+       else if (!strcmp(token, "query_icmp"))
+           parseOnOff(&Config.Options.query_icmp);
 
        else if (!strcmp(token, "minimum_direct_hops"))
            parseIntegerValue(&Config.minDirectHops);
@@ -1198,8 +1212,8 @@ parseConfigFile(const char *file_name)
            parseIntegerValue(&Config.Netdb.high);
        else if (!strcmp(token, "netdb_low"))
            parseIntegerValue(&Config.Netdb.low);
-       else if (!strcmp(token, "netdb_ttl"))
-           parseIntegerValue(&Config.Netdb.ttl);
+       else if (!strcmp(token, "netdb_ping_period"))
+           parseTimeLine(&Config.Netdb.period, "seconds");
 
        /* If unknown, treat as a comment line */
        else {
@@ -1277,6 +1291,7 @@ configFreeMemory(void)
     safe_free(Config.Program.ftpget_opts);
     safe_free(Config.Program.dnsserver);
     safe_free(Config.Program.redirect);
+    safe_free(Config.Program.unlinkd);
     safe_free(Config.Program.pinger);
     safe_free(Config.Accel.host);
     safe_free(Config.Accel.prefix);
@@ -1316,6 +1331,7 @@ configSetFactoryDefaults(void)
     Config.Swap.lowWaterMark = DefaultSwapLowWaterMark;
     Config.Netdb.high = DefaultNetdbHigh;
     Config.Netdb.low = DefaultNetdbLow;
+    Config.Netdb.period = DefaultNetdbPeriod;
 
     Config.Wais.relayHost = safe_xstrdup(DefaultWaisRelayHost);
     Config.Wais.relayPort = DefaultWaisRelayPort;
@@ -1366,6 +1382,7 @@ configSetFactoryDefaults(void)
     Config.Program.dnsserver = safe_xstrdup(DefaultDnsserverProgram);
     Config.Program.redirect = safe_xstrdup(DefaultRedirectProgram);
     Config.Program.pinger = safe_xstrdup(DefaultPingerProgram);
+    Config.Program.unlinkd = safe_xstrdup(DefaultUnlinkdProgram);
     Config.Accel.host = safe_xstrdup(DefaultAccelHost);
     Config.Accel.prefix = safe_xstrdup(DefaultAccelPrefix);
     Config.Accel.port = DefaultAccelPort;
@@ -1402,6 +1419,8 @@ configSetFactoryDefaults(void)
     Config.Options.res_defnames = DefaultOptionsResDefnames;
     Config.Options.anonymizer = DefaultOptionsAnonymizer;
     Config.Options.enable_purge = DefaultOptionsEnablePurge;
+    Config.Options.client_db = DefaultOptionsClientDb;
+    Config.Options.query_icmp = DefaultOptionsQueryIcmp;
 }
 
 static void
@@ -1428,3 +1447,50 @@ configDoConfigure(void)
     else
        Config.appendDomainLen = 0;
 }
+
+/* Parse a time specification from the config file.  Store the
+ * result in 'iptr', after converting it to 'units' */
+static void
+parseTimeLine(int *iptr, const char *units)
+{
+    char *token;
+    double d;
+    int m;
+    int u;
+    if ((u = parseTimeUnits(units)) == 0)
+       self_destruct();
+    if ((token = strtok(NULL, w_space)) == NULL)
+       self_destruct();
+    d = atof(token);
+    m = u;                     /* default to 'units' if none specified */
+    if ((token = strtok(NULL, w_space)) != NULL) {
+       if ((m = parseTimeUnits(token)) == 0)
+           self_destruct();
+    }
+    *iptr = m * d / u;
+}
+
+static int
+parseTimeUnits(const char *unit)
+{
+    if (!strncasecmp(unit, "second", 6))
+       return 1;
+    if (!strncasecmp(unit, "minute", 6))
+       return 60;
+    if (!strncasecmp(unit, "hour", 4))
+       return 3600;
+    if (!strncasecmp(unit, "day", 3))
+       return 86400;
+    if (!strncasecmp(unit, "week", 4))
+       return 86400 * 7;
+    if (!strncasecmp(unit, "fortnight", 9))
+       return 86400 * 14;
+    if (!strncasecmp(unit, "month", 5))
+       return 86400 * 30;
+    if (!strncasecmp(unit, "year", 4))
+       return 86400 * 365.2522;
+    if (!strncasecmp(unit, "decade", 6))
+       return 86400 * 365.2522 * 10;
+    debug(3, 1, "parseTimeUnits: unknown time unit '%s'\n", unit);
+    return 0;
+}
index 2d873d734e9e77ff2a01bfd6b89eab9122521867..115801ceedba3228ad15ba70e113edeec960e434 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: cachemgr.cc,v 1.53 1997/01/13 22:47:03 wessels Exp $
+ * $Id: cachemgr.cc,v 1.54 1997/04/28 04:22:59 wessels Exp $
  *
  * DEBUG: section 0     CGI Cache Manager
  * AUTHOR: Harvest Derived
@@ -298,7 +298,7 @@ static const char *script_name = "/cgi-bin/cachemgr.cgi";
 static const char *const w_space = " \t\n\r";
 static const char *progname = NULL;
 static time_t now;
-static unsigned int inaddr_none;
+static struct in_addr no_addr;
 
 static char x2c _PARAMS((char *));
 static int client_comm_connect _PARAMS((int sock, char *dest_host, u_short dest_port));
@@ -628,7 +628,7 @@ main(int argc, char *argv[])
     int single = TRUE;
     float f1;
 
-    inaddr_none = inet_addr("255.255.255.255");
+    safe_inet_addr("255.255.255.255", &no_addr);
     now = time(NULL);
     if ((s = strrchr(argv[0], '/')))
        progname = xstrdup(s + 1);
@@ -805,7 +805,7 @@ main(int argc, char *argv[])
        perror("client: socket");
        exit(1);
     }
-    if ((conn = client_comm_connect(conn, hostname, portnum)) < 0) {
+    if (client_comm_connect(conn, hostname, portnum) < 0) {
        printf("Error: connecting to cache mgr: %s:%d\n", hostname, portnum);
        printf("%s</PRE></BODY></HTML>\n", xstrerror());
        exit(1);
@@ -994,16 +994,15 @@ client_comm_connect(int sock, char *dest_host, u_short dest_port)
 {
     const struct hostent *hp;
     static struct sockaddr_in to_addr;
-    unsigned long haddr;
 
     /* Set up the destination socket address for message to send to. */
     memset(&to_addr, '\0', sizeof(struct sockaddr_in));
     to_addr.sin_family = AF_INET;
 
     if ((hp = gethostbyname(dest_host)) != NULL)
-       xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
-    else if ((haddr = inet_addr(dest_host)) != inaddr_none)
-       xmemcpy(&to_addr.sin_addr, &haddr, sizeof(haddr));
+       xmemcpy(&to_addr.sin_addr.s_addr, hp->h_addr, hp->h_length);
+    else if (safe_inet_addr(dest_host, &to_addr.sin_addr))
+       (void) 0;
     else
        return (-1);
 
index d424f826e4db43102190b88f2a7660aaf4152c32..810b5066af3e9efc2ebff9ad73bf78b4bd80fe85 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_db.cc,v 1.9 1996/12/20 23:21:26 wessels Exp $
+ * $Id: client_db.cc,v 1.10 1997/04/28 04:22:59 wessels Exp $
  *
  * DEBUG: section 0     Client Database
  * AUTHOR: Duane Wessels
@@ -73,8 +73,12 @@ clientdbInit(void)
 void
 clientdbUpdate(struct in_addr addr, log_type log_type, u_short port)
 {
-    char *key = inet_ntoa(addr);
-    ClientInfo *c = (ClientInfo *) hash_lookup(client_table, key);
+    char *key;
+    ClientInfo *c;
+    if (!Config.Options.client_db)
+       return;
+    key = inet_ntoa(addr);
+    c = (ClientInfo *) hash_lookup(client_table, key);
     if (c == NULL)
        c = clientdbAdd(addr);
     if (c == NULL)
@@ -91,9 +95,13 @@ clientdbUpdate(struct in_addr addr, log_type log_type, u_short port)
 int
 clientdbDeniedPercent(struct in_addr addr)
 {
-    char *key = inet_ntoa(addr);
+    char *key;
     int n = 100;
-    ClientInfo *c = (ClientInfo *) hash_lookup(client_table, key);
+    ClientInfo *c;
+    if (!Config.Options.client_db)
+       return 0;
+    key = inet_ntoa(addr);
+    c = (ClientInfo *) hash_lookup(client_table, key);
     if (c == NULL)
        return 0;
     if (c->Icp.n_requests > 100)
index 2bdbb7296deef165a75720c0c1076655cd395668..a1de5396677eefcbbdd0e22bdabd855b4a1c1c0d 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.95 1997/03/29 04:45:14 wessels Exp $
+ * $Id: client_side.cc,v 1.96 1997/04/28 04:23:00 wessels Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -140,6 +140,9 @@ clientAccessCheckDone(int answer, void *data)
     debug(33, 5, "clientAccessCheckDone: '%s' answer=%d\n", icpState->url, answer);
     if (answer) {
        urlCanonical(icpState->request, icpState->url);
+       if (icpState->redirect_state != REDIRECT_NONE)
+           fatal_dump("clientAccessCheckDone: wrong redirect_state");
+       icpState->redirect_state = REDIRECT_PENDING;
        redirectStart(fd, icpState, clientRedirectDone, icpState);
     } else {
        debug(33, 5, "Access Denied: %s\n", icpState->url);
@@ -171,6 +174,9 @@ clientRedirectDone(void *data, char *result)
     request_t *old_request = icpState->request;
     debug(33, 5, "clientRedirectDone: '%s' result=%s\n", icpState->url,
        result ? result : "NULL");
+    if (icpState->redirect_state != REDIRECT_PENDING)
+       fatal_dump("clientRedirectDone: wrong redirect_state");
+    icpState->redirect_state = REDIRECT_DONE;
     if (result)
        new_request = urlParse(old_request->method, result);
     if (new_request) {
index 9781777abcc96324e80407089fd474ab2cb5c936..dc0dc23495456548029b0c8b9e04ecf28b77d7ff 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: comm.cc,v 1.140 1997/03/04 05:16:27 wessels Exp $
+ * $Id: comm.cc,v 1.141 1997/04/28 04:23:01 wessels Exp $
  *
  * DEBUG: section 5     Socket Functions
  * AUTHOR: Harvest Derived
@@ -153,8 +153,8 @@ static void commSetTcpNoDelay _PARAMS((int));
 static void commSetTcpRcvbuf _PARAMS((int, int));
 static void commConnectFree _PARAMS((int fd, void *data));
 static void commConnectHandle _PARAMS((int fd, void *data));
+static void commHandleWrite _PARAMS((int fd, RWStateData * state));
 
-static int *fd_lifetime = NULL;
 static struct timeval zero_tv;
 
 void
@@ -274,6 +274,7 @@ comm_open(int sock_type,
     if (note)
        fd_note(new_socket, note);
     conn->openned = 1;
+    conn->lifetime = -1;
     if (!BIT_TEST(flags, COMM_NOCLOEXEC))
        commSetCloseOnExec(new_socket);
     if (port > (u_short) 0) {
@@ -281,7 +282,7 @@ comm_open(int sock_type,
        if (do_reuse)
            commSetReuseAddr(new_socket);
     }
-    if (addr.s_addr != inaddr_none)
+    if (addr.s_addr != no_addr.s_addr)
        if (commBind(new_socket, addr, port) != COMM_OK)
            return COMM_ERROR;
     conn->local_port = port;
@@ -385,33 +386,19 @@ commConnectHandle(int fd, void *data)
 int
 comm_set_fd_lifetime(int fd, int lifetime)
 {
+    FD_ENTRY *f;
     debug(5, 3, "comm_set_fd_lifetime: FD %d lft %d\n", fd, lifetime);
     if (fd < 0 || fd > Squid_MaxFD)
        return 0;
+    f = &fd_table[fd];
     if (lifetime < 0)
-       return fd_lifetime[fd] = -1;
+       return f->lifetime = -1;
     if (shutdown_pending || reread_pending) {
        /* don't increase the lifetime if something pending */
-       if (fd_lifetime[fd] > -1 && (fd_lifetime[fd] - squid_curtime) < lifetime)
-           return fd_lifetime[fd];
+       if (f->lifetime > -1 && (f->lifetime - squid_curtime) < lifetime)
+           return f->lifetime;
     }
-    return fd_lifetime[fd] = (int) squid_curtime + lifetime;
-}
-
-int
-comm_get_fd_lifetime(int fd)
-{
-    if (fd < 0)
-       return 0;
-    return fd_lifetime[fd];
-}
-
-int
-comm_get_fd_timeout(int fd)
-{
-    if (fd < 0)
-       return 0;
-    return fd_table[fd].timeout_time;
+    return f->lifetime = (int) squid_curtime + lifetime;
 }
 
 int
@@ -558,13 +545,13 @@ comm_close(int fd)
     }
     conn->openned = 0;
     RWStateCallbackAndFree(fd, COMM_ERROR);
-    comm_set_fd_lifetime(fd, -1);      /* invalidate the lifetime */
     fdstat_close(fd);          /* update fdstat */
     commCallCloseHandlers(fd);
     memset(conn, '\0', sizeof(FD_ENTRY));
 #if USE_ASYNC_IO
     aioClose(fd);
 #else
+    conn->lifetime = -1;
     close(fd);
 #endif
 }
@@ -647,11 +634,11 @@ comm_set_stall(int fd, int delta)
 static void
 comm_select_incoming(void)
 {
-    int fd = 0;
+    int fd;
     int fds[4];
     struct pollfd pfds[4];
     unsigned long N = 0;
-    unsigned long i = 0;
+    unsigned long i, nfds;
     int dopoll = 0;
     PF hdl = NULL;
     if (theInIcpConnection >= 0)
@@ -661,44 +648,41 @@ comm_select_incoming(void)
            fds[N++] = theOutIcpConnection;
     if (theHttpConnection >= 0 && fdstat_are_n_free_fd(RESERVED_FD))
        fds[N++] = theHttpConnection;
-    fds[N++] = 0;
-    for (i = 0; i < N; i++) {
+    for (i = nfds = 0; i < N; i++) {
+       int events;
        fd = fds[i];
-       pfds[i].events = 0;
-       pfds[i].revents = 0;
-       pfds[i].fd = fd;
-       if (fd_table[fd].read_handler) {
-           pfds[i].events |= POLLRDNORM;
-           dopoll++;
-       }
-       if (fd_table[fd].write_handler) {
-           pfds[i].events |= POLLWRNORM;
-           dopoll++;
+       events = 0;
+       if (fd_table[fd].read_handler)
+           events |= POLLRDNORM;
+       if (fd_table[fd].write_handler)
+           events |= POLLWRNORM;
+       if (events) {
+           pfds[nfds].fd = fd;
+           pfds[nfds].events = events;
+           pfds[nfds].revents = 0;
+           nfds++;
        }
-       if (pfds[i].events == 0)
-           pfds[i].fd = -1;
     }
-    if (!dopoll)
+    if (!nfds)
+       return;
+    if (poll(pfds, nfds, 0) < 1)
        return;
-    poll(pfds, N, 0);
+#ifndef LESS_TIMING
     getCurrentTime();
-    for (i = 0; i < N; i++) {
-       if (pfds[i].fd == -1)
+#endif
+    for (i = 0; i < nfds; i++) {
+       int revents;
+       if (((revents = pfds[i].revents) == 0) || ((fd = pfds[i].fd) == -1))
            continue;
-       fd = fds[i];
-       if (fd_table[fd].read_handler) {
-           if (pfds[i].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) {
-               hdl = fd_table[fd].read_handler;
-               fd_table[fd].read_handler = 0;
-               hdl(fd, fd_table[fd].read_data);
-           }
+       if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) {
+           hdl = fd_table[fd].read_handler;
+           fd_table[fd].read_handler = 0;
+           hdl(fd, fd_table[fd].read_data);
        }
-       if (fd_table[fd].write_handler) {
-           if (pfds[i].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) {
-               hdl = fd_table[fd].write_handler;
-               fd_table[fd].write_handler = 0;
-               hdl(fd, fd_table[fd].write_data);
-           }
+       if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) {
+           hdl = fd_table[fd].write_handler;
+           fd_table[fd].write_handler = 0;
+           hdl(fd, fd_table[fd].write_data);
        }
     }
     /* TO FIX: repoll ICP connection here */
@@ -744,7 +728,9 @@ comm_select_incoming(void)
        return;
     if (select(maxfd, &read_mask, &write_mask, NULL, &zero_tv) < 1)
        return;
+#ifndef LESS_TIMING
     getCurrentTime();
+#endif
     for (i = 0; i < N; i++) {
        fd = fds[i];
        if (FD_ISSET(fd, &read_mask)) {
@@ -761,7 +747,6 @@ comm_select_incoming(void)
 }
 #endif
 
-
 #ifdef USE_POLL
 /* poll all sockets; call handlers for those that are ready. */
 int
@@ -773,15 +758,11 @@ comm_select(time_t sec)
     int i;
     int maxfd;
     unsigned long nfds;
-    int incnfd;
     int num;
     static time_t last_timeout = 0;
     static time_t pending_time;
-    int poll_time = 0;
+    int poll_time;
     time_t timeout;
-    struct close_handler *ch = NULL;
-    struct close_handler *next = NULL;
-    FD_ENTRY *f = NULL;
     /* assume all process are very fast (less than 1 second). Call
      * time() only once */
     getCurrentTime();
@@ -795,35 +776,43 @@ comm_select(time_t sec)
            ftpServerClose();
            dnsShutdownServers();
            redirectShutdownServers();
-           if (shutdown_pending > 0)
+           /* shutdown_pending will be set to
+            * +1 for SIGTERM
+            * -1 for SIGINT */
+           /* reread_pending always == 1 when SIGHUP received */
+           if (shutdown_pending > 0 || reread_pending > 0)
                setSocketShutdownLifetimes(Config.lifetimeShutdown);
            else
                setSocketShutdownLifetimes(0);
        }
-       maxfd = fdstat_biggest_fd() + 1;
-       for (nfds = 0, i = 0; i < maxfd; i++) {
-           pfds[i].fd = i;
-           pfds[i].events = 0;
-           if (i == theHttpConnection && !fdstat_are_n_free_fd(RESERVED_FD))
-               continue;
+       nfds = 0;
+       maxfd = Biggest_FD + 1;
+       httpindex = -1;
+       for (i = 0; i < maxfd; i++) {
+           int events;
+           events = 0;
            /* Check each open socket for a handler. */
-           incnfd = 0;
-           if (fd_table[i].read_handler
-               && fd_table[i].stall_until <= squid_curtime) {
-               pfds[i].events |= POLLRDNORM;
-               incnfd = 1;
+           if (fd_table[i].read_handler && fd_table[i].stall_until <= squid_curtime)
+               events |= POLLRDNORM;
+           if (fd_table[i].write_handler)
+               events |= POLLWRNORM;
+           if (events) {
+               if (i == theHttpConnection)
+                   httpindex = nfds;
+               pfds[nfds].fd = i;
+               pfds[nfds].events = events;
+               pfds[nfds].revents = 0;
+               nfds++;
+               if (pfds[i].events == 0)
+                   pfds[i].fd = -1;
            }
-           if (fd_table[i].write_handler) {
-               pfds[i].events |= POLLWRNORM;
-               incnfd = 1;
+           /* If we're out of free fd's, don't poll the http incoming fd */
+           if (!fdstat_are_n_free_fd(RESERVED_FD) && httpindex >= 0) {
+               pfds[httpindex].fd = -1;
+               pfds[httpindex].events = 0;
            }
-           if (incnfd)
-               nfds++;
-           if (pfds[i].events == 0)
-               pfds[i].fd = -1;
-       }
-       if (shutdown_pending || reread_pending) {
-           debug(5, 2, "comm_select: Still waiting on %d FDs\n", nfds);
+           if (shutdown_pending || reread_pending)
+               debug(5, 2, "comm_select: Still waiting on %d FDs\n", nfds);
            if (pending_time == 0)
                pending_time = squid_curtime;
            if ((squid_curtime - pending_time) > (Config.lifetimeShutdown + 5)) {
@@ -838,8 +827,8 @@ comm_select(time_t sec)
                    pfds[fd].fd = -1;
                }
            }
-       } else
-           pending_time = 0;
+       }
+       pending_time = 0;
        if (nfds == 0)
            return COMM_SHUTDOWN;
        poll_time = sec > 0 ? 100 : 0;
@@ -847,7 +836,10 @@ comm_select(time_t sec)
        aioCheckCallbacks();
 #endif
        for (;;) {
-           num = poll(pfds, maxfd, poll_time);
+           poll_time = sec > 0 ? 1000 : 0;
+           num = poll(pfds, nfds, poll_time);
+           select_loops++;
+           getCurrentTime();
            if (num >= 0)
                break;
            if (errno == EINTR)
@@ -879,8 +871,9 @@ comm_select(time_t sec)
        /* scan each socket but the accept socket. Poll this 
         * more frequently to minimize losses due to the 5 connect 
         * limit in SunOS */
-       for (i = 0; i < maxfd; i++) {
-           if ((fd = pfds[i].fd) == -1)
+       for (i = 0; i < nfds; i++) {
+           int revents;
+           if (((revents = pfds[i].revents) == 0) || ((fd = pfds[i].fd) == -1))
                continue;
            /*
             * Admit more connections quickly until we hit the hard limit.
@@ -890,20 +883,22 @@ comm_select(time_t sec)
                comm_select_incoming();
            if ((fd == theInIcpConnection) || (fd == theHttpConnection) || (fd == theOutIcpConnection) || (fd == 0))
                continue;
-           if (fd_table[fd].read_handler && (pfds[i].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))) {
+           if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) {
                debug(5, 6, "comm_select: FD %d ready for reading\n", fd);
                hdl = fd_table[fd].read_handler;
                fd_table[fd].read_handler = 0;
                hdl(fd, fd_table[fd].read_data);
            }
-           if (fd_table[fd].write_handler && (pfds[i].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))) {
+           if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) {
                debug(5, 5, "comm_select: FD %d ready for writing\n", fd);
                hdl = fd_table[fd].write_handler;
                fd_table[fd].write_handler = 0;
                hdl(fd, fd_table[fd].write_data);
            }
-           if (pfds[i].revents & POLLNVAL) {
-               f = &fd_table[fd];
+           if (revents & POLLNVAL) {
+               struct close_handler *ch;
+               struct close_handler *next;
+               FD_ENTRY *f = &fd_table[fd];
                debug(5, 0, "WARNING: FD %d has handlers, but it's invalid.\n", fd);
                debug(5, 0, "FD %d is a %s\n", fd, fdstatTypeStr[fdstatGetType(fd)]);
                debug(5, 0, "--> %s\n", fd_note(fd, NULL));
@@ -975,13 +970,17 @@ comm_select(time_t sec)
            ftpServerClose();
            dnsShutdownServers();
            redirectShutdownServers();
-           if (shutdown_pending > 0)
+           /* shutdown_pending will be set to
+            * +1 for SIGTERM
+            * -1 for SIGINT */
+           /* reread_pending always == 1 when SIGHUP received */
+           if (shutdown_pending > 0 || reread_pending > 0)
                setSocketShutdownLifetimes(Config.lifetimeShutdown);
            else
                setSocketShutdownLifetimes(0);
        }
        nfds = 0;
-       maxfd = fdstat_biggest_fd() + 1;
+       maxfd = Biggest_FD + 1;
        for (i = 0; i < maxfd; i++) {
            /* Check each open socket for a handler. */
            if (fd_table[i].stall_until > squid_curtime)
@@ -995,7 +994,7 @@ comm_select(time_t sec)
                FD_SET(i, &writefds);
            }
        }
-       if (!fdstat_are_n_free_fd(RESERVED_FD)) {
+       if (!fdstat_are_n_free_fd(RESERVED_FD) && theHttpConnection >= 0) {
            FD_CLR(theHttpConnection, &readfds);
        }
        if (shutdown_pending || reread_pending)
@@ -1009,6 +1008,7 @@ comm_select(time_t sec)
            poll_time.tv_sec = sec > 0 ? 1 : 0;
            poll_time.tv_usec = 0;
            num = select(maxfd, &readfds, &writefds, NULL, &poll_time);
+           select_loops++;
            getCurrentTime();
            if (num >= 0)
                break;
@@ -1309,7 +1309,6 @@ comm_init(void)
      * Since Squid_MaxFD can be as high as several thousand, don't waste them */
     RESERVED_FD = min(100, Squid_MaxFD / 4);
     /* hardwired lifetimes */
-    fd_lifetime = xmalloc(sizeof(int) * Squid_MaxFD);
     for (i = 0; i < Squid_MaxFD; i++)
        comm_set_fd_lifetime(i, -1);    /* denotes invalid */
     meta_data.misc += Squid_MaxFD * sizeof(int);
@@ -1414,8 +1413,10 @@ checkTimeouts(void)
     FD_ENTRY *f = NULL;
     void *data;
     /* scan for timeout */
-    for (fd = 0; fd < Squid_MaxFD; ++fd) {
+    for (fd = 0; fd <= Biggest_FD; fd++) {
        f = &fd_table[fd];
+       if (!f->openned)
+           continue;
        if ((hdl = f->timeout_handler) == NULL)
            continue;
        if (f->timeout_time > squid_curtime)
@@ -1432,18 +1433,19 @@ static void
 checkLifetimes(void)
 {
     int fd;
-    time_t lft;
     FD_ENTRY *fde = NULL;
 
     PF hdl = NULL;
 
-    for (fd = 0; fd < Squid_MaxFD; fd++) {
-       if ((lft = comm_get_fd_lifetime(fd)) == -1)
+    for (fd = 0; fd <= Biggest_FD; fd++) {
+       fde = &fd_table[fd];
+       if (!fde->openned)
+           continue;
+       if (fde->lifetime < 0)
            continue;
-       if (lft > squid_curtime)
+       if (fde->lifetime > squid_curtime)
            continue;
        debug(5, 5, "checkLifetimes: FD %d Expired\n", fd);
-       fde = &fd_table[fd];
        if ((hdl = fde->lifetime_handler) != NULL) {
            debug(5, 5, "checkLifetimes: FD %d: Calling lifetime handler\n", fd);
            hdl(fd, fde->lifetime_data);
@@ -1572,5 +1574,4 @@ void
 commFreeMemory(void)
 {
     safe_free(fd_table);
-    safe_free(fd_lifetime);
 }
index 103a87b03c5f03aefe817e7ec5d6e741428be0ba..bd1b3284f7abf59bff7d02e1c7cf7314d1d4fe0e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: disk.cc,v 1.57 1997/02/26 19:46:11 wessels Exp $
+ * $Id: disk.cc,v 1.58 1997/04/28 04:23:03 wessels Exp $
  *
  * DEBUG: section 6     Disk I/O Routines
  * AUTHOR: Harvest Derived
@@ -242,7 +242,6 @@ file_open_complete(void *data, int retcode, int errcode)
     xfree(ctrlp);
 }
 
-
 /* must close a disk file */
 
 int
@@ -275,6 +274,22 @@ file_must_close(int fd)
     return DISK_OK;
 }
 
+void
+file_open_fd(int fd, const char *name, File_Desc_Type type)
+{
+    FileEntry *f = &file_table[fd];
+    fdstat_open(fd, type);
+    commSetCloseOnExec(fd);
+    xstrncpy(f->filename, name, SQUID_MAXPATHLEN);
+    f->at_eof = NO;
+    f->open_stat = FILE_OPEN;
+    f->close_request = NOT_REQUEST;
+    f->write_pending = NO_WRT_PENDING;
+    f->write_daemon = NOT_PRESENT;
+    f->write_q = NULL;
+    memset(&fd_table[fd], '\0', sizeof(FD_ENTRY));
+}
+
 
 /* close a disk file. */
 int
@@ -458,8 +473,10 @@ file_write(int fd,
 {
     dwrite_q *wq = NULL;
 
-    if (file_table[fd].open_stat == FILE_NOT_OPEN)
+    if (file_table[fd].open_stat == FILE_NOT_OPEN) {
+       debug_trap("file_write: FILE_NOT_OPEN");
        return DISK_ERROR;
+    }
     /* if we got here. Caller is eligible to write. */
     wq = xcalloc(1, sizeof(dwrite_q));
     wq->buf = ptr_to_buf;
@@ -480,17 +497,18 @@ file_write(int fd,
        file_table[fd].write_q_tail = wq;
     }
 
-    if (file_table[fd].write_daemon == PRESENT)
-       return DISK_OK;
+    if (file_table[fd].write_daemon != PRESENT) {
 #if USE_ASYNC_IO
-    diskHandleWrite(fd, &file_table[fd]);
+       diskHandleWrite(fd, &file_table[fd]);
 #else
-    commSetSelect(fd,
-       COMM_SELECT_WRITE,
-       (PF) diskHandleWrite,
-       (void *) &file_table[fd],
-       0);
+       commSetSelect(fd,
+           COMM_SELECT_WRITE,
+           (PF) diskHandleWrite,
+           (void *) &file_table[fd],
+           0);
 #endif
+       file_table[fd].write_daemon = PRESENT;
+    }
     return DISK_OK;
 }
 
index 99184be85aa216d541d89b222a9f51270dd8d428..778862ba6757efd196f293a418a53848e6f0c5ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dns.cc,v 1.30 1997/02/07 04:57:13 wessels Exp $
+ * $Id: dns.cc,v 1.31 1997/04/28 04:23:04 wessels Exp $
  *
  * DEBUG: section 34    Dnsserver interface
  * AUTHOR: Harvest Derived
@@ -266,7 +266,8 @@ dnsOpenServers(void)
            dns_child_table[k]->id = k + 1;
            dns_child_table[k]->inpipe = dnssocket;
            dns_child_table[k]->outpipe = dnssocket;
-           dns_child_table[k]->lastcall = squid_curtime;
+           dns_child_table[k]->answer = squid_curtime;
+           dns_child_table[k]->dispatch_time = current_time;
            dns_child_table[k]->size = DNS_INBUF_SZ - 1;
            dns_child_table[k]->offset = 0;
            dns_child_table[k]->ip_inbuf = xcalloc(DNS_INBUF_SZ, 1);
@@ -278,7 +279,7 @@ dnsOpenServers(void)
            NDnsServersAlloc++;
        }
     }
-    if (NDnsServersAlloc == 0)
+    if (NDnsServersAlloc == 0 && Config.dnsChildren > 0)
        fatal("Failed to start any dnsservers");
     debug(34, 1, "Started %d 'dnsserver' processes\n", NDnsServersAlloc);
 }
@@ -288,7 +289,7 @@ void
 dnsStats(StoreEntry * sentry)
 {
     int k;
-
+    dnsserver_t *dns = NULL;
     storeAppendPrintf(sentry, "{DNSServer Statistics:\n");
     storeAppendPrintf(sentry, "{dnsserver requests: %d}\n",
        DnsStats.requests);
@@ -302,7 +303,31 @@ dnsStats(StoreEntry * sentry)
            k + 1,
            DnsStats.hist[k]);
     }
-    storeAppendPrintf(sentry, "}\n\n");
+    storeAppendPrintf(sentry, "{}\n");
+    storeAppendPrintf(sentry, "{dnsservers status:}\n");
+    for (k = 0; k < NDnsServersAlloc; k++) {
+       dns = *(dns_child_table + k);
+       storeAppendPrintf(sentry, "{dnsserver #%d:}\n", k + 1);
+       storeAppendPrintf(sentry, "{    Flags: %c%c%c}\n",
+           dns->flags & DNS_FLAG_ALIVE ? 'A' : ' ',
+           dns->flags & DNS_FLAG_BUSY ? 'B' : ' ',
+           dns->flags & DNS_FLAG_CLOSING ? 'C' : ' ');
+       storeAppendPrintf(sentry, "{    FDs (in/out): %d/%d}\n",
+           dns->inpipe, dns->outpipe);
+       storeAppendPrintf(sentry, "{    Alive since: %s}\n",
+           mkrfc1123(dns->answer));
+       storeAppendPrintf(sentry, "{    Last Dispatched: %0.3f seconds ago}\n",
+           0.001 * tvSubMsec(dns->dispatch_time, current_time));
+       storeAppendPrintf(sentry, "{    Read Buffer Size: %d bytes}\n",
+           dns->size);
+       storeAppendPrintf(sentry, "{    Read Offset: %d bytes}\n",
+           dns->offset);
+    }
+    storeAppendPrintf(sentry, "\n{Flags key:}\n\n");
+    storeAppendPrintf(sentry, "{   A = ALIVE}\n");
+    storeAppendPrintf(sentry, "{   B = BUSY}\n");
+    storeAppendPrintf(sentry, "{   C = CLOSING}\n");
+
     storeAppendPrintf(sentry, close_bracket);
 }
 
index 792092205fe5a49e036a1e73923644ae36ee8433..ed0aa931231d9ffb4c5e735c21acab304a5c7ba3 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: dnsserver.cc,v 1.32 1997/02/06 18:02:10 wessels Exp $
+ * $Id: dnsserver.cc,v 1.33 1997/04/28 04:23:05 wessels Exp $
  *
  * DEBUG: section 0     DNS Resolver
  * AUTHOR: Harvest Derived
@@ -227,7 +227,7 @@ struct hostent *_res_gethostbyname(char *name);
 #endif /* _SQUID_NEXT_ */
 
 static int do_debug = 0;
-static unsigned int inaddr_none;
+static struct in_addr no_addr;
 
 /* error messages from gethostbyname() */
 static char *
@@ -261,7 +261,7 @@ main(int argc, char *argv[])
     int i;
     int c;
 
-    inaddr_none = inet_addr("255.255.255.255");
+    safe_inet_addr("255.255.255.255", &no_addr);
 
 #if HAVE_RES_INIT
     res_init();
@@ -301,7 +301,7 @@ main(int argc, char *argv[])
 
     for (;;) {
        int retry_count = 0;
-       int addrbuf;
+       struct in_addr ip;
        memset(request, '\0', 256);
 
        /* read from ipcache */
@@ -323,7 +323,7 @@ main(int argc, char *argv[])
        result = NULL;
        start = time(NULL);
        /* check if it's already an IP address in text form. */
-       if (inet_addr(request) != inaddr_none) {
+       if (safe_inet_addr(request, &ip)) {
 #if NO_REVERSE_LOOKUP
            printf("$name %s\n", request);
            printf("$h_name %s\n", request);
@@ -335,9 +335,8 @@ main(int argc, char *argv[])
            fflush(stdout);
            continue;
 #endif
-           addrbuf = inet_addr(request);
            for (;;) {
-               result = gethostbyaddr((char *) &addrbuf, 4, AF_INET);
+               result = gethostbyaddr((char *) &ip.s_addr, 4, AF_INET);
                if (result || h_errno != TRY_AGAIN)
                    break;
                if (++retry_count == 2)
index a6af14df9d52fdf06ab40ac3087331f071810389..0931813a186eb3c14aae967bfd984501230af18f 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: fqdncache.cc,v 1.47 1997/03/04 05:16:28 wessels Exp $
+ * $Id: fqdncache.cc,v 1.48 1997/04/28 04:23:07 wessels Exp $
  *
  * DEBUG: section 35    FQDN Cache
  * AUTHOR: Harvest Derived
@@ -143,11 +143,10 @@ static int fqdncache_purgelru _PARAMS((void));
 static void fqdncache_release _PARAMS((fqdncache_entry *));
 static fqdncache_entry *fqdncache_GetFirst _PARAMS((void));
 static fqdncache_entry *fqdncache_GetNext _PARAMS((void));
-static fqdncache_entry *fqdncache_create _PARAMS((void));
+static fqdncache_entry *fqdncache_create _PARAMS((const char *name));
 static void fqdncache_add_to_hash _PARAMS((fqdncache_entry *));
 static void fqdncache_call_pending _PARAMS((fqdncache_entry *));
-static void fqdncache_call_pending_badname _PARAMS((int fd, FQDNH handler, void *));
-static void fqdncache_add _PARAMS((const char *, fqdncache_entry *, const struct hostent *, int));
+static void fqdncacheAddHostent _PARAMS((fqdncache_entry *, const struct hostent *));
 static int fqdncacheHasPending _PARAMS((const fqdncache_entry *));
 static fqdncache_entry *fqdncache_get _PARAMS((const char *));
 static void dummy_handler _PARAMS((int, const char *, void *));
@@ -156,6 +155,9 @@ static void fqdncacheAddPending _PARAMS((fqdncache_entry *, int fd, FQDNH, void
 static void fqdncacheEnqueue _PARAMS((fqdncache_entry *));
 static void *fqdncacheDequeue _PARAMS((void));
 static void fqdncache_dnsDispatch _PARAMS((dnsserver_t *, fqdncache_entry *));
+static void fqdncacheChangeKey _PARAMS((fqdncache_entry * i));
+static void fqdncacheLockEntry _PARAMS((fqdncache_entry * f));
+static void fqdncacheUnlockEntry _PARAMS((fqdncache_entry * f));
 
 static HashID fqdn_table = 0;
 static struct fqdncacheQueueData *fqdncacheQueueHead = NULL;
@@ -195,6 +197,8 @@ fqdncacheDequeue(void)
            fqdncacheQueueTailP = &fqdncacheQueueHead;
        safe_free(old);
     }
+    if (f && f->status != FQDN_PENDING)
+       debug_trap("fqdncacheDequeue: status != FQDN_PENDING");
     return f;
 }
 
@@ -202,7 +206,6 @@ fqdncacheDequeue(void)
 static void
 fqdncache_release(fqdncache_entry * f)
 {
-    fqdncache_entry *result = NULL;
     hash_link *table_entry = NULL;
     int k;
 
@@ -210,9 +213,8 @@ fqdncache_release(fqdncache_entry * f)
        debug(35, 0, "fqdncache_release: Could not find key '%s'\n", f->name);
        return;
     }
-    result = (fqdncache_entry *) table_entry;
-    if (f != result)
-       fatal_dump("fqdncache_release: expected f == result!");
+    if (f != (fqdncache_entry *) table_entry)
+       fatal_dump("fqdncache_release: f != table_entry!");
     if (f->status == FQDN_PENDING) {
        debug(35, 1, "fqdncache_release: Someone called on a PENDING entry\n");
        return;
@@ -223,19 +225,18 @@ fqdncache_release(fqdncache_entry * f)
     }
     if (hash_remove_link(fqdn_table, table_entry)) {
        debug(35, 0, "fqdncache_release: hash_remove_link() failed for '%s'\n",
-           result->name);
+           f->name);
        return;
     }
-    if (result->status == FQDN_CACHED) {
+    if (f->status == FQDN_CACHED) {
        for (k = 0; k < (int) f->name_count; k++)
            safe_free(f->names[k]);
        debug(35, 5, "fqdncache_release: Released FQDN record for '%s'.\n",
-           result->name);
+           f->name);
     }
-    safe_free(result->name);
-    safe_free(result->error_message);
-    memset(result, '\0', sizeof(fqdncache_entry));
-    safe_free(result);
+    safe_free(f->name);
+    safe_free(f->error_message);
+    safe_free(f);
     --meta_data.fqdncache_count;
     return;
 }
@@ -286,6 +287,8 @@ fqdncacheExpiredEntry(const fqdncache_entry * f)
        return 0;
     if (f->status == FQDN_DISPATCHED)
        return 0;
+    if (f->locks != 0)
+       return 0;
     if (f->expires > squid_curtime)
        return 0;
     return 1;
@@ -340,11 +343,13 @@ fqdncache_purgelru(void)
     /* sort LRU candidate list */
     qsort((char *) LRU_list,
        LRU_list_count,
-       sizeof(f),
-       (int (*)(const void *, const void *)) fqdncache_compareLastRef);
-    for (k = 0; LRU_list[k] && (meta_data.fqdncache_count > fqdncache_low)
-       && k < LRU_list_count;
-       ++k) {
+       sizeof(fqdncache_entry *),
+       (QS) fqdncache_compareLastRef);
+    for (k = 0; k < LRU_list_count; k++) {
+       if (meta_data.fqdncache_count < fqdncache_low)
+           break;
+       if (LRU_list[k] == NULL)
+           break;
        fqdncache_release(LRU_list[k]);
        removed++;
     }
@@ -357,7 +362,7 @@ fqdncache_purgelru(void)
 
 /* create blank fqdncache_entry */
 static fqdncache_entry *
-fqdncache_create(void)
+fqdncache_create(const char *name)
 {
     static fqdncache_entry *new;
 
@@ -367,6 +372,9 @@ fqdncache_create(void)
     }
     meta_data.fqdncache_count++;
     new = xcalloc(1, sizeof(fqdncache_entry));
+    new->name = xstrdup(name);
+    new->expires = squid_curtime + Config.negativeDnsTtl;
+    fqdncache_add_to_hash(new);
     return new;
 }
 
@@ -380,34 +388,34 @@ fqdncache_add_to_hash(fqdncache_entry * f)
     debug(35, 5, "fqdncache_add_to_hash: name <%s>\n", f->name);
 }
 
-
 static void
-fqdncache_add(const char *name, fqdncache_entry * f, const struct hostent *hp, int cached)
+fqdncacheAddHostent(fqdncache_entry * f, const struct hostent *hp)
 {
     int k;
+    f->name_count = 0;
+    f->names[f->name_count++] = xstrdup((char *) hp->h_name);
+    for (k = 0; hp->h_aliases[k]; k++) {
+       f->names[f->name_count++] = xstrdup(hp->h_aliases[k]);
+       if (f->name_count == FQDN_MAX_NAMES)
+           break;
+    }
+}
 
+static fqdncache_entry *
+fqdncacheAddNew(const char *name, const struct hostent *hp, fqdncache_status_t status)
+{
+    fqdncache_entry *f;
     if (fqdncache_get(name))
-       fatal_dump("fqdncache_add: somebody adding a duplicate!");
-    debug(35, 10, "fqdncache_add: Adding name '%s' (%s).\n", name,
-       cached ? "cached" : "not cached");
-    f->name = xstrdup(name);
-    if (cached) {
-       f->name_count = 0;
-       f->names[f->name_count++] = xstrdup((char *) hp->h_name);
-       for (k = 0; hp->h_aliases[k]; k++) {
-           f->names[f->name_count++] = xstrdup(hp->h_aliases[k]);
-           if (f->name_count == FQDN_MAX_NAMES)
-               break;
-       }
-       f->lastref = squid_curtime;
-       f->status = FQDN_CACHED;
-       f->expires = squid_curtime + Config.positiveDnsTtl;
-    } else {
-       f->lastref = squid_curtime;
-       f->status = FQDN_NEGATIVE_CACHED;
-       f->expires = squid_curtime + Config.negativeDnsTtl;
-    }
-    fqdncache_add_to_hash(f);
+       fatal_dump("fqdncacheAddNew: somebody adding a duplicate!");
+    debug(14, 10, "fqdncacheAddNew: Adding '%s', status=%c\n",
+       name,
+       fqdncache_status_char[status]);
+    f = fqdncache_create(name);
+    if (hp)
+       fqdncacheAddHostent(f, hp);
+    f->status = status;
+    f->lastref = squid_curtime;
+    return f;
 }
 
 /* walks down the pending list, calling handlers */
@@ -419,6 +427,7 @@ fqdncache_call_pending(fqdncache_entry * f)
 
     f->lastref = squid_curtime;
 
+    fqdncacheLockEntry(f);
     while (f->pending_head != NULL) {
        p = f->pending_head;
        f->pending_head = p->next;
@@ -429,18 +438,11 @@ fqdncache_call_pending(fqdncache_entry * f)
                (f->status == FQDN_CACHED) ? f->names[0] : NULL,
                p->handlerData);
        }
-       memset(p, '\0', sizeof(struct _fqdn_pending));
        safe_free(p);
     }
     f->pending_head = NULL;    /* nuke list */
     debug(35, 10, "fqdncache_call_pending: Called %d handlers.\n", nhandler);
-}
-
-static void
-fqdncache_call_pending_badname(int fd, FQDNH handler, void *data)
-{
-    debug(35, 0, "fqdncache_call_pending_badname: Bad Name: Calling handler with NULL result.\n");
-    handler(fd, NULL, data);
+    fqdncacheUnlockEntry(f);
 }
 
 static fqdncache_entry *
@@ -510,6 +512,15 @@ fqdncache_parsebuffer(const char *inbuf, dnsserver_t * dnsData)
     return &f;
 }
 
+static void
+fqdncacheNudgeQueue(void)
+{
+    dnsserver_t *dnsData;
+    fqdncache_entry *f = NULL;
+    while ((dnsData = dnsGetFirstAvailable()) && (f = fqdncacheDequeue()))
+       fqdncache_dnsDispatch(dnsData, f);
+}
+
 static void
 fqdncache_dnsHandleRead(int fd, void *data)
 {
@@ -549,7 +560,9 @@ fqdncache_dnsHandleRead(int fd, void *data)
     DnsStats.replies++;
     dnsData->offset += len;
     dnsData->ip_inbuf[dnsData->offset] = '\0';
-
+    f = dnsData->data;
+    if (f->status != FQDN_DISPATCHED)
+       fatal_dump("fqdncache_dnsHandleRead: bad status");
     if (strstr(dnsData->ip_inbuf, "$end\n")) {
        /* end of record found */
        svc_time = tvSubMsec(dnsData->dispatch_time, current_time);
@@ -562,7 +575,6 @@ fqdncache_dnsHandleRead(int fd, void *data)
        } else {
            dnsData->offset = 0;
            dnsData->ip_inbuf[0] = '\0';
-           f = dnsData->data;
            f->name_count = x->name_count;
            for (n = 0; n < (int) f->name_count; n++)
                f->names[n] = x->names[n];
@@ -571,6 +583,7 @@ fqdncache_dnsHandleRead(int fd, void *data)
            f->expires = x->expires;
            fqdncache_call_pending(f);
        }
+       fqdncacheUnlockEntry(f);        /* unlock from FQDN_DISPATCHED */
     }
     if (dnsData->offset == 0) {
        dnsData->data = NULL;
@@ -581,8 +594,7 @@ fqdncache_dnsHandleRead(int fd, void *data)
        COMM_SELECT_READ,
        fqdncache_dnsHandleRead,
        dnsData, 0);
-    while ((dnsData = dnsGetFirstAvailable()) && (f = fqdncacheDequeue()))
-       fqdncache_dnsDispatch(dnsData, f);
+    fqdncacheNudgeQueue();
 }
 
 static void
@@ -590,16 +602,17 @@ fqdncacheAddPending(fqdncache_entry * f, int fd, FQDNH handler, void *handlerDat
 {
     struct _fqdn_pending *pending = xcalloc(1, sizeof(struct _fqdn_pending));
     struct _fqdn_pending **I = NULL;
-
+    f->lastref = squid_curtime;
     pending->fd = fd;
     pending->handler = handler;
     pending->handlerData = handlerData;
-
     for (I = &(f->pending_head); *I; I = &((*I)->next));
     *I = pending;
+    if (f->status == IP_PENDING)
+       fqdncacheNudgeQueue();
 }
 
-int
+void
 fqdncache_nbgethostbyaddr(struct in_addr addr, int fd, FQDNH handler, void *handlerData)
 {
     fqdncache_entry *f = NULL;
@@ -614,8 +627,8 @@ fqdncache_nbgethostbyaddr(struct in_addr addr, int fd, FQDNH handler, void *hand
 
     if (name == NULL || name[0] == '\0') {
        debug(35, 4, "fqdncache_nbgethostbyaddr: Invalid name!\n");
-       fqdncache_call_pending_badname(fd, handler, handlerData);
-       return 0;
+       handler(fd, NULL, handlerData);
+       return;
     }
     if ((f = fqdncache_get(name))) {
        if (fqdncacheExpiredEntry(f)) {
@@ -627,11 +640,8 @@ fqdncache_nbgethostbyaddr(struct in_addr addr, int fd, FQDNH handler, void *hand
        /* MISS: No entry, create the new one */
        debug(35, 5, "fqdncache_nbgethostbyaddr: MISS for '%s'\n", name);
        FqdncacheStats.misses++;
-       f = fqdncache_create();
-       f->name = xstrdup(name);
-       f->status = FQDN_PENDING;
+       f = fqdncacheAddNew(name, NULL, FQDN_PENDING);
        fqdncacheAddPending(f, fd, handler, handlerData);
-       fqdncache_add_to_hash(f);
     } else if (f->status == FQDN_CACHED || f->status == FQDN_NEGATIVE_CACHED) {
        /* HIT */
        debug(35, 4, "fqdncache_nbgethostbyaddr: HIT for '%s'\n", name);
@@ -641,23 +651,33 @@ fqdncache_nbgethostbyaddr(struct in_addr addr, int fd, FQDNH handler, void *hand
            FqdncacheStats.hits++;
        fqdncacheAddPending(f, fd, handler, handlerData);
        fqdncache_call_pending(f);
-       return 0;
+       return;
     } else if (f->status == FQDN_PENDING || f->status == FQDN_DISPATCHED) {
        debug(35, 4, "fqdncache_nbgethostbyaddr: PENDING for '%s'\n", name);
        FqdncacheStats.pending_hits++;
        fqdncacheAddPending(f, fd, handler, handlerData);
-       return 0;
+       if (squid_curtime - f->expires > 600) {
+           debug(14, 0, "fqdncache_nbgethostbyname: '%s' PENDING for %d seconds, aborting\n", name, squid_curtime + Config.negativeDnsTtl - f->expires);
+           fqdncacheChangeKey(f);
+           fqdncache_call_pending(f);
+       }
+       return;
     } else {
        fatal_dump("fqdncache_nbgethostbyaddr: BAD fqdncache_entry status");
     }
 
     /* for HIT, PENDING, DISPATCHED we've returned.  For MISS we continue */
 
-    if ((dnsData = dnsGetFirstAvailable()))
+    if ((dnsData = dnsGetFirstAvailable())) {
        fqdncache_dnsDispatch(dnsData, f);
-    else
+       return;
+    }
+    if (NDnsServersAlloc > 0) {
        fqdncacheEnqueue(f);
-    return 0;
+       return;
+    }
+    fqdncache_gethostbyaddr(addr, FQDN_BLOCKING_LOOKUP);
+    fqdncache_call_pending(f);
 }
 
 static void
@@ -673,11 +693,13 @@ fqdncache_dnsDispatch(dnsserver_t * dns, fqdncache_entry * f)
        fqdncache_release(f);
        return;
     }
-    f->status = FQDN_DISPATCHED;
+    if (f->status != FQDN_PENDING)
+       debug_trap("fqdncache_dnsDispatch: status != FQDN_PENDING");
     buf = xcalloc(1, 256);
     sprintf(buf, "%1.254s\n", f->name);
     dns->flags |= DNS_FLAG_BUSY;
     dns->data = f;
+    f->status = FQDN_DISPATCHED;
     comm_write(dns->outpipe,
        buf,
        strlen(buf),
@@ -695,6 +717,7 @@ fqdncache_dnsDispatch(dnsserver_t * dns, fqdncache_entry * f)
     dns->dispatch_time = current_time;
     DnsStats.requests++;
     DnsStats.hist[dns->id - 1]++;
+    fqdncacheLockEntry(f);     /* lock while IP_DISPATCHED */
 }
 
 
@@ -746,16 +769,24 @@ fqdncache_gethostbyaddr(struct in_addr addr, int flags)
     char *name = inet_ntoa(addr);
     fqdncache_entry *f = NULL;
     const struct hostent *hp = NULL;
-    unsigned int ip;
+    struct in_addr ip;
     static char *static_name = NULL;
 
     if (!name)
        fatal_dump("fqdncache_gethostbyaddr: NULL name");
     FqdncacheStats.requests++;
     if ((f = fqdncache_get(name))) {
+       if (fqdncacheExpiredEntry(f)) {
+           fqdncache_release(f);
+           f = NULL;
+       }
+    }
+    if (f) {
        if (f->status == FQDN_PENDING || f->status == FQDN_DISPATCHED) {
-           FqdncacheStats.pending_hits++;
-           return NULL;
+           if (!BIT_TEST(flags, IP_BLOCKING_LOOKUP)) {
+               FqdncacheStats.pending_hits++;
+               return NULL;
+           }
        } else if (f->status == FQDN_NEGATIVE_CACHED) {
            FqdncacheStats.negative_hits++;
            dns_error_message = f->error_message;
@@ -766,30 +797,36 @@ fqdncache_gethostbyaddr(struct in_addr addr, int flags)
            return f->names[0];
        }
     }
-    FqdncacheStats.misses++;
     /* check if it's already a FQDN address in text form. */
-    if (inet_addr(name) == inaddr_none) {
+    if (!safe_inet_addr(name, &ip))
        return name;
-    }
-    if (flags & FQDN_BLOCKING_LOOKUP) {
+    FqdncacheStats.misses++;
+    if (BIT_TEST(flags, FQDN_BLOCKING_LOOKUP)) {
+       if (NDnsServersAlloc)
+           debug(14, 0, "WARNING: blocking on gethostbyaddr() for '%s'\n", name);
        FqdncacheStats.ghba_calls++;
-       ip = inet_addr(name);
-       hp = gethostbyaddr((char *) &ip, 4, AF_INET);
+       hp = gethostbyaddr((char *) &ip.s_addr, 4, AF_INET);
        if (hp && hp->h_name && (hp->h_name[0] != '\0') && fqdn_table) {
-           if (f->status == FQDN_PENDING || f->status == FQDN_DISPATCHED) {
+           if (f == NULL) {
+               f = fqdncacheAddNew(name, hp, FQDN_CACHED);
+           } else if (f->status == FQDN_DISPATCHED) {
+               /* only dnsHandleRead() can change from DISPATCHED to CACHED */
                xfree(static_name);
                static_name = xstrdup(hp->h_name);
                return static_name;
+           } else {
+               fqdncacheAddHostent(f, hp);
+               f->status = FQDN_CACHED;
            }
-           /* good address, cached */
-           fqdncache_add(name, fqdncache_create(), hp, 1);
-           f = fqdncache_get(name);
+           f->expires = squid_curtime + Config.positiveDnsTtl;
            return f->names[0];
        }
        /* bad address, negative cached */
-       if (fqdn_table)
-           fqdncache_add(name, fqdncache_create(), hp, 0);
-       return NULL;
+       if (fqdn_table && f == NULL) {
+           f = fqdncacheAddNew(name, hp, FQDN_NEGATIVE_CACHED);
+           f->expires = squid_curtime + Config.negativeDnsTtl;
+           return NULL;
+       }
     }
     if (flags & FQDN_LOOKUP_IF_MISS)
        fqdncache_nbgethostbyaddr(addr, -1, dummy_handler, NULL);
@@ -897,6 +934,24 @@ fqdncacheQueueDrain(void)
     return 1;
 }
 
+static void
+fqdncacheLockEntry(fqdncache_entry * f)
+{
+    f->locks++;
+}
+
+static void
+fqdncacheUnlockEntry(fqdncache_entry * f)
+{
+    if (f->locks == 0) {
+       debug_trap("fqdncacheUnlockEntry: Entry has no locks");
+       return;
+    }
+    f->locks--;
+    if (fqdncacheExpiredEntry(f))
+       fqdncache_release(f);
+}
+
 void
 fqdncacheFreeMemory(void)
 {
@@ -923,3 +978,53 @@ fqdncacheFreeMemory(void)
     xfree(list);
     hashFreeMemory(fqdn_table);
 }
+
+static void
+fqdncacheChangeKey(fqdncache_entry * f)
+{
+    static int index = 0;
+    LOCAL_ARRAY(char, new_key, 256);
+    hash_link *table_entry = hash_lookup(fqdn_table, f->name);
+    if (table_entry == NULL) {
+       debug(14, 0, "fqdncacheChangeKey: Could not find key '%s'\n", f->name);
+       return;
+    }
+    if (f != (fqdncache_entry *) table_entry) {
+       debug_trap("fqdncacheChangeKey: f != table_entry!");
+       return;
+    }
+    if (hash_remove_link(fqdn_table, table_entry)) {
+       debug_trap("fqdncacheChangeKey: hash_remove_link() failed\n");
+       return;
+    }
+    sprintf(new_key, "%d/", ++index);
+    strncat(new_key, f->name, 128);
+    debug(14, 1, "fqdncacheChangeKey: from '%s' to '%s'\n", f->name, new_key);
+    safe_free(f->name);
+    f->name = xstrdup(new_key);
+    fqdncache_add_to_hash(f);
+}
+
+/* call during reconfigure phase to clear out all the
+ * pending and dispatched reqeusts that got lost */
+void
+fqdncache_restart(void)
+{
+    fqdncache_entry *this;
+    fqdncache_entry *next;
+    if (fqdn_table == 0)
+       fatal_dump("fqdncache_restart: fqdn_table == 0\n");
+    while (fqdncacheDequeue());
+    next = (fqdncache_entry *) hash_first(fqdn_table);
+    while ((this = next)) {
+       next = (fqdncache_entry *) hash_next(fqdn_table);
+       if (this->status == FQDN_CACHED)
+           continue;
+       if (this->status == FQDN_NEGATIVE_CACHED)
+           continue;
+       /* else its PENDING or DISPATCHED; there are no dnsservers
+        * running, so abort it */
+       this->status = FQDN_NEGATIVE_CACHED;
+       fqdncache_release(this);
+    }
+}
index 33f4eae47ca368cfb7dd5621adac5f9bd2e5f501..e6692b24bd043b18483d0691ea589d9d89c7cdab 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ftp.cc,v 1.98 1997/03/29 04:45:16 wessels Exp $
+ * $Id: ftp.cc,v 1.99 1997/04/28 04:23:08 wessels Exp $
  *
  * DEBUG: section 9     File Transfer Protocol (FTP)
  * AUTHOR: Harvest Derived
@@ -167,23 +167,18 @@ ftpStateFree(int fd, FtpStateData * ftpState)
 static void
 ftp_login_parser(const char *login, FtpStateData * data)
 {
-    char *user = data->user;
-    char *password = data->password;
     char *s = NULL;
-
-    strcpy(user, login);
-    s = strchr(user, ':');
-    if (s) {
+    xstrncpy(data->user, login, MAX_URL);
+    if ((s = strchr(data->user, ':'))) {
        *s = 0;
-       strcpy(password, s + 1);
+       xstrncpy(data->password, s + 1, MAX_URL);
     } else {
-       strcpy(password, null_string);
-    }
-
-    if (!*user && !*password) {
-       strcpy(user, "anonymous");
-       strcpy(password, Config.ftpUser);
+       xstrncpy(data->password, null_string, MAX_URL);
     }
+    if (data->user[0] || data->password[0])
+       return;
+    xstrncpy(data->user, "anonymous", MAX_URL);
+    xstrncpy(data->password, Config.ftpUser, MAX_URL);
 }
 
 /* This will be called when socket lifetime is expired. */
@@ -459,11 +454,9 @@ ftpSendRequest(int fd, FtpStateData * data)
     char *s = NULL;
     int got_timeout = 0;
     int got_negttl = 0;
-    int buflen;
 
     debug(9, 5, "ftpSendRequest: FD %d\n", fd);
 
-    buflen = strlen(data->request->urlpath) + 256;
     buf = get_free_8k_page();
 
     path = data->request->urlpath;
@@ -501,7 +494,7 @@ ftpSendRequest(int fd, FtpStateData * data)
     if (data->authenticated) {
        strcat(buf, "-a ");
     }
-    if (Config.Addrs.tcp_outgoing.s_addr != inaddr_none) {
+    if (Config.Addrs.tcp_outgoing.s_addr != no_addr.s_addr) {
        sprintf(tbuf, "-o %s ", inet_ntoa(Config.Addrs.tcp_outgoing));
        strcat(buf, tbuf);
     }
@@ -545,6 +538,38 @@ ftpGetBasicAuth(const char *req_hdr)
     return base64_decode(t);
 }
 
+/*
+ * ftpCheckAuth
+ *
+ * Return 1 if we have everything needed to complete this request.
+ * Return 0 if something is missing.
+ */
+static int
+ftpCheckAuth(FtpStateData * ftpState, char *req_hdr)
+{
+    char *orig_user;
+    char *auth;
+    ftp_login_parser(ftpState->request->login, ftpState);
+    if (ftpState->user[0] && ftpState->password[0])
+       return 1;               /* name and passwd both in URL */
+    if (!ftpState->user[0] && !ftpState->password[0])
+       return 1;               /* no name or passwd */
+    if (ftpState->password[0])
+       return 1;               /* passwd with no name? */
+    /* URL has name, but no passwd */
+    if ((auth = ftpGetBasicAuth(req_hdr)) == NULL)
+       return 0;               /* need auth header */
+    orig_user = xstrdup(ftpState->user);
+    ftp_login_parser(auth, ftpState);
+    if (!strcmp(orig_user, ftpState->user)) {
+       xfree(orig_user);
+       return 1;               /* same username */
+    }
+    strcpy(ftpState->user, orig_user);
+    xfree(orig_user);
+    return 0;                  /* different username */
+}
+
 
 int
 ftpStart(request_t * request, StoreEntry * entry)
@@ -573,32 +598,24 @@ ftpStartComplete(void *data, int status)
     FtpStateData *ftpData = xcalloc(1, sizeof(FtpStateData));
     char *req_hdr;
     char *response;
-    char *auth;
     ftpData->entry = entry;
     xfree(ctrlp);
     req_hdr = entry->mem_obj->mime_hdr;
     ftpData->request = requestLink(request);
-    /* Parse login info. */
-    if ((auth = ftpGetBasicAuth(req_hdr))) {
-       ftp_login_parser(auth, ftpData);
-       ftpData->authenticated = 1;
-    } else {
-       ftp_login_parser(request->login, ftpData);
-       if (*ftpData->user && !*ftpData->password) {
-           /* This request is not fully authenticated */
-           if (request->port == 21) {
-               sprintf(realm, "ftp %s", ftpData->user);
-           } else {
-               sprintf(realm, "ftp %s port %d",
-                   ftpData->user, request->port);
-           }
-           response = authorization_needed_msg(request, realm);
-           storeAppend(entry, response, strlen(response));
-           httpParseReplyHeaders(response, entry->mem_obj->reply);
-           storeComplete(entry);
-           ftpStateFree(-1, ftpData);
-           return;
+    if (!ftpCheckAuth(ftpData, req_hdr)) {
+       /* This request is not fully authenticated */
+       if (request->port == 21) {
+           sprintf(realm, "ftp %s", ftpData->user);
+       } else {
+           sprintf(realm, "ftp %s port %d",
+               ftpData->user, request->port);
        }
+       response = authorization_needed_msg(request, realm);
+       storeAppend(entry, response, strlen(response));
+       httpParseReplyHeaders(response, entry->mem_obj->reply);
+       storeComplete(entry);
+       ftpStateFree(-1, ftpData);
+       return;
     }
     debug(9, 5, "FtpStart: host=%s, path=%s, user=%s, passwd=%s\n",
        ftpData->request->host, ftpData->request->urlpath,
@@ -636,7 +653,6 @@ ftpConnectDone(int fd, int status, void *data)
        comm_close(fd);
        return;
     }
-    fdstat_open(fd, FD_SOCKET);
     commSetNonBlocking(fd);
     (void) fd_note(fd, ftpData->entry->url);
     /* Install connection complete handler. */
@@ -778,7 +794,7 @@ ftpInitialize(void)
     close(ftpget_to_squid[1]);
     dup2(cfd, 3);              /* pass listening socket to ftpget */
     /* inherit stdin,stdout,stderr */
-    for (cfd = 4; cfd <= fdstat_biggest_fd(); cfd++)
+    for (cfd = 4; cfd <= Biggest_FD; cfd++)
        (void) close(cfd);
     sprintf(pbuf, "%d", ftpget_port);
     execlp(ftpget, ftpget, "-S", pbuf, NULL);
index bee2a302da20b96d5573a4e0d73f0b071fe270f7..23c8b7428217e0ff6808f216cfcc3438dc8a64c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: http.cc,v 1.153 1997/03/04 05:16:31 wessels Exp $
+ * $Id: http.cc,v 1.154 1997/04/28 04:23:11 wessels Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -240,6 +240,8 @@ httpStateFree(int fd, void *data)
        put_free_8k_page(httpState->reply_hdr);
        httpState->reply_hdr = NULL;
     }
+    if (httpState->ip_lookup_pending)
+       ipcache_unregister(httpState->request->host, httpState->fd);
     requestUnlink(httpState->request);
     requestUnlink(httpState->orig_request);
     xfree(httpState);
@@ -607,8 +609,8 @@ httpReadReply(int fd, void *data)
     errno = 0;
     len = read(fd, buf, SQUID_TCP_SO_RCVBUF);
     debug(11, 5, "httpReadReply: FD %d: len %d.\n", fd, len);
-    comm_set_fd_lifetime(fd, 86400);   /* extend after good read */
     if (len > 0) {
+       comm_set_fd_lifetime(fd, 86400);        /* extend after good read */
        IOStats.Http.reads++;
        for (clen = len - 1, bin = 0; clen; bin++)
            clen >>= 1;
@@ -726,8 +728,8 @@ httpBuildRequestHeader(request_t * request,
     size_t out_sz,
     int cfd)
 {
+    LOCAL_ARRAY(char, ybuf, MAX_URL + 32);
     char *xbuf = get_free_4k_page();
-    char *ybuf = get_free_8k_page();
     char *viabuf = get_free_4k_page();
     char *fwdbuf = get_free_4k_page();
     char *t = NULL;
@@ -815,7 +817,6 @@ httpBuildRequestHeader(request_t * request,
     }
     httpAppendRequestHeader(hdr_out, null_string, &len, out_sz);
     put_free_4k_page(xbuf);
-    put_free_8k_page(ybuf);
     put_free_4k_page(viabuf);
     put_free_4k_page(fwdbuf);
     if (in_len)
@@ -940,8 +941,9 @@ proxyhttpStartComplete(void *data, int status)
     httpState->request = requestLink(request);
     httpState->neighbor = e;
     httpState->orig_request = requestLink(orig_request);
+    httpState->fd = sock;
     /* register the handler to free HTTP state data when the FD closes */
-    comm_add_close_handler(sock,
+    comm_add_close_handler(httpState->fd,
        httpStateFree,
        (void *) httpState);
     request->method = orig_request->method;
@@ -949,8 +951,9 @@ proxyhttpStartComplete(void *data, int status)
     request->port = e->http_port;
     xstrncpy(request->urlpath, url, MAX_URL);
     BIT_SET(request->flags, REQ_PROXYING);
+    httpState->ip_lookup_pending = 1;
     ipcache_nbgethostbyname(request->host,
-       sock,
+       httpState->fd,
        httpConnect,
        httpState);
     return;
@@ -962,6 +965,7 @@ httpConnect(int fd, const ipcache_addrs * ia, void *data)
     HttpStateData *httpState = data;
     request_t *request = httpState->request;
     StoreEntry *entry = httpState->entry;
+    httpState->ip_lookup_pending = 0;
     if (ia == NULL) {
        debug(11, 4, "httpConnect: Unknown host: %s\n", request->host);
        squid_error_entry(entry, ERR_DNS_FAIL, dns_error_message);
@@ -1057,11 +1061,13 @@ httpStartComplete(void *data, int status)
     httpState->req_hdr = req_hdr;
     httpState->req_hdr_sz = req_hdr_sz;
     httpState->request = requestLink(request);
-    comm_add_close_handler(sock,
+    httpState->fd = sock;
+    comm_add_close_handler(httpState->fd,
        httpStateFree,
        (void *) httpState);
+    httpState->ip_lookup_pending = 1;
     ipcache_nbgethostbyname(request->host,
-       sock,
+       httpState->fd,
        httpConnect,
        httpState);
 }
index fa2bc496d2d966172e300a143804cc793142c63c..0ad95a42582de756d3a4e05bc118e33659c0c024 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: icmp.cc,v 1.32 1997/03/04 05:16:32 wessels Exp $
+ * $Id: icmp.cc,v 1.33 1997/04/28 04:23:12 wessels Exp $
  *
  * DEBUG: section 37    ICMP Routines
  * AUTHOR: Duane Wessels
@@ -259,7 +259,7 @@ icmpOpen(void)
        local_addr,
        0,
        COMM_NONBLOCKING,
-       "ICMP Socket");
+       "Pinger Socket");
     if (icmp_sock < 0) {
        debug(50, 0, "icmpOpen: icmp_sock: %s\n", xstrerror());
        return;
@@ -288,7 +288,7 @@ icmpOpen(void)
     }
     if (pid == 0) {            /* child */
        char *x = xcalloc(strlen(Config.debugOptions) + 32, 1);
-       sprintf(x, "SQUID_DEBUG=%s\n", Config.debugOptions);
+       sprintf(x, "SQUID_DEBUG=%s", Config.debugOptions);
        putenv(x);
        comm_close(icmp_sock);
        dup2(child_sock, 0);
index d7e454d2369b942f055fd33ce1ba75685efb7d70..3d0ba41f911c3791b9465eff0994ec6ddc8c9df8 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ipcache.cc,v 1.108 1997/03/04 05:16:35 wessels Exp $
+ * $Id: ipcache.cc,v 1.109 1997/04/28 04:23:15 wessels Exp $
  *
  * DEBUG: section 14    IP Cache
  * AUTHOR: Harvest Derived
 
 #include "squid.h"
 
-#define MAX_LINELEN (4096)
-
-#define IP_LOW_WATER       90
-#define IP_HIGH_WATER      95
-
 struct _ip_pending {
     int fd;
     IPH handler;
@@ -133,12 +128,13 @@ static struct {
     int errors;
     int avg_svc_time;
     int ghbn_calls;            /* # calls to blocking gethostbyname() */
+    int release_locked;
 } IpcacheStats;
 
 static int ipcache_testname _PARAMS((void));
 static int ipcache_compareLastRef _PARAMS((ipcache_entry **, ipcache_entry **));
 static int ipcache_reverseLastRef _PARAMS((ipcache_entry **, ipcache_entry **));
-static int ipcache_dnsHandleRead _PARAMS((int, dnsserver_t *));
+static void ipcache_dnsHandleRead _PARAMS((int, dnsserver_t *));
 static ipcache_entry *ipcache_parsebuffer _PARAMS((const char *buf, dnsserver_t *));
 static void ipcache_release _PARAMS((ipcache_entry *));
 static ipcache_entry *ipcache_GetFirst _PARAMS((void));
@@ -205,6 +201,8 @@ ipcacheDequeue(void)
            ipcacheQueueTailP = &ipcacheQueueHead;
        safe_free(old);
     }
+    if (i && i->status != IP_PENDING)
+       debug_trap("ipcacheDequeue: status != IP_PENDING");
     return i;
 }
 
@@ -235,12 +233,9 @@ ipcache_release(ipcache_entry * i)
     }
     if (i != (ipcache_entry *) table_entry)
        fatal_dump("ipcache_release: i != table_entry!");
-    if (i->status == IP_PENDING) {
-       debug(14, 1, "ipcache_release: Someone called on a PENDING entry\n");
-       return;
-    }
-    if (i->status == IP_DISPATCHED) {
-       debug(14, 1, "ipcache_release: Someone called on a DISPATCHED entry\n");
+    if (i->locks) {
+       i->expires = squid_curtime;
+       IpcacheStats.release_locked++;
        return;
     }
     if (hash_remove_link(ip_table, table_entry)) {
@@ -424,7 +419,6 @@ ipcacheAddHostent(ipcache_entry * i, const struct hostent *hp)
        xmemcpy(&i->addrs.in_addrs[k].s_addr,
            *(hp->h_addr_list + k),
            hp->h_length);
-    i->status = IP_CACHED;
 }
 
 static ipcache_entry *
@@ -483,7 +477,6 @@ ipcache_parsebuffer(const char *inbuf, dnsserver_t * dnsData)
     debug(14, 5, "ipcache_parsebuffer: parsing:\n%s", inbuf);
     memset(&i, '\0', sizeof(ipcache_entry));
     i.expires = squid_curtime + Config.positiveDnsTtl;
-    i.status = IP_DISPATCHED;
     for (token = strtok(buf, w_space); token; token = strtok(NULL, w_space)) {
        if (!strcmp(token, "$end")) {
            break;
@@ -523,7 +516,8 @@ ipcache_parsebuffer(const char *inbuf, dnsserver_t * dnsData)
            for (k = 0; k < ipcount; k++) {
                if ((token = strtok(NULL, w_space)) == NULL)
                    fatal_dump("Invalid IP address");
-               i.addrs.in_addrs[k].s_addr = inet_addr(token);
+               if (!safe_inet_addr(token, &i.addrs.in_addrs[k]))
+                   fatal_dump("Invalid IP address");
            }
        } else if (!strcmp(token, "$aliascount")) {
            if ((token = strtok(NULL, w_space)) == NULL)
@@ -555,7 +549,7 @@ ipcacheNudgeQueue(void)
        ipcache_dnsDispatch(dnsData, i);
 }
 
-static int
+static void
 ipcache_dnsHandleRead(int fd, dnsserver_t * dnsData)
 {
     int len;
@@ -575,7 +569,7 @@ ipcache_dnsHandleRead(int fd, dnsserver_t * dnsData)
                COMM_SELECT_READ,
                (PF) ipcache_dnsHandleRead,
                dnsData, 0);
-           return 0;
+           return;
        }
        debug(14, dnsData->flags & DNS_FLAG_CLOSING ? 5 : 1,
            "FD %d: Connection from DNSSERVER #%d is closed, disabling\n",
@@ -586,7 +580,7 @@ ipcache_dnsHandleRead(int fd, dnsserver_t * dnsData)
            NULL,
            NULL, 0);
        comm_close(fd);
-       return 0;
+       return;
     }
     n = ++IpcacheStats.replies;
     DnsStats.replies++;
@@ -607,7 +601,6 @@ ipcache_dnsHandleRead(int fd, dnsserver_t * dnsData)
        } else {
            dnsData->offset = 0;
            dnsData->ip_inbuf[0] = '\0';
-           i = dnsData->data;
            i->addrs = x->addrs;
            i->error_message = x->error_message;
            i->status = x->status;
@@ -626,7 +619,6 @@ ipcache_dnsHandleRead(int fd, dnsserver_t * dnsData)
        (PF) ipcache_dnsHandleRead,
        dnsData, 0);
     ipcacheNudgeQueue();
-    return 0;
 }
 
 static void
@@ -649,7 +641,7 @@ ipcache_nbgethostbyname(const char *name, int fd, IPH handler, void *handlerData
 {
     ipcache_entry *i = NULL;
     dnsserver_t *dnsData = NULL;
-    ipcache_addrs *addrs = NULL;
+    const ipcache_addrs *addrs = NULL;
 
     if (!handler)
        fatal_dump("ipcache_nbgethostbyname: NULL handler");
@@ -708,16 +700,10 @@ ipcache_nbgethostbyname(const char *name, int fd, IPH handler, void *handlerData
        ipcache_dnsDispatch(dnsData, i);
        return;
     }
-    if (addrs != NULL)         /* TEMPORARY */
-       debug_trap("ipcache_nbgethostbyname: Stack Trashed");
     if (NDnsServersAlloc > 0) {
        ipcacheEnqueue(i);
        return;
     }
-    if (addrs != NULL)         /* TEMPORARY */
-       debug_trap("ipcache_nbgethostbyname: Stack Trashed");
-    if (NDnsServersAlloc)
-       debug(14, 0, "WARNING: blocking on gethostbyname() for '%s'\n", name);
     ipcache_gethostbyname(name, IP_BLOCKING_LOOKUP);
     ipcache_call_pending(i);
 }
@@ -729,17 +715,18 @@ ipcache_dnsDispatch(dnsserver_t * dns, ipcache_entry * i)
     if (!BIT_TEST(dns->flags, DNS_FLAG_ALIVE))
        debug_trap("Dispatching a dead DNS server");
     if (!ipcacheHasPending(i)) {
-       debug(14, 0, "ipcache_dnsDispatch: skipping '%s' because no handler.\n",
+       debug(14, 0, "Skipping lookup of '%s' because client(s) disappeared.\n",
            i->name);
        i->status = IP_NEGATIVE_CACHED;
        ipcache_release(i);
        return;
     }
+    if (i->status != IP_PENDING)
+       debug_trap("ipcache_dnsDispatch: status != IP_PENDING");
     buf = xcalloc(1, 256);
     sprintf(buf, "%1.254s\n", i->name);
     dns->flags |= DNS_FLAG_BUSY;
     dns->data = i;
-    dns->lastcall = squid_curtime;
     i->status = IP_DISPATCHED;
     comm_write(dns->outpipe,
        buf,
@@ -850,13 +837,15 @@ ipcache_gethostbyname(const char *name, int flags)
        return addrs;
     IpcacheStats.misses++;
     if (BIT_TEST(flags, IP_BLOCKING_LOOKUP)) {
+       if (NDnsServersAlloc)
+           debug(14, 0, "WARNING: blocking on gethostbyname() for '%s'\n", name);
        IpcacheStats.ghbn_calls++;
        hp = gethostbyname(name);
        if (hp && hp->h_name && (hp->h_name[0] != '\0') && ip_table) {
            /* good address, cached */
            if (i == NULL) {
                i = ipcacheAddNew(name, hp, IP_CACHED);
-           } else if (i->status == IP_PENDING || i->status == IP_DISPATCHED) {
+           } else if (i->status == IP_DISPATCHED) {
                /* only dnsHandleRead() can change from DISPATCHED to CACHED */
                static_addrs.count = 1;
                static_addrs.cur = 0;
@@ -866,6 +855,7 @@ ipcache_gethostbyname(const char *name, int flags)
                return &static_addrs;
            } else {
                ipcacheAddHostent(i, hp);
+               i->status = IP_CACHED;
            }
            i->expires = squid_curtime + Config.positiveDnsTtl;
 #if LIBRESOLV_DNS_TTL_HACK
@@ -927,6 +917,8 @@ stat_ipcache_get(StoreEntry * sentry)
        IpcacheStats.misses);
     storeAppendPrintf(sentry, "{Blocking calls to gethostbyname(): %d}\n",
        IpcacheStats.ghbn_calls);
+    storeAppendPrintf(sentry, "{Attempts to release locked entries: %d}\n",
+       IpcacheStats.release_locked);
     storeAppendPrintf(sentry, "{dnsserver avg service time: %d msec}\n",
        IpcacheStats.avg_svc_time);
     storeAppendPrintf(sentry, "}\n\n");
@@ -1000,13 +992,13 @@ ipcacheInvalidate(const char *name)
 ipcache_addrs *
 ipcacheCheckNumeric(const char *name)
 {
-    unsigned int ip;
+    struct in_addr ip;
     /* check if it's already a IP address in text form. */
-    if ((ip = inet_addr(name)) == inaddr_none)
+    if (!safe_inet_addr(name, &ip))
        return NULL;
     static_addrs.count = 1;
     static_addrs.cur = 0;
-    static_addrs.in_addrs[0].s_addr = ip;
+    static_addrs.in_addrs[0].s_addr = ip.s_addr;
     return &static_addrs;
 }
 
@@ -1114,9 +1106,39 @@ ipcacheChangeKey(ipcache_entry * i)
        debug_trap("ipcacheChangeKey: hash_remove_link() failed\n");
        return;
     }
-    sprintf(new_key, "%d/%-128.128s", ++index, i->name);
+    sprintf(new_key, "%d/", ++index);
+    strncat(new_key, i->name, 128);
     debug(14, 1, "ipcacheChangeKey: from '%s' to '%s'\n", i->name, new_key);
     safe_free(i->name);
     i->name = xstrdup(new_key);
     ipcache_add_to_hash(i);
 }
+
+/* call during reconfigure phase to clear out all the 
+ * pending and dispatched reqeusts that got lost */
+void
+ipcache_restart(void)
+{
+    ipcache_entry *this;
+    ipcache_entry *next;
+    if (ip_table == 0)
+       fatal_dump("ipcache_restart: ip_table == 0\n");
+    while (ipcacheDequeue());
+    next = (ipcache_entry *) hash_first(ip_table);
+    while ((this = next)) {
+       next = (ipcache_entry *) hash_next(ip_table);
+       if (this->status == IP_CACHED)
+           continue;
+       if (this->status == IP_NEGATIVE_CACHED)
+           continue;
+       /* else its PENDING or DISPATCHED; there are no dnsservers
+        * running, so abort it */
+       this->status = IP_NEGATIVE_CACHED;
+       ipcache_release(this);
+    }
+    /* recalculate these while we're at it */
+    ipcache_high = (long) (((float) Config.ipcache.size *
+           (float) Config.ipcache.high) / (float) 100);
+    ipcache_low = (long) (((float) Config.ipcache.size *
+           (float) Config.ipcache.low) / (float) 100);
+}
index 9f7bf12ba7d8c61d1c356d67a6b142ccb0279b50..b6c195155ae8255bdc35e2c442c905f09044084a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: main.cc,v 1.140 1997/04/25 06:38:21 wessels Exp $
+ * $Id: main.cc,v 1.141 1997/04/28 04:23:16 wessels Exp $
  *
  * DEBUG: section 1     Startup and Main Loop
  * AUTHOR: Harvest Derived
@@ -125,6 +125,8 @@ int opt_forwarded_for = 1;
 int opt_accel_uses_host = 0;
 int vhost_mode = 0;
 int Squid_MaxFD = SQUID_MAXFD;
+int Biggest_FD = -1;
+int select_loops = 0;          /* how many times thru select loop */
 volatile int unbuffered_logs = 1;      /* debug and hierarchy unbuffered by default */
 volatile int shutdown_pending = 0;     /* set by SIGTERM handler (shut_down()) */
 volatile int reread_pending = 0;       /* set by SIGHUP handler */
@@ -137,7 +139,6 @@ struct in_addr theOutICPAddr;
 const char *const dash_str = "-";
 const char *const null_string = "";
 char ThisCache[SQUIDHOSTNAMELEN << 1];
-unsigned int inaddr_none;
 
 /* for error reporting from xmalloc and friends */
 extern void (*failure_notify) _PARAMS((const char *));
@@ -165,6 +166,7 @@ usage(void)
     fprintf(stderr,
        "Usage: %s [-hsvzCDFRUVY] [-f config-file] [-[au] port] [-k signal]\n"
        "       -a port   Specify ASCII port number (default: %d).\n"
+       "       -b        Buffer log output (default is unbuffered).\n"
        "       -f file   Use given config-file instead of\n"
        "                 %s\n"
        "       -h        Print help message.\n"
@@ -181,7 +183,7 @@ usage(void)
        "       -R        Do not set REUSEADDR on port.\n"
        "       -U        Unlink expired objects on reload.\n"
        "       -V        Virtual host httpd-accelerator.\n"
-       "       -Y        Only return UDP_HIT or UDP_MISSNOFETCH during fast reload.\n",
+       "       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
        appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
     exit(1);
 }
@@ -373,7 +375,7 @@ serverConnectionsOpen(void)
            debug(1, 1, "Accepting ICP connections on FD %d.\n",
                theInIcpConnection);
 
-           if ((addr = Config.Addrs.udp_outgoing).s_addr != inaddr_none) {
+           if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) {
                enter_suid();
                theOutIcpConnection = comm_open(SOCK_DGRAM,
                    0,
@@ -503,6 +505,8 @@ mainReinitialize(void)
     neighborsDestroy();
     parseConfigFile(ConfigFile);
     _db_init(Config.Log.log, Config.debugOptions);
+    ipcache_restart();         /* clear stuck entries */
+    fqdncache_restart();       /* sigh, fqdncache too */
     dnsOpenServers();
     redirectOpenServers();
     serverConnectionsOpen();
@@ -565,6 +569,7 @@ mainInitialize(void)
 #endif
 
     if (first_time) {
+       unlinkdInit();
        /* module initialization */
        urlInitialize();
        stat_init(&HTTPCacheInfo, Config.Log.access);
@@ -603,7 +608,6 @@ mainInitialize(void)
        if (Config.Announce.on)
            eventAdd("start_announce", start_announce, NULL, 3600);
        eventAdd("ipcache_purgelru", (EVH) ipcache_purgelru, NULL, 10);
-       eventAdd("peerUpdateFudge", peerUpdateFudge, NULL, 10);
     }
     first_time = 0;
 }
@@ -635,12 +639,11 @@ main(int argc, char **argv)
 #endif /* HAVE_MALLOPT */
 
     memset(&local_addr, '\0', sizeof(struct in_addr));
-    local_addr.s_addr = inet_addr(localhost);
+    safe_inet_addr(localhost, &local_addr);
     memset(&any_addr, '\0', sizeof(struct in_addr));
-    any_addr.s_addr = inet_addr("0.0.0.0");
+    safe_inet_addr("0.0.0.0", &any_addr);
     memset(&no_addr, '\0', sizeof(struct in_addr));
-    no_addr.s_addr = inet_addr("255.255.255.255");
-    inaddr_none = inet_addr("255.255.255.255");
+    safe_inet_addr("255.255.255.255", &no_addr);
 
 #if HAVE_SRANDOM
     srandom(time(NULL));
@@ -672,7 +675,7 @@ main(int argc, char **argv)
     comm_init();
 
     /* we have to init fdstat here. */
-    fdstat_init(PREOPEN_FD);
+    fdstat_init();
     fdstat_open(0, FD_LOG);
     fdstat_open(1, FD_LOG);
     fdstat_open(2, FD_LOG);
index 0810f24044d84ae77b7cc94ea37dd2c0fa654b93..31fa20832d0a7a95ea2045c9aa6562a6ec9c81cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: neighbors.cc,v 1.130 1997/03/29 04:45:18 wessels Exp $
+ * $Id: neighbors.cc,v 1.131 1997/04/28 04:23:17 wessels Exp $
  *
  * DEBUG: section 15    Neighbor Routines
  * AUTHOR: Harvest Derived
 
 #include "squid.h"
 
+/* count mcast group peers every 15 minutes */
+#define MCAST_COUNT_RATE 900
+
 static int peerAllowedToUse _PARAMS((const peer *, request_t *));
 static int peerHTTPOkay _PARAMS((const peer *, request_t *));
 static int peerWouldBePinged _PARAMS((const peer *, request_t *));
@@ -118,45 +121,27 @@ static void peerDNSConfigure _PARAMS((int fd, const ipcache_addrs * ia, void *da
 static void peerCheckConnect _PARAMS((void *));
 static void peerCheckConnect2 _PARAMS((int, const ipcache_addrs *, void *));
 static void peerCheckConnectDone _PARAMS((int, int, void *));
+static void peerCountMcastPeersDone _PARAMS((void *data));
+static void peerCountMcastPeersStart _PARAMS((void *data));
+static void peerCountMcastPeersSchedule _PARAMS((peer * p, time_t when));
+static void peerCountHandleIcpReply _PARAMS((peer * p, peer_t type, icp_opcode op, void *data));
 
 static icp_common_t echo_hdr;
 static u_short echo_port;
 
 static int NLateReplies = 0;
-static int NObjectsQueried = 0;
-static int MulticastFudgeFactor = 1;
 
 static struct {
     int n;
     peer *peers_head;
     peer *peers_tail;
     peer *first_ping;
+    peer *removed;
 } Peers = {
 
     0, NULL, NULL, NULL
 };
 
-const char *hier_strings[] =
-{
-    "NONE",
-    "DIRECT",
-    "SIBLING_HIT",
-    "PARENT_HIT",
-    "DEFAULT_PARENT",
-    "SINGLE_PARENT",
-    "FIRST_UP_PARENT",
-    "NO_PARENT_DIRECT",
-    "BEST_PARENT_MISS",
-    "NO_DIRECT_FAIL",
-    "SOURCE_FASTEST",
-    "SIBLING_UDP_HIT_OBJ",
-    "PARENT_UDP_HIT_OBJ",
-    "PASSTHROUGH_PARENT",
-    "SSL_PARENT_MISS",
-    "ROUNDROBIN_PARENT",
-    "INVALID CODE"
-};
-
 char *
 neighborTypeStr(const peer * e)
 {
@@ -398,7 +383,9 @@ neighborRemove(peer * target)
     }
     if (e) {
        *E = e->next;
-       peerDestroy(e);
+       e->next = Peers.removed;
+       Peers.removed = e;
+       e->stats.ack_deficit = HIER_MAX_DEFICIT;
        Peers.n--;
     }
     Peers.first_ping = Peers.peers_head;
@@ -417,6 +404,10 @@ neighborsDestroy(void)
        peerDestroy(e);
        Peers.n--;
     }
+    for (e = Peers.removed; e; e = next) {
+       next = e->next;
+       peerDestroy(e);
+    }
     memset(&Peers, '\0', sizeof(Peers));
 }
 
@@ -461,8 +452,7 @@ neighborsUdpPing(request_t * request,
     int reqnum = 0;
     int flags;
     icp_common_t *query;
-    int ICP_queries_sent = 0;
-    int ICP_mcasts_sent = 0;
+    int queries_sent = 0;
     int peers_pinged = 0;
 
     if (Peers.peers_head == NULL)
@@ -475,6 +465,9 @@ neighborsUdpPing(request_t * request,
     }
     if (entry->swap_status != NO_SWAP)
        fatal_dump("neighborsUdpPing: bad swap_status");
+    mem->w_rtt = 0;
+    mem->e_pings_closest_parent = NULL;
+    mem->p_rtt = 0;
     mem->start_ping = current_time;
     mem->icp_reply_callback = callback;
     mem->ircb_data = callback_data;
@@ -488,7 +481,7 @@ neighborsUdpPing(request_t * request,
        debug(15, 4, "neighborsUdpPing: pinging peer %s for '%s'\n",
            e->host, url);
        if (e->type == PEER_MULTICAST)
-           comm_set_mcast_ttl(theOutIcpConnection, e->mcast_ttl);
+           comm_set_mcast_ttl(theOutIcpConnection, e->mcast.ttl);
        reqnum = storeReqnum(entry, request->method);
        debug(15, 3, "neighborsUdpPing: key = '%s'\n", entry->key);
        debug(15, 3, "neighborsUdpPing: reqnum = %d\n", reqnum);
@@ -502,7 +495,6 @@ neighborsUdpPing(request_t * request,
                query,
                LOG_TAG_NONE,
                PROTO_NONE);
-           ICP_queries_sent++;
        } else {
            flags = 0;
            /* check if we should set ICP_FLAG_HIT_OBJ */
@@ -510,14 +502,17 @@ neighborsUdpPing(request_t * request,
                if (!BIT_TEST(request->flags, REQ_NOCACHE))
                    if (e->icp_version == ICP_VERSION_2)
                        flags |= ICP_FLAG_HIT_OBJ;
+           if (Config.Options.query_icmp)
+               if (e->icp_version == ICP_VERSION_2)
+                   flags |= ICP_FLAG_SRC_RTT;
            query = icpCreateMessage(ICP_OP_QUERY, flags, url, reqnum, 0);
            icpUdpSend(theOutIcpConnection,
                &e->in_addr,
                query,
                LOG_TAG_NONE,
                PROTO_NONE);
-           ICP_queries_sent++;
        }
+       queries_sent++;
 
        e->stats.ack_deficit++;
        e->stats.pings_sent++;
@@ -525,7 +520,7 @@ neighborsUdpPing(request_t * request,
            e->host, e->stats.ack_deficit);
        if (e->type == PEER_MULTICAST) {
            e->stats.ack_deficit = 0;
-           ICP_mcasts_sent++;
+           (*exprep) += e->mcast.n_replies_expected;
        } else if (neighborUp(e)) {
            /* its alive, expect a reply from it */
            (*exprep)++;
@@ -562,17 +557,16 @@ neighborsUdpPing(request_t * request,
                    query,
                    LOG_TAG_NONE,
                    PROTO_NONE);
-               ICP_queries_sent++;
            }
        } else {
            debug(15, 6, "neighborsUdpPing: Source Ping: unknown host: %s\n",
                host);
        }
     }
-    if ((ICP_queries_sent))
-       NObjectsQueried++;
-    if ((ICP_mcasts_sent))
-       *exprep += MulticastFudgeFactor;
+#if LOG_ICP_NUMBERS
+    request->hierarchy.n_sent = peers_pinged;
+    request->hierarchy.n_expect = *exprep;
+#endif
     return peers_pinged;
 }
 
@@ -609,6 +603,30 @@ neighborCountIgnored(peer * e, icp_opcode op_unused)
     NLateReplies++;
 }
 
+/* ignoreMulticastReply
+ * 
+ * We want to ignore replies from multicast peers if the
+ * cache_host_domain rules would normally prevent the peer
+ * from being used
+ */
+static int
+ignoreMulticastReply(peer * e, MemObject * mem)
+{
+    if (e == NULL)
+       return 0;
+    if (!BIT_TEST(e->options, NEIGHBOR_MCAST_RESPONDER))
+       return 0;
+    if (peerHTTPOkay(e, mem->request))
+       return 0;
+    return 1;
+}
+
+/* I should attach these records to the entry.  We take the first
+ * hit we get our wait until everyone misses.  The timeout handler
+ * call needs to nip this shopping list or call one of the misses.
+ * 
+ * If a hit process is already started, then sobeit
+ */
 void
 neighborsUdpAck(int fd, const char *url, icp_common_t * header, const struct sockaddr_in *from, StoreEntry * entry, char *data, int data_sz)
 {
@@ -655,7 +673,26 @@ neighborsUdpAck(int fd, const char *url, icp_common_t * header, const struct soc
        opcode_d, url, e ? e->host : "source");
     if (e)
        ntype = neighborType(e, mem->request);
-    if (opcode == ICP_OP_MISS) {
+    if (ignoreMulticastReply(e, mem)) {
+       neighborCountIgnored(e, opcode);
+    } else if (opcode == ICP_OP_SECHO) {
+       /* Received source-ping reply */
+       if (e) {
+           debug(15, 1, "Ignoring SECHO from neighbor %s\n", e->host);
+           neighborCountIgnored(e, opcode);
+       } else {
+           /* if we reach here, source-ping reply is the first 'parent',
+            * so fetch directly from the source */
+           debug(15, 6, "Source is the first to respond.\n");
+           hierarchyNote(entry->mem_obj->request,
+               SOURCE_FASTEST,
+               0,
+               fqdnFromAddr(from->sin_addr));
+           entry->ping_status = PING_DONE;
+           protoStart(0, entry, NULL, entry->mem_obj->request);
+           return;
+       }
+    } else if (opcode == ICP_OP_MISS) {
        if (e == NULL) {
            debug(15, 1, "Ignoring MISS from non-peer %s\n",
                inet_ntoa(from->sin_addr));
@@ -704,7 +741,7 @@ neighborsUdpAck(int fd, const char *url, icp_common_t * header, const struct soc
                neighborCountIgnored(e, opcode);
            }
        }
-    } else if (opcode == ICP_OP_MISSNOFETCH) {
+    } else if (opcode == ICP_OP_MISS_NOFETCH) {
        mem->icp_reply_callback(e, ntype, opcode, mem->ircb_data);
     } else {
        debug(15, 0, "neighborsUdpAck: Unexpected ICP reply: %s\n", opcode_d);
@@ -730,7 +767,7 @@ neighborAdd(const char *host,
     e = xcalloc(1, sizeof(peer));
     e->http_port = http_port;
     e->icp_port = icp_port;
-    e->mcast_ttl = mcast_ttl;
+    e->mcast.ttl = mcast_ttl;
     e->options = options;
     e->weight = weight;
     e->host = xstrdup(host);
@@ -883,57 +920,43 @@ peerDestroy(peer * e)
        return;
     if (!e->tcp_up)
        eventDelete(peerCheckConnect, e);
+    if (e->type == PEER_MULTICAST) {
+       if (e->mcast.flags & PEER_COUNT_EVENT_PENDING)
+           eventDelete(peerCountMcastPeersStart, e);
+       if (e->mcast.flags & PEER_COUNTING)
+           eventDelete(peerCountMcastPeersDone, e);
+    }
     for (l = e->pinglist; l; l = nl) {
        nl = l->next;
        safe_free(l->domain);
        safe_free(l);
     }
+    if (e->ip_lookup_pending)
+       ipcache_unregister(e->host, e->ipcache_fd);
     safe_free(e->host);
     safe_free(e);
 }
 
-void
-peerUpdateFudge(void *unused)
-{
-    if ((NObjectsQueried)) {
-       MulticastFudgeFactor = NLateReplies / NObjectsQueried;
-       if (NObjectsQueried > 20) {
-           /* Re-scale this so it adjusts faster */
-           NLateReplies = 20 * NLateReplies / NObjectsQueried;
-           NObjectsQueried = 20;
-       }
-    }
-    eventAdd("peerUpdateFudge", peerUpdateFudge, NULL, 10);
-    debug(15, 3, "peerUpdateFudge: Factor = %d\n", MulticastFudgeFactor);
-}
-
 static void
 peerDNSConfigure(int fd, const ipcache_addrs * ia, void *data)
 {
     peer *e = data;
     struct sockaddr_in *ap;
     int j;
+    e->ip_lookup_pending = 0;
     if (e->n_addresses == 0) {
        debug(15, 1, "Configuring %s %s/%d/%d\n", neighborTypeStr(e),
            e->host, e->http_port, e->icp_port);
        if (e->type == PEER_MULTICAST)
-           debug(15, 1, "    Multicast TTL = %d\n", e->mcast_ttl);
+           debug(15, 1, "    Multicast TTL = %d\n", e->mcast.ttl);
     }
     e->n_addresses = 0;
     if (ia == NULL) {
        debug(0, 0, "WARNING: DNS lookup for '%s' failed!\n", e->host);
-#ifdef DONT
-       debug(0, 0, "THIS NEIGHBOR WILL BE IGNORED.\n");
-       neighborRemove(e);
-#endif
        return;
     }
     if ((int) ia->count < 1) {
        debug(0, 0, "WARNING: No IP address found for '%s'!\n", e->host);
-#ifdef DONT
-       debug(0, 0, "THIS NEIGHBOR WILL BE IGNORED.\n");
-       neighborRemove(e);
-#endif
        return;
     }
     for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) {
@@ -946,6 +969,8 @@ peerDNSConfigure(int fd, const ipcache_addrs * ia, void *data)
     ap->sin_family = AF_INET;
     ap->sin_addr = e->addresses[0];
     ap->sin_port = htons(e->icp_port);
+    if (e->type == PEER_MULTICAST)
+       peerCountMcastPeersSchedule(e, 10);
 }
 
 static void
@@ -955,7 +980,10 @@ peerRefreshDNS(void *junk)
     peer *next = Peers.peers_head;
     while ((e = next)) {
        next = e->next;
-       ipcache_nbgethostbyname(e->host, 0, peerDNSConfigure, (void *) e);
+       e->ip_lookup_pending = 1;
+       /* some random, bogus FD for ipcache */
+       e->ipcache_fd = Squid_MaxFD + current_time.tv_usec;
+       ipcache_nbgethostbyname(e->host, e->ipcache_fd, peerDNSConfigure, e);
     }
     /* Reconfigure the peers every hour */
     eventAdd("peerRefreshDNS", peerRefreshDNS, NULL, 3600);
@@ -970,6 +998,8 @@ peerCheckConnect(void *data)
        0, COMM_NONBLOCKING, p->host);
     if (fd < 0)
        return;
+    p->ip_lookup_pending = 1;
+    p->ipcache_fd = fd;
     ipcache_nbgethostbyname(p->host, fd, peerCheckConnect2, p);
 }
 
@@ -977,6 +1007,7 @@ static void
 peerCheckConnect2(int fd, const ipcache_addrs * ia, void *data)
 {
     peer *p = data;
+    p->ip_lookup_pending = 0;
     commConnectStart(fd,
        p->host,
        p->http_port,
@@ -1009,3 +1040,90 @@ peerCheckConnectStart(peer * p)
     p->last_fail_time = squid_curtime;
     eventAdd("peerCheckConnect", peerCheckConnect, p, 80);
 }
+
+static void
+peerCountMcastPeersSchedule(peer * p, time_t when)
+{
+    if (p->mcast.flags & PEER_COUNT_EVENT_PENDING)
+       return;
+    eventAdd("peerCountMcastPeersStart",
+       peerCountMcastPeersStart,
+       p,
+       when);
+    p->mcast.flags |= PEER_COUNT_EVENT_PENDING;
+}
+
+static void
+peerCountMcastPeersStart(void *data)
+{
+    peer *p = data;
+    ps_state *psstate = xcalloc(1, sizeof(ps_state));
+    StoreEntry *fake;
+    MemObject *mem;
+    icp_common_t *query;
+    LOCAL_ARRAY(char, url, MAX_URL);
+    if (p->type != PEER_MULTICAST)
+       fatal_dump("peerCountMcastPeersStart: non-multicast peer");
+    p->mcast.flags &= ~PEER_COUNT_EVENT_PENDING;
+    sprintf(url, "http://%s/", inet_ntoa(p->in_addr.sin_addr));
+    fake = storeCreateEntry(url, NULL, 0, 0, METHOD_GET);
+    psstate->request = requestLink(urlParse(METHOD_GET, url));
+    psstate->entry = fake;
+    psstate->callback = NULL;
+    psstate->fail_callback = NULL;
+    psstate->callback_data = p;
+    psstate->icp.start = current_time;
+    mem = fake->mem_obj;
+    mem->start_ping = current_time;
+    mem->icp_reply_callback = peerCountHandleIcpReply;
+    mem->ircb_data = psstate;
+    comm_set_mcast_ttl(theOutIcpConnection, p->mcast.ttl);
+    p->mcast.reqnum = storeReqnum(fake, METHOD_GET);
+    query = icpCreateMessage(ICP_OP_QUERY, 0, url, p->mcast.reqnum, 0);
+    icpUdpSend(theOutIcpConnection,
+       &p->in_addr,
+       query,
+       LOG_TAG_NONE,
+       PROTO_NONE);
+    fake->ping_status = PING_WAITING;
+    eventAdd("peerCountMcastPeersDone",
+       peerCountMcastPeersDone,
+       p,
+       Config.neighborTimeout);
+    p->mcast.flags |= PEER_COUNTING;
+    peerCountMcastPeersSchedule(p, MCAST_COUNT_RATE);
+}
+
+static void
+peerCountMcastPeersDone(void *data)
+{
+    ps_state *psstate = data;
+    peer *p = psstate->callback_data;
+    StoreEntry *fake = psstate->entry;
+    double old;
+    double new;
+    double D;
+    p->mcast.flags &= ~PEER_COUNTING;
+    D = (double) ++p->mcast.n_times_counted;
+    if (D > 10.0)
+       D = 10.0;
+    old = p->mcast.avg_n_members;
+    new = (double) psstate->icp.n_recv;
+    p->mcast.avg_n_members = (old * (D - 1.0) + new) / D;
+    debug(15, 1, "Group %s: %d replies, %4.1f average\n",
+       p->host,
+       psstate->icp.n_recv,
+       p->mcast.avg_n_members);
+    p->mcast.n_replies_expected = (int) p->mcast.avg_n_members;
+    fake->store_status = STORE_ABORTED;
+    storeReleaseRequest(fake);
+    storeUnlockObject(fake);
+}
+
+static void
+peerCountHandleIcpReply(peer * p, peer_t type, icp_opcode op, void *data)
+{
+    ps_state *psstate = data;
+    psstate->icp.n_recv++;
+    debug(0, 0, "peerCountHandleIcpReply: %d replies\n", psstate->icp.n_recv);
+}
index 78e05088e45f6e0d7aa24f882bafc198f121e4b6..22c5cd1b3092f86c572c34b9c2a653b0cf18b8d5 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: net_db.cc,v 1.31 1997/02/19 17:11:07 wessels Exp $
+ * $Id: net_db.cc,v 1.32 1997/04/28 04:23:19 wessels Exp $
  *
  * DEBUG: section 37    Network Measurement Database
  * AUTHOR: Duane Wessels
@@ -45,6 +45,17 @@ static void netdbHashDelete _PARAMS((const char *key));
 static void netdbHashLink _PARAMS((netdbEntry * n, const char *hostname));
 static void netdbHashUnlink _PARAMS((const char *key));
 static void netdbPurgeLRU _PARAMS((void));
+static net_db_peer *netdbPeerByName _PARAMS((const netdbEntry * n, const char *));
+static net_db_peer *netdbPeerAdd _PARAMS((netdbEntry * n, peer * e));
+static char *netdbPeerName _PARAMS((const char *name));
+
+/* We have to keep a local list of peer names.  The Peers structure
+ * gets freed during a reconfigure.  We want this database to
+ * remain persisitent, so _net_db_peer->peername points into this
+ * linked list */
+static wordlist *peer_names = NULL;
+static wordlist **peer_names_tail = &peer_names;
+static const char *const w_space = " \t\n\r";
 
 static void
 netdbHashInsert(netdbEntry * n, struct in_addr addr)
@@ -70,7 +81,7 @@ netdbHashDelete(const char *key)
 static void
 netdbHashLink(netdbEntry * n, const char *hostname)
 {
-    struct _net_db_name *x = xcalloc(1, sizeof(struct _net_db_name));
+    net_db_name *x = xcalloc(1, sizeof(net_db_name));
     x->name = xstrdup(hostname);
     x->next = n->hosts;
     n->hosts = x;
@@ -116,8 +127,8 @@ netdbGetNext(HashID table)
 static void
 netdbRelease(netdbEntry * n)
 {
-    struct _net_db_name *x;
-    struct _net_db_name *next;
+    net_db_name *x;
+    net_db_name *next;
     for (x = n->hosts; x; x = next) {
        next = x->next;
        netdbHashUnlink(x->name);
@@ -125,6 +136,11 @@ netdbRelease(netdbEntry * n)
        safe_free(x);
     }
     n->hosts = NULL;
+    safe_free(n->peers);
+    meta_data.netdb_peers -= n->n_peers_alloc;
+    n->peers = NULL;
+    n->n_peers = 0;
+    n->n_peers_alloc = 0;
     if (n->link_count == 0) {
        netdbHashDelete(n->network);
        xfree(n);
@@ -206,7 +222,7 @@ netdbSendPing(int fdunused, const ipcache_addrs * ia, void *data)
     debug(37, 3, "netdbSendPing: pinging %s\n", hostname);
     icmpDomainPing(addr, hostname);
     n->pings_sent++;
-    n->next_ping_time = squid_curtime + Config.Netdb.ttl;
+    n->next_ping_time = squid_curtime + Config.Netdb.period;
     n->last_use_time = squid_curtime;
     xfree(hostname);
 }
@@ -216,27 +232,203 @@ networkFromInaddr(struct in_addr a)
 {
     struct in_addr b;
     b.s_addr = ntohl(a.s_addr);
+#if USE_CLASSFUL
     if (IN_CLASSC(b.s_addr))
        b.s_addr &= IN_CLASSC_NET;
     else if (IN_CLASSB(b.s_addr))
        b.s_addr &= IN_CLASSB_NET;
     else if (IN_CLASSA(b.s_addr))
        b.s_addr &= IN_CLASSA_NET;
+#else
+    /* use /24 for everything */
+    b.s_addr &= IN_CLASSC_NET;
+#endif
     b.s_addr = htonl(b.s_addr);
     return b;
 }
 
 static int
-sortByHops(netdbEntry ** n1, netdbEntry ** n2)
+sortByRtt(netdbEntry ** n1, netdbEntry ** n2)
 {
-    if ((*n1)->hops > (*n2)->hops)
+    if ((*n1)->rtt > (*n2)->rtt)
        return 1;
-    else if ((*n1)->hops < (*n2)->hops)
+    else if ((*n1)->rtt < (*n2)->rtt)
        return -1;
     else
        return 0;
 }
 
+static net_db_peer *
+netdbPeerByName(const netdbEntry * n, const char *peername)
+{
+    int i;
+    net_db_peer *p = n->peers;
+    for (i = 0; i < n->n_peers; i++, p++) {
+       if (!strcmp(p->peername, peername))
+           return p;
+    }
+    return NULL;
+}
+
+static net_db_peer *
+netdbPeerAdd(netdbEntry * n, peer * e)
+{
+    net_db_peer *p;
+    net_db_peer *o;
+    int osize;
+    int i;
+    if (n->n_peers == n->n_peers_alloc) {
+       o = n->peers;
+       osize = n->n_peers_alloc;
+       if (n->n_peers_alloc == 0)
+           n->n_peers_alloc = 2;
+       else
+           n->n_peers_alloc <<= 1;
+       debug(37, 3, "netdbPeerAdd: Growing peer list for '%s' to %d\n",
+           n->network, n->n_peers_alloc);
+       n->peers = xcalloc(n->n_peers_alloc, sizeof(net_db_peer));
+       meta_data.netdb_peers += n->n_peers_alloc;
+       for (i = 0; i < osize; i++)
+           *(n->peers + i) = *(o + i);
+       if (osize) {
+           safe_free(o);
+           meta_data.netdb_peers -= osize;
+       }
+    }
+    p = n->peers + n->n_peers;
+    p->peername = netdbPeerName(e->host);
+    n->n_peers++;
+    return p;
+}
+
+static int
+sortPeerByRtt(net_db_peer * p1, net_db_peer * p2)
+{
+    if (p1->rtt > p2->rtt)
+       return 1;
+    else if (p1->rtt < p2->rtt)
+       return -1;
+    else
+       return 0;
+}
+
+static void
+netdbSaveState(void *foo)
+{
+    LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN);
+    FILE *fp;
+    netdbEntry *n;
+    netdbEntry *next;
+    net_db_name *x;
+    struct timeval start = current_time;
+    int count = 0;
+    sprintf(path, "%s/netdb_state", swappath(0));
+    fp = fopen(path, "w");
+    if (fp == NULL) {
+       debug(50, 1, "netdbSaveState: %s: %s\n", path, xstrerror());
+       return;
+    }
+    next = (netdbEntry *) hash_first(addr_table);
+    while ((n = next)) {
+       next = (netdbEntry *) hash_next(addr_table);
+       if (n->pings_recv == 0)
+           continue;
+       fprintf(fp, "%s %d %d %10.5f %10.5f %d %d",
+           n->network,
+           n->pings_sent,
+           n->pings_recv,
+           n->hops,
+           n->rtt,
+           (int) n->next_ping_time,
+           (int) n->last_use_time);
+       for (x = n->hosts; x; x = x->next)
+           fprintf(fp, " %s", x->name);
+       fprintf(fp, "\n");
+       count++;
+    }
+    fclose(fp);
+    getCurrentTime();
+    debug(37, 0, "NETDB state saved; %d entries, %d msec\n",
+       count, tvSubMsec(start, current_time));
+    eventAdd("netdbSaveState", netdbSaveState, NULL, 3617);
+}
+
+static void
+netdbReloadState(void)
+{
+    LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN);
+    char *buf = get_free_4k_page();
+    char *t;
+    FILE *fp;
+    netdbEntry *n;
+    netdbEntry N;
+    struct in_addr addr;
+    int count = 0;
+    struct timeval start = current_time;
+    sprintf(path, "%s/netdb_state", swappath(0));
+    fp = fopen(path, "r");
+    if (fp == NULL)
+       return;
+    while (fgets(buf, 4095, fp)) {
+       memset(&N, '\0', sizeof(netdbEntry));
+       if ((t = strtok(buf, w_space)) == NULL)
+           continue;
+       if (!safe_inet_addr(t, &addr))
+           continue;
+       if ((t = strtok(NULL, w_space)) == NULL)
+           continue;
+       N.pings_sent = atoi(t);
+       if ((t = strtok(NULL, w_space)) == NULL)
+           continue;
+       N.pings_recv = atoi(t);
+       if (N.pings_recv == 0)
+           continue;
+       /* give this measurement low weight */
+       N.pings_sent = 1;
+       N.pings_recv = 1;
+       if ((t = strtok(NULL, w_space)) == NULL)
+           continue;
+       N.hops = atof(t);
+       if ((t = strtok(NULL, w_space)) == NULL)
+           continue;
+       N.rtt = atof(t);
+       if ((t = strtok(NULL, w_space)) == NULL)
+           continue;
+       N.next_ping_time = (time_t) atoi(t);
+       if ((t = strtok(NULL, w_space)) == NULL)
+           continue;
+       N.last_use_time = (time_t) atoi(t);
+       n = xcalloc(1, sizeof(netdbEntry));
+       memcpy(n, &N, sizeof(netdbEntry));
+       netdbHashInsert(n, addr);
+       while ((t = strtok(NULL, w_space)) != NULL)
+           netdbHashLink(n, t);
+       count++;
+    }
+    put_free_4k_page(buf);
+    fclose(fp);
+    getCurrentTime();
+    debug(37, 0, "NETDB state reloaded; %d entries, %d msec\n",
+       count, tvSubMsec(start, current_time));
+}
+
+static char *
+netdbPeerName(const char *name)
+{
+    wordlist *w;
+    for (w = peer_names; w; w = w->next) {
+       if (!strcmp(w->key, name))
+           return w->key;
+    }
+    w = xcalloc(1, sizeof(wordlist));
+    w->key = xstrdup(name);
+    *peer_names_tail = w;
+    peer_names_tail = &w->next;
+    return w->key;
+}
+
+
+
 #endif /* USE_ICMP */
 
 /* PUBLIC FUNCTIONS */
@@ -249,6 +441,8 @@ netdbInit(void)
        return;
     addr_table = hash_create((int (*)_PARAMS((const char *, const char *))) strcmp, 229, hash_string);
     host_table = hash_create((int (*)_PARAMS((const char *, const char *))) strcmp, 467, hash_string);
+    eventAdd("netdbSaveState", netdbSaveState, NULL, 3617);
+    netdbReloadState();
 #endif
 }
 
@@ -276,12 +470,11 @@ netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt)
     debug(37, 3, "netdbHandlePingReply: from %s\n", inet_ntoa(from->sin_addr));
     if ((n = netdbLookupAddr(from->sin_addr)) == NULL)
        return;
-    N = ++n->n;
-    if (N > 100)
-       N = 100;
+    N = ++n->pings_recv;
+    if (N > 5)
+       N = 5;
     n->hops = ((n->hops * (N - 1)) + hops) / N;
     n->rtt = ((n->rtt * (N - 1)) + rtt) / N;
-    n->pings_recv++;
     debug(37, 3, "netdbHandlePingReply: %s; rtt=%5.1f  hops=%4.1f\n",
        n->network,
        n->rtt,
@@ -297,7 +490,7 @@ netdbFreeMemory(void)
     netdbEntry **L1;
     hash_link *h;
     hash_link **L2;
-    struct _net_db_name *x;
+    net_db_name *x;
     int i = 0;
     int j;
     L1 = xcalloc(meta_data.netdb_addrs, sizeof(netdbEntry *));
@@ -313,6 +506,7 @@ netdbFreeMemory(void)
            n->hosts = x->next;
            safe_free(x);
        }
+       safe_free(n->peers);
        xfree(n);
     }
     xfree(L1);
@@ -332,6 +526,9 @@ netdbFreeMemory(void)
     xfree(L2);
     hashFreeMemory(addr_table);
     hashFreeMemory(host_table);
+    wordlistDestroy(&peer_names);
+    peer_names = NULL;
+    peer_names_tail = &peer_names;
 #endif
 }
 
@@ -354,9 +551,11 @@ netdbDump(StoreEntry * sentry)
 #if USE_ICMP
     netdbEntry *n;
     netdbEntry **list;
-    struct _net_db_name *x;
+    net_db_name *x;
     int k;
     int i;
+    int j;
+    net_db_peer *p;
     storeAppendPrintf(sentry, "{Network DB Statistics:\n");    /* } */
     storeAppendPrintf(sentry, "{%-16.16s %9s %7s %5s %s}\n",
        "Network",
@@ -374,7 +573,7 @@ netdbDump(StoreEntry * sentry)
     qsort((char *) list,
        i,
        sizeof(netdbEntry *),
-       (QS) sortByHops);
+       (QS) sortByRtt);
     for (k = 0; k < i; k++) {
        n = *(list + k);
        storeAppendPrintf(sentry, "{%-16.16s %4d/%4d %7.1f %5.1f",      /* } */
@@ -386,6 +585,13 @@ netdbDump(StoreEntry * sentry)
        for (x = n->hosts; x; x = x->next)
            storeAppendPrintf(sentry, " %s", x->name);
        storeAppendPrintf(sentry, close_bracket);
+       p = n->peers;
+       for (j = 0; j < n->n_peers; j++, p++) {
+           storeAppendPrintf(sentry, "{    %-22.22s %7.1f %5.1f}\n",
+               p->peername,
+               p->rtt,
+               p->hops);
+       }
     }
     storeAppendPrintf(sentry, close_bracket);
     xfree(list);
@@ -397,10 +603,12 @@ netdbHostHops(const char *host)
 {
 #if USE_ICMP
     netdbEntry *n = netdbLookupHost(host);
-    if (n)
+    if (n) {
+       n->last_use_time = squid_curtime;
        return (int) (n->hops + 0.5);
+    }
 #endif
-    return 0xFFFF;
+    return 0;
 }
 
 int
@@ -408,8 +616,38 @@ netdbHostRtt(const char *host)
 {
 #if USE_ICMP
     netdbEntry *n = netdbLookupHost(host);
-    if (n)
+    if (n) {
+       n->last_use_time = squid_curtime;
        return (int) (n->rtt + 0.5);
+    }
+#endif
+    return 0;
+}
+
+void
+netdbUpdatePeer(request_t * r, peer * e, int irtt, int ihops)
+{
+#if USE_ICMP
+    netdbEntry *n;
+    double rtt = (double) irtt;
+    double hops = (double) ihops;
+    net_db_peer *p;
+    debug(37, 3, "netdbUpdatePeer: '%s', %d hops, %d rtt\n", r->host, ihops, irtt);
+    n = netdbLookupHost(r->host);
+    if (n == NULL) {
+       debug(37, 3, "netdbUpdatePeer: host '%s' not found\n", r->host);
+       return;
+    }
+    if ((p = netdbPeerByName(n, e->host)) == NULL)
+       p = netdbPeerAdd(n, e);
+    p->rtt = rtt;
+    p->hops = hops;
+    p->expires = squid_curtime + 3600;
+    if (n->n_peers < 2)
+       return;
+    qsort((char *) n->peers,
+       n->n_peers,
+       sizeof(net_db_peer),
+       (QS) sortPeerByRtt);
 #endif
-    return 0xFFFF;
 }
index 8fcdbc14e7a71d232130922bbad14272a1c417c1..50d3fb908faffe58891facad6335989446eef7f8 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_select.cc,v 1.8 1997/03/29 04:45:19 wessels Exp $
+ * $Id: peer_select.cc,v 1.9 1997/04/28 04:23:21 wessels Exp $
  *
  * DEBUG: section 44    Peer Selection Algorithm
  * AUTHOR: Duane Wessels
 
 #include "squid.h"
 
+const char *hier_strings[] =
+{
+    "NONE",
+    "DIRECT",
+    "SIBLING_HIT",
+    "PARENT_HIT",
+    "DEFAULT_PARENT",
+    "SINGLE_PARENT",
+    "FIRST_UP_PARENT",
+    "NO_PARENT_DIRECT",
+    "FIRST_PARENT_MISS",
+    "CLOSEST_PARENT_MISS",
+    "CLOSEST_DIRECT",
+    "NO_DIRECT_FAIL",
+    "SOURCE_FASTEST",
+    "SIBLING_UDP_HIT_OBJ",
+    "PARENT_UDP_HIT_OBJ",
+    "PASSTHROUGH_PARENT",
+    "SSL_PARENT_MISS",
+    "ROUNDROBIN_PARENT",
+    "INVALID CODE"
+};
+
 static struct {
     int timeouts;
 } PeerStats;
@@ -68,28 +91,28 @@ peerGetSomeParent(request_t * request, hier_code * code)
     peer *p;
     if (request->method == METHOD_CONNECT)
        if ((p = Config.sslProxy)) {
-           *code = HIER_SSL_PARENT;
+           *code = SSL_PARENT;
            return p;
        }
     if (request->method != METHOD_GET)
        if ((p = Config.passProxy)) {
-           *code = HIER_PASS_PARENT;
+           *code = PASS_PARENT;
            return p;
        }
     if ((p = getDefaultParent(request))) {
-       *code = HIER_DEFAULT_PARENT;
+       *code = DEFAULT_PARENT;
        return p;
     }
     if ((p = getSingleParent(request))) {
-       *code = HIER_SINGLE_PARENT;
+       *code = SINGLE_PARENT;
        return p;
     }
     if ((p = getRoundRobinParent(request))) {
-       *code = HIER_ROUNDROBIN_PARENT;
+       *code = ROUNDROBIN_PARENT;
        return p;
     }
     if ((p = getFirstUpParent(request))) {
-       *code = HIER_FIRSTUP_PARENT;
+       *code = FIRSTUP_PARENT;
        return p;
     }
     return NULL;
@@ -196,8 +219,8 @@ peerSelectFoo(ps_state * psstate)
     }
     debug(44, 3, "peerSelect: direct = %d\n", direct);
     if (direct == DIRECT_YES) {
-       debug(44, 3, "peerSelect: HIER_DIRECT\n");
-       hierarchyNote(request, HIER_DIRECT, &psstate->icp, request->host);
+       debug(44, 3, "peerSelect: DIRECT\n");
+       hierarchyNote(request, DIRECT, &psstate->icp, request->host);
        peerSelectCallback(psstate, NULL);
        return;
     }
@@ -220,13 +243,13 @@ peerSelectFoo(ps_state * psstate)
        }
        debug_trap("peerSelect: neighborsUdpPing returned 0");
     }
-    if ((p = psstate->best_parent)) {
-       code = HIER_BEST_PARENT_MISS;
+    if ((p = psstate->first_parent_miss)) {
+       code = FIRST_PARENT_MISS;
        debug(44, 3, "peerSelect: %s/%s\n", hier_strings[code], p->host);
        hierarchyNote(request, code, &psstate->icp, p->host);
        peerSelectCallback(psstate, p);
     } else if (direct != DIRECT_NO) {
-       code = HIER_DIRECT;
+       code = DIRECT;
        debug(44, 3, "peerSelect: %s/%s\n", hier_strings[code], request->host);
        hierarchyNote(request, code, &psstate->icp, request->host);
        peerSelectCallback(psstate, NULL);
@@ -235,7 +258,7 @@ peerSelectFoo(ps_state * psstate)
        hierarchyNote(request, code, &psstate->icp, p->host);
        peerSelectCallback(psstate, p);
     } else {
-       code = HIER_NO_DIRECT_FAIL;
+       code = NO_DIRECT_FAIL;
        hierarchyNote(request, code, &psstate->icp, NULL);
        peerSelectCallbackFail(psstate);
     }
@@ -271,20 +294,20 @@ peerHandleIcpReply(peer * p, peer_t type, icp_opcode op, void *data)
        if (type == PEER_PARENT) {
            w_rtt = tvSubMsec(psstate->icp.start, current_time) / p->weight;
            if (psstate->icp.w_rtt == 0 || w_rtt < psstate->icp.w_rtt) {
-               psstate->best_parent = p;
+               psstate->first_parent_miss = p;
                psstate->icp.w_rtt = w_rtt;
            }
        }
     } else if (op == ICP_OP_HIT || op == ICP_OP_HIT_OBJ) {
        hierarchyNote(request,
-           type == PEER_PARENT ? HIER_PARENT_HIT : HIER_SIBLING_HIT,
+           type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT,
            &psstate->icp,
            p->host);
        peerSelectCallback(psstate, p);
        return;
     } else if (op == ICP_OP_SECHO) {
        hierarchyNote(request,
-           HIER_SOURCE_FASTEST,
+           SOURCE_FASTEST,
            &psstate->icp,
            request->host);
        peerSelectCallback(psstate, p);
index 409defc8c8fec366fda0c664bb3e6f62746f2f25..1184a55081a0f7434a45fb9ffbb08137f0f8222e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: pinger.cc,v 1.20 1997/03/04 05:16:39 wessels Exp $
+ * $Id: pinger.cc,v 1.21 1997/04/28 04:23:22 wessels Exp $
  *
  * DEBUG: section 42    ICMP Pinger program
  * AUTHOR: Duane Wessels
@@ -72,7 +72,8 @@ struct SquidConfig Config;
 #define ip_dst daddr
 #endif
 
-#define MAX_PAYLOAD (8192 - sizeof(struct icmphdr) - sizeof (char) - sizeof(struct timeval) - 1)
+#define MAX_PKT_SZ 8192
+#define MAX_PAYLOAD (MAX_PKT_SZ - sizeof(struct icmphdr) - sizeof (char) - sizeof(struct timeval) - 1)
 
 typedef struct {
     struct timeval tv;
@@ -143,13 +144,13 @@ pingerClose(void)
 static void
 pingerSendEcho(struct in_addr to, int opcode, char *payload, int len)
 {
-    LOCAL_ARRAY(char, pkt, 8192);
+    LOCAL_ARRAY(char, pkt, MAX_PKT_SZ);
     struct icmphdr *icmp = NULL;
     icmpEchoData *echo;
     int icmp_pktsize = sizeof(struct icmphdr);
     int x;
     struct sockaddr_in S;
-    memset(pkt, '\0', 8192);
+    memset(pkt, '\0', MAX_PKT_SZ);
     icmp = (struct icmphdr *) (void *) pkt;
     icmp->icmp_type = ICMP_ECHO;
     icmp->icmp_code = 0;
@@ -188,7 +189,7 @@ pingerRecv(void)
     int iphdrlen = 20;
     struct iphdr *ip = NULL;
     struct icmphdr *icmp = NULL;
-    LOCAL_ARRAY(char, pkt, 8192);
+    LOCAL_ARRAY(char, pkt, MAX_PKT_SZ);
     struct timeval now;
     icmpEchoData *echo;
     static pingerReplyData preply;
@@ -196,7 +197,7 @@ pingerRecv(void)
     fromlen = sizeof(from);
     n = recvfrom(icmp_sock,
        pkt,
-       8192,
+       MAX_PKT_SZ,
        0,
        (struct sockaddr *) &from,
        &fromlen);
@@ -223,7 +224,7 @@ pingerRecv(void)
     preply.opcode = echo->opcode;
     preply.hops = ipHops(ip->ip_ttl);
     preply.rtt = tvSubMsec(echo->tv, now);
-    preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - 8192);
+    preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT_SZ);
     pingerSendtoSquid(&preply);
     pingerLog(icmp, from.sin_addr, preply.rtt, preply.hops);
 }
@@ -288,11 +289,9 @@ pingerReadRequest(void)
     int guess_size;
     memset(&pecho, '\0', sizeof(pecho));
     n = recv(0, (char *) &pecho, sizeof(pecho), 0);
-    if (n < 0) {
-       perror("recv");
+    if (n < 0)
        return n;
-    }
-    guess_size = n - (sizeof(pingerEchoData) - 8192);
+    guess_size = n - (sizeof(pingerEchoData) - MAX_PKT_SZ);
     if (guess_size != pecho.psize)
        fprintf(stderr, "size mismatch, guess=%d psize=%d\n",
            guess_size, pecho.psize);
@@ -306,7 +305,7 @@ pingerReadRequest(void)
 static void
 pingerSendtoSquid(pingerReplyData * preply)
 {
-    int len = sizeof(pingerReplyData) - 8192 + preply->psize;
+    int len = sizeof(pingerReplyData) - MAX_PKT_SZ + preply->psize;
     if (send(1, (char *) preply, len, 0) < 0) {
        debug(50, 0, "pinger: send: %s\n", xstrerror());
        exit(1);
@@ -352,8 +351,10 @@ main(int argc, char *argv[])
        if (x < 0)
            return 1;
        if (FD_ISSET(0, &R))
-           if (pingerReadRequest() < 0)
+           if (pingerReadRequest() < 0) {
+               debug(42, 0, "Pinger exiting.\n");
                return 1;
+           }
        if (FD_ISSET(icmp_sock, &R))
            pingerRecv();
        if (10 + last_check_time < squid_curtime) {
index 20d50d63c73ea099a0ee8648a4d789cb421e08dc..7adbf9cc4f1778a61602355ed15f75076bd42d25 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: redirect.cc,v 1.34 1997/01/31 23:38:38 wessels Exp $
+ * $Id: redirect.cc,v 1.35 1997/04/28 04:23:24 wessels Exp $
  *
  * DEBUG: section 29    Redirector
  * AUTHOR: Duane Wessels
@@ -135,7 +135,7 @@ redirectCreateRedirector(const char *command)
        }
        comm_set_fd_lifetime(sfd, -1);
        debug(29, 4, "redirect_create_redirector: FD %d connected to %s #%d.\n",
-           sfd, command, n_redirector++);
+           sfd, command, ++n_redirector);
        slp.tv_sec = 0;
        slp.tv_usec = 250000;
        select(0, NULL, NULL, NULL, &slp);
@@ -211,6 +211,9 @@ redirectHandleRead(int fd, redirector_t * redirector)
        } else {
            debug(29, 5, "redirectHandleRead: reply: '%s'\n",
                redirector->inbuf);
+           /* careful here.  r->data might point to something which
+            * has recently been freed.  If so, we require that r->handler
+            * be NULL */
            if (r->handler) {
                r->handler(r->data,
                    t == redirector->inbuf ? NULL : redirector->inbuf);
@@ -323,6 +326,7 @@ redirectStart(int cfd, icpStateData * icpState, RH handler, void *data)
 {
     redirectStateData *r = NULL;
     redirector_t *redirector = NULL;
+    debug(29, 5, "redirectStart: '%s'\n", icpState->url);
     if (!handler)
        fatal_dump("redirectStart: NULL handler");
     if (!icpState)
index 849c34a76a977a160013b5a9fbc4c040f1e370e3..03f14aa559a818c0b59239504781850f1ff79e7a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: squid.h,v 1.103 1997/04/02 05:22:14 wessels Exp $
+ * $Id: squid.h,v 1.104 1997/04/28 04:23:27 wessels Exp $
  *
  * AUTHOR: Duane Wessels
  *
@@ -271,7 +271,6 @@ typedef int (*QS) (const void *, const void *);
 #include "cache_cf.h"
 #include "comm.h"
 #include "debug.h"
-#include "disk.h"
 #include "fdstat.h"
 #include "hash.h"
 #include "proto.h"             /* must go before neighbors.h */
@@ -305,6 +304,8 @@ typedef int (*QS) (const void *, const void *);
 #include "client_db.h"
 #include "objcache.h"
 #include "refresh.h"
+#include "unlinkd.h"
+#include "disk.h"
 
 #if !HAVE_TEMPNAM
 #include "tempnam.h"
@@ -331,12 +332,13 @@ extern int opt_catch_signals;     /* main.c */
 extern int opt_no_ipcache;     /* main.c */
 extern int vhost_mode;         /* main.c */
 extern int Squid_MaxFD;                /* main.c */
+extern int Biggest_FD;         /* main.c */
+extern int select_loops;       /* main.c */
 extern const char *const version_string;       /* main.c */
 extern const char *const appname;      /* main.c */
 extern struct in_addr local_addr;      /* main.c */
 extern struct in_addr theOutICPAddr;   /* main.c */
 extern const char *const localhost;
-extern unsigned int inaddr_none;
 extern struct in_addr no_addr; /* comm.c */
 extern int opt_udp_hit_obj;    /* main.c */
 extern int opt_mem_pools;      /* main.c */
@@ -344,7 +346,7 @@ extern int opt_forwarded_for;       /* main.c */
 extern int opt_accel_uses_host;        /* main.c */
 extern char ThisCache[];       /* main.c */
 
-/* Prototypes and definitions which don't really deserve a seaprate
+/* Prototypes and definitions which don't really deserve a separate
  * include file */
 
 #define  CONNECT_PORT        443
index 8e10064078de64fc33895250053211a5dfcfcaf1..d66f08910a4bb0af1377b8850014b8b6d3cc3249 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ssl.cc,v 1.43 1997/03/29 04:45:20 wessels Exp $
+ * $Id: ssl.cc,v 1.44 1997/04/28 04:23:27 wessels Exp $
  *
  * DEBUG: section 26    Secure Sockets Layer Proxy
  * AUTHOR: Duane Wessels
@@ -46,6 +46,7 @@ typedef struct {
     time_t timeout;
     int *size_ptr;             /* pointer to size in an icpStateData for logging */
     int proxying;
+    int ip_lookup_pending;
 } SslStateData;
 
 static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
@@ -118,6 +119,8 @@ sslStateFree(int fd, void *data)
     safe_free(sslState->client.buf);
     xfree(sslState->url);
     requestUnlink(sslState->request);
+    if (sslState->ip_lookup_pending)
+       ipcache_unregister(sslState->host, sslState->server.fd);
     safe_free(sslState);
 }
 
@@ -337,6 +340,7 @@ sslConnect(int fd, const ipcache_addrs * ia, void *data)
     SslStateData *sslState = data;
     request_t *request = sslState->request;
     char *buf = NULL;
+    sslState->ip_lookup_pending = 0;
     if (ia == NULL) {
        debug(26, 4, "sslConnect: Unknown host: %s\n", sslState->host);
        buf = squid_error_url(sslState->url,
@@ -500,6 +504,7 @@ sslPeerSelectComplete(peer * p, void *data)
     } else {
        sslState->port = CACHE_HTTP_PORT;
     }
+    sslState->ip_lookup_pending = 1;
     ipcache_nbgethostbyname(sslState->host,
        sslState->server.fd,
        sslConnect,
index d8130bc277fcce02ed020023c77f8b847eaf934b..a654a5e506f9e8a5697394d25b2b294b23f29827 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: stat.cc,v 1.132 1997/04/25 21:43:58 wessels Exp $
+ * $Id: stat.cc,v 1.133 1997/04/28 04:23:28 wessels Exp $
  *
  * DEBUG: section 18    Cache Manager Statistics
  * AUTHOR: Harvest Derived
@@ -127,7 +127,8 @@ struct _iostats IOStats;
 const char *const open_bracket = "{\n";
 const char *const close_bracket = "}\n";
 
-extern char *diskFileName _PARAMS((int));
+extern int unlinkd_count;
+extern int fileno_stack_count;
 
 /* LOCALS */
 static const char *describeStatuses _PARAMS((const StoreEntry *));
@@ -326,8 +327,10 @@ describeFlags(const StoreEntry * entry)
     int flags = (int) entry->flag;
     char *t;
     buf[0] = '\0';
+#ifdef OLD_CODE
     if (BIT_TEST(flags, IP_LOOKUP_PENDING))
        strcat(buf, "IP,");
+#endif
     if (BIT_TEST(flags, DELETE_BEHIND))
        strcat(buf, "DB,");
     if (BIT_TEST(flags, CLIENT_ABORT_REQUEST))
@@ -633,6 +636,7 @@ statFiledescriptors(StoreEntry * sentry)
     char *s = NULL;
     int lft;
     int to;
+    FD_ENTRY *f;
 
     storeAppendPrintf(sentry, open_bracket);
     storeAppendPrintf(sentry, "{Active file descriptors:}\n");
@@ -645,6 +649,7 @@ statFiledescriptors(StoreEntry * sentry)
        "Description");
     storeAppendPrintf(sentry, "{---- ------ ---- ---- --------------------- ------------------------------}\n");
     for (i = 0; i < Squid_MaxFD; i++) {
+       f = &fd_table[i];
        if (!fdstat_isopen(i))
            continue;
        j = fdstatGetType(i);
@@ -653,9 +658,9 @@ statFiledescriptors(StoreEntry * sentry)
            fdstatTypeStr[j]);
        switch (j) {
        case FD_SOCKET:
-           if ((lft = comm_get_fd_lifetime(i)) < 0)
+           if ((lft = f->lifetime) < 0)
                lft = 0;
-           to = comm_get_fd_timeout(i);
+           to = f->timeout_time;
            if (lft > 0)
                lft = (lft - squid_curtime) / 60;
            if (to > 0)
@@ -703,6 +708,7 @@ memoryAccounted(void)
        meta_data.url_strings +
        meta_data.netdb_addrs * sizeof(netdbEntry) +
        meta_data.netdb_hosts * sizeof(struct _net_db_name) +
+                 meta_data.netdb_peers * sizeof(struct _net_db_peer) +
                  meta_data.client_info * client_info_sz +
                  meta_data.misc;
 }
@@ -752,9 +758,12 @@ info_get(const cacheinfo * obj, StoreEntry * sentry)
     storeAppendPrintf(sentry, "{\tNumber of UDP connections:\t%lu}\n",
        nudpconn);
 
+
     f = (float) (squid_curtime - squid_starttime);
     storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n",
        f == 0.0 ? 0.0 : ((ntcpconn + nudpconn) / (f / 3600.0)));
+    storeAppendPrintf(sentry, "{\tSelect loop called: %d times, %0.3f ms avg}\n",
+       select_loops, 1000.0 * f / select_loops);
 
     storeAppendPrintf(sentry, "{Cache information for %s:}\n",
        appname);
@@ -764,6 +773,10 @@ info_get(const cacheinfo * obj, StoreEntry * sentry)
        store_mem_size >> 10);
     storeAppendPrintf(sentry, "{\tStorage LRU Expiration Age:\t%6.2f days}\n",
        (double) storeExpiredReferenceAge() / 86400.0);
+    storeAppendPrintf(sentry, "{\tRequests given to unlinkd:\t%d}\n",
+       unlinkd_count);
+    storeAppendPrintf(sentry, "{\tUnused fileno stack count:\t%d}\n",
+       fileno_stack_count);
 
 #if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
     storeAppendPrintf(sentry, "{Resource usage for %s:}\n", appname);
@@ -833,7 +846,7 @@ info_get(const cacheinfo * obj, StoreEntry * sentry)
     storeAppendPrintf(sentry, "{\tMax number of file desc available:    %4d}\n",
        Squid_MaxFD);
     storeAppendPrintf(sentry, "{\tLargest file desc currently in use:   %4d}\n",
-       fdstat_biggest_fd());
+       Biggest_FD);
     storeAppendPrintf(sentry, "{\tAvailable number of file descriptors: %4d}\n",
        fdstat_are_n_free_fd(0));
     storeAppendPrintf(sentry, "{\tReserved number of file descriptors:  %4d}\n",
@@ -918,6 +931,12 @@ info_get(const cacheinfo * obj, StoreEntry * sentry)
        (int) sizeof(struct _net_db_name),
                     (int) (meta_data.netdb_hosts * sizeof(struct _net_db_name) >> 10));
 
+    storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
+       "NetDB Peer Entries",
+       meta_data.netdb_peers,
+       (int) sizeof(struct _net_db_peer),
+                    (int) (meta_data.netdb_peers * sizeof(struct _net_db_peer) >> 10));
+
     storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
        "ClientDB Entries",
        meta_data.client_info,
@@ -1080,10 +1099,13 @@ log_append(const cacheinfo * obj,
     const char *client = NULL;
     hier_code hier_code = HIER_NONE;
     const char *hier_host = dash_str;
+    int hier_timeout = 0;
+#ifdef LOG_ICP_NUMBERS
     int ns = 0;
     int ne = 0;
     int nr = 0;
     int tt = 0;
+#endif
 
     if (obj->logfile_status != LOG_ENABLE)
        return;
@@ -1106,11 +1128,13 @@ log_append(const cacheinfo * obj,
     if (hierData) {
        hier_code = hierData->code;
        hier_host = hierData->host ? hierData->host : dash_str;
-       if (hierData->icp.start.tv_sec && hierData->icp.stop.tv_sec)
-           tt = tvSubMsec(hierData->icp.start, hierData->icp.stop);
-       ns = hierData->icp.n_sent;
-       ne = hierData->icp.n_replies_expected;
-       nr = hierData->icp.n_recv;
+       hier_timeout = hierData->timeout;
+#ifdef LOG_ICP_NUMBERS
+       tt = hierData->delay;
+       ns = hierData->n_sent;
+       ne = hierData->n_expect;
+       nr = hierData->n_recv;
+#endif
     }
     if (Config.commonLogFormat)
        sprintf(tmp, "%s %s - [%s] \"%s %s\" %s:%s %d\n",
@@ -1123,7 +1147,11 @@ log_append(const cacheinfo * obj,
            hier_strings[hier_code],
            size);
     else
-       sprintf(tmp, "%9d.%03d %6d %s %s/%03d %d %s %s %s %s/%s %d/%d/%d/%d %s\n",
+#ifdef LOG_ICP_NUMBERS
+       sprintf(tmp, "%9d.%03d %6d %s %s/%03d %d %s %s %s %s%s/%s/%d/%d/%d/%d %s\n",
+#else
+       sprintf(tmp, "%9d.%03d %6d %s %s/%03d %d %s %s %s %s%s/%s %s\n",
+#endif
            (int) current_time.tv_sec,
            (int) current_time.tv_usec / 1000,
            msec,
@@ -1134,9 +1162,12 @@ log_append(const cacheinfo * obj,
            method,
            url,
            ident,
+           hier_timeout ? "TIMEOUT_" : "",
            hier_strings[hier_code],
            hier_host,
+#ifdef LOG_ICP_NUMBERS
            ns, ne, nr, tt,
+#endif
            content_type);
 #if LOG_FULL_HEADERS
     if (Config.logMimeHdrs) {
index 98a1510ed5cc2284cfe13bb36b4ffacb774a16ae..c9d839bf5e9ab9d095399bd207c6dc313d61b809 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store.cc,v 1.221 1997/04/25 22:01:18 wessels Exp $
+ * $Id: store.cc,v 1.222 1997/04/28 04:23:30 wessels Exp $
  *
  * DEBUG: section 20    Storeage Manager
  * AUTHOR: Harvest Derived
@@ -251,9 +251,8 @@ static const char *storeDescribeStatus _PARAMS((const StoreEntry *));
 static HashID storeCreateHashTable _PARAMS((int (*)_PARAMS((const char *, const char *))));
 static int compareLastRef _PARAMS((StoreEntry **, StoreEntry **));
 static int compareSize _PARAMS((StoreEntry **, StoreEntry **));
-static int compareBucketOrder _PARAMS((struct _bucketOrder *,
-       struct _bucketOrder *));
-static int storeCheckExpired _PARAMS((const StoreEntry *));
+static int compareBucketOrder _PARAMS((struct _bucketOrder *, struct _bucketOrder *));
+static int storeCheckExpired _PARAMS((const StoreEntry *, int flag));
 static int storeCheckPurgeMem _PARAMS((const StoreEntry *));
 static int storeClientListSearch _PARAMS((const MemObject *, int));
 static int storeCopy _PARAMS((const StoreEntry *, int, int, char *, int *));
@@ -304,6 +303,8 @@ static void storeValidate _PARAMS((StoreEntry *, void (*)(), void *));
 static void storeValidateComplete _PARAMS((void *data, int, int));
 static void storeRebuiltFromDisk _PARAMS((struct storeRebuildState * data));
 static unsigned int getKeyCounter _PARAMS((void));
+static void storePutUnusedFileno _PARAMS((int fileno));
+static int storeGetUnusedFileno _PARAMS((void));
 
 /* Now, this table is inaccessible to outsider. They have to use a method
  * to access a value in internal storage data structure. */
@@ -621,10 +622,14 @@ storeUnlockObject(StoreEntry * e)
     if (e->lock_count)
        return (int) e->lock_count;
     if (e->store_status == STORE_PENDING) {
+#ifdef COMPLAIN
        debug_trap("storeUnlockObject: Someone unlocked STORE_PENDING object");
        debug(20, 1, "   --> Key '%s'\n", e->key);
+#endif
        e->store_status = STORE_ABORTED;
     }
+    if (storePendingNClients(e) > 0)
+       debug_trap("storeUnlockObject: unlocked entry with pending clients\n");
     if (BIT_TEST(e->flag, RELEASE_REQUEST)) {
        storeRelease(e);
     } else if (BIT_TEST(e->flag, ABORT_MSG_PENDING)) {
@@ -1231,7 +1236,7 @@ storeSwapOutHandle(int fd, int flag, StoreEntry * e)
        file_close(fd);
        if (e->swap_file_number != -1) {
            storeDirMapBitReset(e->swap_file_number);
-           safeunlink(storeSwapFullPath(e->swap_file_number, NULL), 0);
+           storePutUnusedFileno(e->swap_file_number);
            e->swap_file_number = -1;
        }
        storeRelease(e);
@@ -1303,7 +1308,8 @@ storeSwapOutStart(StoreEntry * e)
 {
     swapout_ctrl_t *ctrlp;
     LOCAL_ARRAY(char, swapfilename, SQUID_MAXPATHLEN);
-    swapfileno = storeDirMapAllocate();
+    if ((swapfileno = storeGetUnusedFileno()) < 0)
+       swapfileno = storeDirMapAllocate();
     storeSwapFullPath(swapfileno, swapfilename);
     ctrlp = xmalloc(sizeof(swapout_ctrl_t));
     ctrlp->swapfilename = xstrdup(swapfilename);
@@ -1383,6 +1389,7 @@ static void
 storeDoRebuildFromDisk(void *data)
 {
     struct storeRebuildState *RB = data;
+    LOCAL_ARRAY(char, swapfile, MAXPATHLEN);
     LOCAL_ARRAY(char, url, MAX_URL);
     StoreEntry *e = NULL;
     time_t expires;
@@ -1398,6 +1405,9 @@ storeDoRebuildFromDisk(void *data)
     int x;
     struct _rebuild_dir *d;
     struct _rebuild_dir **D;
+    int used;                  /* is swapfile already in use? */
+    int newer;                 /* is the log entry newer than current entry? */
+
     /* load a number of objects per invocation */
     if ((d = RB->rebuild_dir) == NULL) {
        storeRebuiltFromDisk(RB);
@@ -1436,8 +1446,13 @@ storeDoRebuildFromDisk(void *data)
            &scan3,             /* last modified */
            &scan4,             /* size */
            url);               /* url */
-       if (x != 6)
+       if (x < 1)
            continue;
+       storeSwapFullPath(sfileno, swapfile);
+       if (x != 6) {
+           storePutUnusedFileno(sfileno);
+           continue;
+       }
        if (sfileno < 0)
            continue;
        sfileno = storeDirProperFileno(d->dirn, sfileno);
@@ -1458,16 +1473,51 @@ storeDoRebuildFromDisk(void *data)
            RB->objcount--;
            RB->dupcount++;
        }
-       /* Is the swap file number already taken? */
-       if (storeDirMapBitTest(sfileno)) {
-           /* Yes it is, we can't use this swapfile */
-           debug(20, 2, "storeRebuildFromDisk: Line %d Active clash: file #%d\n",
-               RB->linecount,
+       e = storeGet(url);
+       used = storeDirMapBitTest(sfileno);
+       /* If this URL already exists in the cache, does the swap log
+        * appear to have a newer entry?  Compare 'timestamp' from the
+        * swap log to e->lastref.  Note, we can't compare e->timestamp
+        * because it is the Date: header from the HTTP reply and
+        * doesn't really tell us when the object was added to the
+        * cache. */
+       newer = e ? (timestamp > e->lastref ? 1 : 0) : 0;
+       if (used && !newer) {
+           /* log entry is old, ignore it */
+           RB->clashcount++;
+           continue;
+       } else if (used && e && e->swap_file_number == sfileno) {
+           /* swapfile taken, same URL, newer, update meta */
+           e->lastref = timestamp;
+           e->timestamp = timestamp;
+           e->expires = expires;
+           e->lastmod = lastmod;
+           continue;
+       } else if (used) {
+           /* swapfile in use, not by this URL, log entry is newer */
+           /* This is sorta bad: the log entry should NOT be newer at this
+            * point.  If the log is dirty, the filesize check should have
+            * caught this.  If the log is clean, there should never be a
+            * newer entry. */
+           debug(20, 1, "WARNING: newer swaplog entry for fileno %08X\n",
                sfileno);
-           debug(20, 3, "storeRebuildFromDisk: --> '%s'\n", url);
-           /* don't unlink the file!  just skip this log entry */
+           /* I'm tempted to remove the swapfile here just to be safe,
+            * but there is a bad race condition in the NOVM version if
+            * the swapfile has recently been opened for writing, but
+            * not yet opened for reading.  Because we can't map
+            * swapfiles back to StoreEntrys, we don't know the state
+            * of the entry using that file.  */
            RB->clashcount++;
            continue;
+       } else if (e) {
+           /* URL already exists, this swapfile not being used */
+           /* junk old, load new */
+           storeRelease(e);    /* release old entry */
+           RB->dupcount++;
+       } else {
+           /* URL doesnt exist, swapfile not in use */
+           /* load new */
+           (void) 0;
        }
        /* update store_swap_size */
        storeDirUpdateSwapSize(sfileno, size, 1);
@@ -1821,7 +1871,7 @@ storePurgeOld(void *unused)
        }
        if ((n & 0xFFF) == 0)
            debug(20, 2, "storeWalkThrough: %7d objects so far.\n", n);
-       if (storeCheckExpired(e))
+       if (storeCheckExpired(e, 1))
            count += storeRelease(e);
     }
     debug(20, 0, "storePurgeOld: Removed %d objects\n", count);
@@ -1860,7 +1910,7 @@ storeGetMemSpace(int size)
            break;
        if (storeEntryLocked(e))
            continue;
-       if (storeCheckExpired(e)) {
+       if (storeCheckExpired(e, 0)) {
            debug(20, 2, "storeGetMemSpace: Expired: %s\n", e->url);
            n_expired++;
            storeRelease(e);
@@ -1973,7 +2023,6 @@ storeGetSwapSpace(int size)
     StoreEntry *e = NULL;
     int scanned = 0;
     int removed = 0;
-    int expired = 0;
     int locked = 0;
     int locked_size = 0;
     int list_count = 0;
@@ -2000,12 +2049,10 @@ storeGetSwapSpace(int size)
     LRU_list = xcalloc(max_list_count, sizeof(StoreEntry *));
     /* remove expired objects until recover enough or no expired objects */
     for (i = 0; i < store_buckets; i++) {
-       int expired_in_one_bucket = 0;
        link_ptr = hash_get_bucket(store_table, storeGetBucketNum());
        if (link_ptr == NULL)
            continue;
-       /* this while loop handles one bucket of hash table */
-       expired_in_one_bucket = 0;
+       /* this for loop handles one bucket of hash table */
        for (; link_ptr; link_ptr = next) {
            if (list_count == max_list_count)
                break;
@@ -2014,9 +2061,9 @@ storeGetSwapSpace(int size)
            e = (StoreEntry *) link_ptr;
            if (!BIT_TEST(e->flag, ENTRY_VALIDATED))
                continue;
-           if (storeCheckExpired(e)) {
+           if (storeCheckExpired(e, 0)) {
                debug(20, 3, "storeGetSwapSpace: Expired '%s'\n", e->url);
-               expired_in_one_bucket += storeRelease(e);
+               storeRelease(e);
            } else if (!storeEntryLocked(e)) {
                *(LRU_list + list_count) = e;
                list_count++;
@@ -2025,18 +2072,7 @@ storeGetSwapSpace(int size)
                locked++;
                locked_size += e->mem_obj->e_current_len;
            }
-       }                       /* while, end of one bucket of hash table */
-       expired += expired_in_one_bucket;
-       if (expired_in_one_bucket &&
-           ((!fReduceSwap && (store_swap_size + kb_size <= store_swap_high)) ||
-               (fReduceSwap && (store_swap_size + kb_size <= store_swap_low)))
-           ) {
-           fReduceSwap = 0;
-           safe_free(LRU_list);
-           debug(20, 2, "storeGetSwapSpace: Finished, %d objects expired.\n",
-               expired);
-           return 0;
-       }
+       }                       /* for, end of one bucket of hash table */
        qsort((char *) LRU_list,
            list_count,
            sizeof(StoreEntry *),
@@ -2158,7 +2194,7 @@ storeRelease(StoreEntry * e)
        debug(20, 5, "storeRelease: Release anonymous object\n");
 
     if (e->swap_status == SWAP_OK && (e->swap_file_number > -1)) {
-       (void) safeunlink(storeSwapFullPath(e->swap_file_number, NULL), 1);
+       storePutUnusedFileno(e->swap_file_number);
        storeDirUpdateSwapSize(e->swap_file_number, e->object_len, -1);
        storeDirMapBitReset(e->swap_file_number);
        e->swap_file_number = -1;
@@ -2187,33 +2223,25 @@ storeEntryLocked(const StoreEntry * e)
     return 0;
 }
 
-/*  use this for internal call only */
 static int
 storeCopy(const StoreEntry * e, int stateoffset, int maxSize, char *buf, int *size)
 {
-    int available_to_write = 0;
-
-    available_to_write = e->mem_obj->e_current_len - stateoffset;
-
-    if (stateoffset < e->mem_obj->e_lowest_offset) {
-       /* this should not happen. Logic race !!! */
-       debug(20, 1, "storeCopy: Client Request a chunk of data in area lower than the lowest_offset\n");
-       debug(20, 1, "           Current Lowest offset : %d\n", e->mem_obj->e_lowest_offset);
-       debug(20, 1, "           Requested offset      : %d\n", stateoffset);
-       /* can't really do anything here. Client may hang until lifetime runout. */
-       return 0;
+    int available;
+    MemObject *mem = e->mem_obj;
+    int s;
+    if (stateoffset < mem->e_lowest_offset) {
+       debug_trap("storeCopy: requested offset < e_lowest_offset");
+       return *size = 0;
     }
-    *size = (available_to_write >= maxSize) ?
-       maxSize : available_to_write;
-
-    debug(20, 6, "storeCopy: avail_to_write=%d, store_offset=%d\n",
-       *size, stateoffset);
-
-    if (*size > 0)
-       if (e->mem_obj->data->mem_copy(e->mem_obj->data, stateoffset, buf, *size) < 0)
-           return -1;
-
-    return *size;
+    s = available = mem->e_current_len - stateoffset;
+    if (s < 0)
+       fatal_dump("storeCopy: offset > e_current_len");
+    if (s > maxSize)
+       s = maxSize;
+    debug(20, 6, "storeCopy: copying %d bytes at offset %d\n", s, stateoffset);
+    if (s > 0)
+       (void) mem->data->mem_copy(mem->data, stateoffset, buf, s);
+    return *size = s;
 }
 
 /* check if there is any client waiting for this object at all */
@@ -2264,6 +2292,8 @@ storeClientListAdd(StoreEntry * e, int fd, int last_offset)
            mem->clients[i].fd = -1;
     }
     for (i = 0; i < mem->nclients; i++) {
+       if (mem->clients[i].fd == fd)
+           return i;           /* its already here */
        if (mem->clients[i].fd == -1)
            break;
     }
@@ -2520,7 +2550,7 @@ storeMaintainSwapSpace(void *unused)
                scan_obj++;
                next = link_ptr->next;
                e = (StoreEntry *) link_ptr;
-               if (!storeCheckExpired(e))
+               if (!storeCheckExpired(e, 1))
                    continue;
                rm_obj += storeRelease(e);
            }
@@ -2742,14 +2772,16 @@ storeCheckPurgeMem(const StoreEntry * e)
 }
 
 static int
-storeCheckExpired(const StoreEntry * e)
+storeCheckExpired(const StoreEntry * e, int check_lru_age)
 {
-    time_t max_age = storeExpiredReferenceAge();
+    time_t max_age;
     if (storeEntryLocked(e))
        return 0;
     if (BIT_TEST(e->flag, ENTRY_NEGCACHED) && squid_curtime >= e->expires)
        return 1;
-    if (max_age <= 0)
+    if (!check_lru_age)
+       return 0;
+    if ((max_age = storeExpiredReferenceAge()) <= 0)
        return 0;
     if (squid_curtime - e->lastref > max_age)
        return 1;
@@ -2759,12 +2791,13 @@ storeCheckExpired(const StoreEntry * e)
 /* 
  * storeExpiredReferenceAge
  *
- * The LRU age is scaled exponentially between 1 minute and 1 year, when
- * store_swap_low < store_swap_size < store_swap_high.  This keeps
- * store_swap_size within the low and high water marks.  If the cache is
- * very busy then store_swap_size stays closer to the low water mark, if
- * it is not busy, then it will stay near the high water mark.  The LRU
- * age value can be examined on the cachemgr 'info' page.
+ * The LRU age is scaled exponentially between 1 minute and
+ * Config.referenceAge , when store_swap_low < store_swap_size <
+ * store_swap_high.  This keeps store_swap_size within the low and high
+ * water marks.  If the cache is very busy then store_swap_size stays
+ * closer to the low water mark, if it is not busy, then it will stay
+ * near the high water mark.  The LRU age value can be examined on the
+ * cachemgr 'info' page.
  */
 time_t
 storeExpiredReferenceAge(void)
@@ -2772,11 +2805,11 @@ storeExpiredReferenceAge(void)
     double x;
     double z;
     time_t age;
-    if (Config.referenceAge != 0)
-       return Config.referenceAge;
-    x = 2.0 * (store_swap_high - store_swap_size) / (store_swap_high - store_swap_low);
-    x = x < 0.0 ? 0.0 : x > 2.0 ? 2.0 : x;
-    z = pow(724.0, x);         /* minutes [1:525600] */
+    if (Config.referenceAge == 0)
+       return 0;
+    x = (double) (store_swap_high - store_swap_size) / (store_swap_high - store_swap_low);
+    x = x < 0.0 ? 0.0 : x > 1.0 ? 1.0 : x;
+    z = pow((double) Config.referenceAge, x);
     age = (time_t) (z * 60.0);
     if (age < 60)
        age = 60;
@@ -2883,3 +2916,24 @@ storeTimestampsSet(StoreEntry * entry)
        entry->lastmod = served_date;
     entry->timestamp = served_date;
 }
+
+#define FILENO_STACK_SIZE 128
+static int fileno_stack[FILENO_STACK_SIZE];
+int fileno_stack_count = 0;
+
+static int
+storeGetUnusedFileno(void)
+{
+    if (fileno_stack_count < 1)
+       return -1;
+    return fileno_stack[--fileno_stack_count];
+}
+
+static void
+storePutUnusedFileno(int fileno)
+{
+    if (fileno_stack_count < FILENO_STACK_SIZE)
+       fileno_stack[fileno_stack_count++] = fileno;
+    else
+       unlinkdUnlink(storeSwapFullPath(fileno, NULL));
+}
index beac4d5a0627c438b35036681bc7b0d1b664fd21..f12a98af87989b514b5ece9f57dfd168b74187c6 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: tools.cc,v 1.98 1997/04/25 06:38:25 wessels Exp $
+ * $Id: tools.cc,v 1.99 1997/04/28 04:23:32 wessels Exp $
  *
  * DEBUG: section 21    Misc Functions
  * AUTHOR: Harvest Derived
@@ -132,6 +132,18 @@ int getpagesize _PARAMS((void));
 int gethostname _PARAMS((char *, int));
 #endif
 
+static void
+releaseServerSockets(void)
+{
+    /* Release the main ports as early as possible */
+    if (theHttpConnection >= 0)
+       (void) close(theHttpConnection);
+    if (theInIcpConnection >= 0)
+       (void) close(theInIcpConnection);
+    if (theOutIcpConnection >= 0 && theOutIcpConnection != theInIcpConnection)
+       (void) close(theOutIcpConnection);
+}
+
 static char *
 dead_msg(void)
 {
@@ -272,11 +284,7 @@ death(int sig)
     signal(SIGBUS, SIG_DFL);
     signal(sig, SIG_DFL);
 #endif
-    /* Release the main ports as early as possible */
-    if (theHttpConnection >= 0)
-       (void) close(theHttpConnection);
-    if (theInIcpConnection >= 0)
-       (void) close(theInIcpConnection);
+    releaseServerSockets();
     storeWriteCleanLogs();
     PrintRusage(NULL, debug_log);
     if (squid_curtime - SQUID_RELEASE_TIME < 864000) {
@@ -311,16 +319,14 @@ void
 setSocketShutdownLifetimes(int lft)
 {
     FD_ENTRY *f = NULL;
-    int cur;
     int i;
-    for (i = fdstat_biggest_fd(); i >= 0; i--) {
+    for (i = Biggest_FD; i >= 0; i--) {
        f = &fd_table[i];
        if (!f->read_handler && !f->write_handler)
            continue;
        if (fdstatGetType(i) != FD_SOCKET)
            continue;
-       cur = comm_get_fd_lifetime(i);
-       if (cur > 0 && (cur - squid_curtime) <= lft)
+       if (f->lifetime > 0 && (f->lifetime - squid_curtime) <= lft)
            continue;
        comm_set_fd_lifetime(i, lft);
     }
@@ -335,6 +341,8 @@ normal_shutdown(void)
        safeunlink(Config.pidFilename, 0);
        leave_suid();
     }
+    releaseServerSockets();
+    unlinkdClose();
     storeWriteCleanLogs();
     PrintRusage(NULL, debug_log);
     storeCloseLog();
@@ -378,6 +386,7 @@ fatal_common(const char *message)
 void
 fatal(const char *message)
 {
+    releaseServerSockets();
     /* check for store_rebuilding flag because fatal() is often
      * used in early initialization phases, long before we ever
      * get to the store log. */
@@ -391,6 +400,7 @@ fatal(const char *message)
 void
 fatal_dump(const char *message)
 {
+    releaseServerSockets();
     if (message)
        fatal_common(message);
     if (opt_catch_signals)
@@ -508,18 +518,23 @@ leave_suid(void)
     if ((pwd = getpwnam(Config.effectiveUser)) == NULL)
        return;
     if (Config.effectiveGroup && (grp = getgrnam(Config.effectiveGroup))) {
-       setgid(grp->gr_gid);
+       if (setgid(grp->gr_gid) < 0)
+           debug(50, 1, "leave_suid: setgid: %s\n", xstrerror());
     } else {
-       setgid(pwd->pw_gid);
+       if (setgid(pwd->pw_gid) < 0)
+           debug(50, 1, "leave_suid: setgid: %s\n", xstrerror());
     }
     debug(21, 3, "leave_suid: PID %d giving up root, becoming '%s'\n",
        getpid(), pwd->pw_name);
 #if HAVE_SETRESUID
-    setresuid(pwd->pw_uid, pwd->pw_uid, 0);
+    if (setresuid(pwd->pw_uid, pwd->pw_uid, 0) < 0)
+       debug(50, 1, "leave_suid: setresuid: %s\n", xstrerror());
 #elif HAVE_SETEUID
-    seteuid(pwd->pw_uid);
+    if (seteuid(pwd->pw_uid) < 0)
+       debug(50, 1, "leave_suid: seteuid: %s\n", xstrerror());
 #else
-    setuid(pwd->pw_uid);
+    if (setuid(pwd->pw_uid) < 0)
+       debug(50, 1, "leave_suid: setuid: %s\n", xstrerror());
 #endif
 }
 
@@ -546,10 +561,12 @@ no_suid(void)
     uid = geteuid();
     debug(21, 3, "leave_suid: PID %d giving up root priveleges forever\n", getpid());
 #if HAVE_SETRESUID
-    setresuid(uid, uid, uid);
+    if (setresuid(uid, uid, uid) < 0)
+       debug(50, 1, "no_suid: setresuid: %s\n", xstrerror());
 #else
     setuid(0);
-    setuid(uid);
+    if (setuid(uid) < 0)
+       debug(50, 1, "no_suid: setuid: %s\n", xstrerror());
 #endif
 }
 
index ed22eedadc8405147439de13654acd7e4669f4f7..d5e7d3aaa87465b1be57e84dde6430789b09b914 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: tunnel.cc,v 1.43 1997/03/29 04:45:20 wessels Exp $
+ * $Id: tunnel.cc,v 1.44 1997/04/28 04:23:27 wessels Exp $
  *
  * DEBUG: section 26    Secure Sockets Layer Proxy
  * AUTHOR: Duane Wessels
@@ -46,6 +46,7 @@ typedef struct {
     time_t timeout;
     int *size_ptr;             /* pointer to size in an icpStateData for logging */
     int proxying;
+    int ip_lookup_pending;
 } SslStateData;
 
 static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
@@ -118,6 +119,8 @@ sslStateFree(int fd, void *data)
     safe_free(sslState->client.buf);
     xfree(sslState->url);
     requestUnlink(sslState->request);
+    if (sslState->ip_lookup_pending)
+       ipcache_unregister(sslState->host, sslState->server.fd);
     safe_free(sslState);
 }
 
@@ -337,6 +340,7 @@ sslConnect(int fd, const ipcache_addrs * ia, void *data)
     SslStateData *sslState = data;
     request_t *request = sslState->request;
     char *buf = NULL;
+    sslState->ip_lookup_pending = 0;
     if (ia == NULL) {
        debug(26, 4, "sslConnect: Unknown host: %s\n", sslState->host);
        buf = squid_error_url(sslState->url,
@@ -500,6 +504,7 @@ sslPeerSelectComplete(peer * p, void *data)
     } else {
        sslState->port = CACHE_HTTP_PORT;
     }
+    sslState->ip_lookup_pending = 1;
     ipcache_nbgethostbyname(sslState->host,
        sslState->server.fd,
        sslConnect,
diff --git a/src/unlinkd.cc b/src/unlinkd.cc
new file mode 100644 (file)
index 0000000..0a0ac97
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * $Id: unlinkd.cc,v 1.2 1997/04/28 04:23:32 wessels Exp $
+ *
+ * DEBUG: section 43    Unlink Daemon
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from the
+ *  Internet community.  Development is led by Duane Wessels of the
+ *  National Laboratory for Applied Network Research and funded by
+ *  the National Science Foundation.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  
+ */
+
+static char hello_string[] = "hi there\n";
+
+#ifdef UNLINK_DAEMON
+
+/* This is the external unlinkd process */
+
+#include "config.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#define UNLINK_BUF_LEN 1024
+
+int
+main(int argc, char *argv[])
+{
+    char buf[UNLINK_BUF_LEN];
+    char *t;
+    setbuf(stdin, NULL);
+    write(1, hello_string, sizeof(hello_string));
+    while (fgets(buf, UNLINK_BUF_LEN, stdin)) {
+       if ((t = strchr(buf, '\n')))
+           *t = '\0';
+       unlink(buf);
+    }
+    exit(0);
+}
+
+#else /* UNLINK_DAEMON */
+
+/* This code gets linked to Squid */
+
+#include "squid.h"
+
+static int unlinkd_fd = -1;
+int unlinkd_count;
+
+static int unlinkdCreate _PARAMS((void));
+
+#define HELLO_BUFSIZ 128
+static int
+unlinkdCreate(void)
+{
+    pid_t pid;
+    int rfd1, rfd2, wfd1, wfd2;
+    int squid_to_unlinkd[2] =
+    {-1, -1};
+    int unlinkd_to_squid[2] =
+    {-1, -1};
+    int n;
+    char buf[HELLO_BUFSIZ];
+    struct timeval slp;
+    if (pipe(squid_to_unlinkd) < 0) {
+       debug(50, 0, "unlinkdCreate: pipe: %s\n", xstrerror());
+       return -1;
+    }
+    if (pipe(unlinkd_to_squid) < 0) {
+       debug(50, 0, "unlinkdCreate: pipe: %s\n", xstrerror());
+       return -1;
+    }
+    rfd1 = squid_to_unlinkd[0];
+    wfd1 = squid_to_unlinkd[1];
+    rfd2 = unlinkd_to_squid[0];
+    wfd2 = unlinkd_to_squid[1];
+    if ((pid = fork()) < 0) {
+       debug(50, 0, "unlinkdCreate: fork: %s\n", xstrerror());
+       close(rfd1);
+       close(wfd1);
+       close(rfd2);
+       close(wfd2);
+       return -1;
+    }
+    if (pid > 0) {             /* parent process */
+       close(rfd1);
+       close(wfd2);
+       memset(buf, '\0', HELLO_BUFSIZ);
+       n = read(rfd2, buf, HELLO_BUFSIZ - 1);
+       close(rfd2);
+       if (n <= 0) {
+           debug(50, 0, "unlinkdCreate: handshake failed\n");
+           close(wfd1);
+           return -1;
+       } else if (strcmp(buf, hello_string)) {
+           debug(50, 0, "unlinkdCreate: handshake failed\n");
+           debug(50, 0, "--> got '%s'\n", rfc1738_escape(buf));
+           close(wfd1);
+           return -1;
+       }
+       comm_set_fd_lifetime(wfd1, -1);
+       slp.tv_sec = 0;
+       slp.tv_usec = 250000;
+       select(0, NULL, NULL, NULL, &slp);
+       file_open_fd(wfd1, "unlinkd socket", FD_PIPE);
+       commSetNonBlocking(wfd1);
+       return wfd1;
+    }
+    /* child */
+    no_suid();                 /* give up extra priviliges */
+    close(wfd1);
+    close(rfd2);
+    dup2(rfd1, 0);
+    dup2(wfd2, 1);
+    close(rfd1);               /* close FD since we dup'd it */
+    close(wfd2);               /* close parent's FD */
+    commSetCloseOnExec(fileno(debug_log));
+    execlp(Config.Program.unlinkd, "(unlinkd)", NULL);
+    debug(50, 0, "unlinkdCreate: %s: %s\n",
+       Config.Program.unlinkd, xstrerror());
+    _exit(1);
+    return 0;
+}
+
+void
+unlinkdUnlink(const char *path)
+{
+    char *buf;
+    int l;
+    if (unlinkd_fd < 0) {
+       debug_trap("unlinkdUnlink: unlinkd_fd < 0");
+       safeunlink(path, 0);
+       return;
+    }
+    l = strlen(path) + 1;
+    buf = xcalloc(1, l + 1);
+    strcpy(buf, path);
+    strcat(buf, "\n");
+    file_write(unlinkd_fd,
+       buf,
+       l,
+       NULL,                   /* Handler */
+       NULL,                   /* Handler-data */
+       xfree);
+    unlinkd_count++;
+}
+
+void
+unlinkdClose(void)
+{
+    if (unlinkd_fd < 0) {
+       debug_trap("unlinkdClose: unlinkd_fd < 0");
+       return;
+    }
+    file_close(unlinkd_fd);
+    unlinkd_fd = -1;
+}
+
+void
+unlinkdInit(void)
+{
+    unlinkd_count = 0;
+    unlinkd_fd = unlinkdCreate();
+    if (unlinkd_fd < 0)
+       fatal("unlinkdInit: failed to start unlinkd\n");
+    fd_note(unlinkd_fd, Config.Program.unlinkd);
+    debug(43, 0, "Unlinkd pipe opened on FD %d\n", unlinkd_fd);
+}
+
+#endif /* ndef UNLINK_DAEMON */
index 8b3aab5936d6f75fc84ef81a89dfe9ae36f80eac..ca2103d2af351f15ddc6b5c6688bbdcaad1b5eaf 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: url.cc,v 1.54 1997/02/19 17:05:24 wessels Exp $
+ * $Id: url.cc,v 1.55 1997/04/28 04:23:34 wessels Exp $
  *
  * DEBUG: section 23    URL Parsing
  * AUTHOR: Duane Wessels
@@ -168,8 +168,6 @@ urlParseProtocol(const char *s)
        return PROTO_WAIS;
     if (strncasecmp(s, "cache_object", 12) == 0)
        return PROTO_CACHEOBJ;
-    if (strncasecmp(s, "file", 4) == 0)
-       return PROTO_FTP;
     return PROTO_NONE;
 }
 
@@ -246,6 +244,14 @@ urlParse(method_t method, char *url)
        debug(23, 0, "urlParse: Invalid port == 0\n");
        return NULL;
     }
+#ifdef HARDCODE_DENY_PORTS
+    /* These ports are filtered in the default squid.conf, but
+     * maybe someone wants them hardcoded... */
+    if (port == 7 || port == 9 || port = 19) {
+       debug(23, 0, "urlParse: Deny access to port %d\n", port);
+       return NULL;
+    }
+#endif
 #ifdef REMOVE_FTP_TRAILING_SLASHES
     /* remove trailing slashes from FTP URLs */
     if (protocol == PROTO_FTP) {
index 88f8e07bff59f2790a0b865e2713cceee0cd0aba..b106fcb02c6ce3a1d6fa2cdbe05a6d50f974eaee 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: wais.cc,v 1.62 1997/03/04 05:16:45 wessels Exp $
+ * $Id: wais.cc,v 1.63 1997/04/28 04:23:34 wessels Exp $
  *
  * DEBUG: section 24    WAIS Relay
  * AUTHOR: Harvest Derived
@@ -116,6 +116,7 @@ typedef struct {
     int relayport;
     char *mime_hdr;
     char request[MAX_URL];
+    int ip_lookup_pending;
 } WaisStateData;
 
 static int waisStateFree _PARAMS((int, WaisStateData *));
@@ -134,6 +135,8 @@ waisStateFree(int fd, WaisStateData * waisState)
     if (waisState == NULL)
        return 1;
     storeUnlockObject(waisState->entry);
+    if (waisState->ip_lookup_pending)
+       ipcache_unregister(waisState->relayhost, waisState->fd);
     xfree(waisState);
     return 0;
 }
@@ -373,6 +376,7 @@ waisStartComplete(void *data, int status)
     comm_add_close_handler(waisState->fd,
        (PF) waisStateFree,
        (void *) waisState);
+    waisState->ip_lookup_pending = 1;
     ipcache_nbgethostbyname(waisState->relayhost,
        waisState->fd,
        waisConnect,
@@ -384,6 +388,7 @@ static void
 waisConnect(int fd, const ipcache_addrs * ia, void *data)
 {
     WaisStateData *waisState = data;
+    waisState->ip_lookup_pending = 0;
     if (!ipcache_gethostbyname(waisState->relayhost, 0)) {
        debug(24, 4, "waisstart: Unknown host: %s\n", waisState->relayhost);
        squid_error_entry(waisState->entry, ERR_DNS_FAIL, dns_error_message);