From 429fdbecbf36ca7f145bc760181a892136c54445 Mon Sep 17 00:00:00 2001 From: wessels <> Date: Mon, 28 Apr 1997 10:22:55 +0000 Subject: [PATCH] merge 1.1.8->1.1.10; just get it to compile --- src/Makefile.in | 33 +++++- src/acl.cc | 23 ++-- src/cache_cf.cc | 134 ++++++++++++++++------ src/cachemgr.cc | 15 ++- src/client_db.cc | 18 ++- src/client_side.cc | 8 +- src/comm.cc | 211 +++++++++++++++++----------------- src/disk.cc | 40 +++++-- src/dns.cc | 35 +++++- src/dnsserver.cc | 13 +-- src/fqdncache.cc | 279 +++++++++++++++++++++++++++++++-------------- src/ftp.cc | 96 +++++++++------- src/http.cc | 22 ++-- src/icmp.cc | 6 +- src/ipcache.cc | 92 +++++++++------ src/main.cc | 23 ++-- src/neighbors.cc | 246 ++++++++++++++++++++++++++++----------- src/net_db.cc | 276 +++++++++++++++++++++++++++++++++++++++++--- src/peer_select.cc | 55 ++++++--- src/pinger.cc | 27 ++--- src/redirect.cc | 8 +- src/squid.h | 10 +- src/ssl.cc | 7 +- src/stat.cc | 53 +++++++-- src/store.cc | 200 ++++++++++++++++++++------------ src/tools.cc | 51 ++++++--- src/tunnel.cc | 7 +- src/unlinkd.cc | 199 ++++++++++++++++++++++++++++++++ src/url.cc | 12 +- src/wais.cc | 7 +- 30 files changed, 1605 insertions(+), 601 deletions(-) create mode 100644 src/unlinkd.cc diff --git a/src/Makefile.in b/src/Makefile.in index da4b07c37d..78d6a187ba 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -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 diff --git a/src/acl.cc b/src/acl.cc index 3bba4f25da..e22e1a58e9 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -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; diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 8f15e3c194..62085c23a2 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -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; +} diff --git a/src/cachemgr.cc b/src/cachemgr.cc index 2d873d734e..115801ceed 100644 --- a/src/cachemgr.cc +++ b/src/cachemgr.cc @@ -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\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); diff --git a/src/client_db.cc b/src/client_db.cc index d424f826e4..810b5066af 100644 --- a/src/client_db.cc +++ b/src/client_db.cc @@ -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) diff --git a/src/client_side.cc b/src/client_side.cc index 2bdbb7296d..a1de539667 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -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) { diff --git a/src/comm.cc b/src/comm.cc index 9781777abc..dc0dc23495 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -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); } diff --git a/src/disk.cc b/src/disk.cc index 103a87b03c..bd1b3284f7 100644 --- a/src/disk.cc +++ b/src/disk.cc @@ -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; } diff --git a/src/dns.cc b/src/dns.cc index 99184be85a..778862ba67 100644 --- a/src/dns.cc +++ b/src/dns.cc @@ -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); } diff --git a/src/dnsserver.cc b/src/dnsserver.cc index 792092205f..ed0aa93123 100644 --- a/src/dnsserver.cc +++ b/src/dnsserver.cc @@ -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) diff --git a/src/fqdncache.cc b/src/fqdncache.cc index a6af14df9d..0931813a18 100644 --- a/src/fqdncache.cc +++ b/src/fqdncache.cc @@ -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); + } +} diff --git a/src/ftp.cc b/src/ftp.cc index 33f4eae47c..e6692b24bd 100644 --- a/src/ftp.cc +++ b/src/ftp.cc @@ -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); diff --git a/src/http.cc b/src/http.cc index bee2a302da..23c8b74282 100644 --- a/src/http.cc +++ b/src/http.cc @@ -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); } diff --git a/src/icmp.cc b/src/icmp.cc index fa2bc496d2..0ad95a4258 100644 --- a/src/icmp.cc +++ b/src/icmp.cc @@ -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); diff --git a/src/ipcache.cc b/src/ipcache.cc index d7e454d236..3d0ba41f91 100644 --- a/src/ipcache.cc +++ b/src/ipcache.cc @@ -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 @@ -106,11 +106,6 @@ #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); +} diff --git a/src/main.cc b/src/main.cc index 9f7bf12ba7..b6c195155a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -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); diff --git a/src/neighbors.cc b/src/neighbors.cc index 0810f24044..31fa20832d 100644 --- a/src/neighbors.cc +++ b/src/neighbors.cc @@ -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 @@ -105,6 +105,9 @@ #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); +} diff --git a/src/net_db.cc b/src/net_db.cc index 78e05088e4..22c5cd1b30 100644 --- a/src/net_db.cc +++ b/src/net_db.cc @@ -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; } diff --git a/src/peer_select.cc b/src/peer_select.cc index 8fcdbc14e7..50d3fb908f 100644 --- a/src/peer_select.cc +++ b/src/peer_select.cc @@ -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 @@ -31,6 +31,29 @@ #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); diff --git a/src/pinger.cc b/src/pinger.cc index 409defc8c8..1184a55081 100644 --- a/src/pinger.cc +++ b/src/pinger.cc @@ -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) { diff --git a/src/redirect.cc b/src/redirect.cc index 20d50d63c7..7adbf9cc4f 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -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) diff --git a/src/squid.h b/src/squid.h index 849c34a76a..03f14aa559 100644 --- a/src/squid.h +++ b/src/squid.h @@ -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 diff --git a/src/ssl.cc b/src/ssl.cc index 8e10064078..d66f08910a 100644 --- a/src/ssl.cc +++ b/src/ssl.cc @@ -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, diff --git a/src/stat.cc b/src/stat.cc index d8130bc277..a654a5e506 100644 --- a/src/stat.cc +++ b/src/stat.cc @@ -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) { diff --git a/src/store.cc b/src/store.cc index 98a1510ed5..c9d839bf5e 100644 --- a/src/store.cc +++ b/src/store.cc @@ -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)); +} diff --git a/src/tools.cc b/src/tools.cc index beac4d5a06..f12a98af87 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -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 } diff --git a/src/tunnel.cc b/src/tunnel.cc index ed22eedadc..d5e7d3aaa8 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -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 index 0000000000..0a0ac97cbd --- /dev/null +++ b/src/unlinkd.cc @@ -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 +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#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 */ diff --git a/src/url.cc b/src/url.cc index 8b3aab5936..ca2103d2af 100644 --- a/src/url.cc +++ b/src/url.cc @@ -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) { diff --git a/src/wais.cc b/src/wais.cc index 88f8e07bff..b106fcb02c 100644 --- a/src/wais.cc +++ b/src/wais.cc @@ -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); -- 2.39.5