Browse code

Don't PING servers that are down so often

git-svn: trunk@3114

Nigel Horne authored on 2007/06/25 19:24:49
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Mon Jun 25 11:00:32 BST 2007 (njh)
2
+----------------------------------
3
+  * clamav-milter:	Don't PING servers that are down so often
4
+
1 5
 Sun Jun 24 16:57:34 CEST 2007 (tk)
2 6
 ----------------------------------
3 7
   * 0.91rc2 (released with JS and PST code removed)
... ...
@@ -33,7 +33,7 @@
33 33
  */
34 34
 static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.312 2007/02/12 22:24:21 njh Exp $";
35 35
 
36
-#define	CM_VERSION	"devel-070419"
36
+#define	CM_VERSION	"devel-070625"
37 37
 
38 38
 #if HAVE_CONFIG_H
39 39
 #include "clamav-config.h"
... ...
@@ -289,6 +289,7 @@ static	int		createSession(unsigned int s);
289 289
 #else
290 290
 static	int		pingServer(int serverNumber);
291 291
 static	void		*try_server(void *var);
292
+static	int		active_servers(void);
292 293
 struct	try_server_struct {
293 294
 	int	sock;
294 295
 	int	rc;
... ...
@@ -481,6 +482,10 @@ static	in_addr_t	*serverIPs;	/* IPv4 only, in network byte order */
481 481
 static	long	*serverIPs;	/* IPv4 only, in network byte order */
482 482
 #endif
483 483
 static	int	numServers;	/* number of elements in serverIPs array */
484
+#ifndef	SESSION
485
+#define	RETRY_SECS	300	/* How often to retry a server that's down */
486
+static	time_t	*last_failed_pings;	/* For servers that are down */
487
+#endif
484 488
 
485 489
 #ifdef	CL_EXPERIMENTAL
486 490
 static	char	*rootdir;	/* for chroot */
... ...
@@ -492,7 +497,6 @@ static	struct	session {
492 492
 	enum	{ CMDSOCKET_FREE, CMDSOCKET_INUSE, CMDSOCKET_DOWN }	status;
493 493
 } *sessions;	/* max_children elements in the array */
494 494
 static	pthread_mutex_t sstatus_mutex = PTHREAD_MUTEX_INITIALIZER;
495
-
496 495
 #endif	/*SESSION*/
497 496
 
498 497
 static	pthread_cond_t	watchdog_cond = PTHREAD_COND_INITIALIZER;
... ...
@@ -572,7 +576,7 @@ help(void)
572 572
 	puts("\tCopyright (C) 2007 Nigel Horne <njh@clamav.net>\n");
573 573
 
574 574
 	puts(_("\t--advisory\t\t-A\tFlag viruses rather than deleting them."));
575
-	puts(_("\t--blacklist-time\t-k\tTime (in seconds) to blacklist an IP."));
575
+	puts(_("\t--blacklist-time=SECS\t-k\tTime (in seconds) to blacklist an IP."));
576 576
 	puts(_("\t--black-hole-mode\t\tDon't scan messages aliased to /dev/null."));
577 577
 #ifdef	BOUNCE
578 578
 	puts(_("\t--bounce\t\t-b\tSend a failure message to the sender."));
... ...
@@ -629,6 +633,9 @@ main(int argc, char **argv)
629 629
 	int i, Bflag = 0, server = 0;
630 630
 	char *cfgfile = NULL;
631 631
 	const char *wont_blacklist = NULL;
632
+#ifdef	C_LINUX
633
+	const char *lang;
634
+#endif
632 635
 	const struct cfgstruct *cpt;
633 636
 	char version[VERSION_LENGTH + 1];
634 637
 	pthread_t tid;
... ...
@@ -644,7 +651,7 @@ main(int argc, char **argv)
644 644
 	struct smfiDesc smfilter = {
645 645
 		"ClamAv", /* filter name */
646 646
 		SMFI_VERSION,	/* version code -- leave untouched */
647
-		SMFIF_ADDHDRS|SMFIF_CHGHDRS,	/* flags - we add and deleted headers */
647
+		SMFIF_ADDHDRS|SMFIF_CHGHDRS,	/* flags - we add and delete headers */
648 648
 		clamfi_connect, /* connexion callback */
649 649
 #ifdef	CL_DEBUG
650 650
 		clamfi_helo,	/* HELO filter callback */
... ...
@@ -696,6 +703,13 @@ main(int argc, char **argv)
696 696
 	setlocale(LC_ALL, "");
697 697
 	bindtextdomain(progname, DATADIR"/clamav-milter/locale");
698 698
 	textdomain(progname);
699
+	lang = getenv("LANG");
700
+
701
+	if(lang && (strstr(lang, "UTF-8") != NULL)) {
702
+		fprintf(stderr, "*** Your LANG environment variable is set to '%s\n", lang);
703
+		fprintf(stderr, "This is known to cause problems for some %s installations.\n", argv[0]);
704
+		fputs("If you get failures with temporary fils, please try again with LANG unset.\n", stderr);
705
+	}
699 706
 #endif
700 707
 
701 708
 	for(;;) {
... ...
@@ -1429,7 +1443,7 @@ main(int argc, char **argv)
1429 1429
 			perror(localSocket);
1430 1430
 			return EX_UNAVAILABLE;
1431 1431
 		}
1432
-		if(send(sessions[0].sock, "SESSION\n", 7, 0) < 7) {
1432
+		if(send(sessions[0].sock, "SESSION\n", 8, 0) < 8) {
1433 1433
 			perror("send");
1434 1434
 			fputs(_("!Can't create a clamd session"), stderr);
1435 1435
 			return EX_UNAVAILABLE;
... ...
@@ -1592,6 +1606,7 @@ main(int argc, char **argv)
1592 1592
 			logg(_("!Can't find any clamd server\n"));
1593 1593
 			return EX_CONFIG;
1594 1594
 		}
1595
+		last_failed_pings = (time_t *)cli_calloc(numServers, sizeof(time_t));
1595 1596
 #endif
1596 1597
 	} else {
1597 1598
 		fprintf(stderr, _("%s: You must select server type (local/TCP) in %s\n"),
... ...
@@ -1948,6 +1963,10 @@ main(int argc, char **argv)
1948 1948
 			if(unlink(&port[6]) < 0)
1949 1949
 				if(errno != ENOENT)
1950 1950
 					perror(&port[6]);
1951
+		} else if(port[0] == '/') {
1952
+			if(unlink(port) < 0)
1953
+				if(errno != ENOENT)
1954
+					perror(port);
1951 1955
 		}
1952 1956
 	}
1953 1957
 
... ...
@@ -2015,10 +2034,10 @@ static int
2015 2015
 createSession(unsigned int s)
2016 2016
 {
2017 2017
 	int ret = 0, fd;
2018
-	struct sockaddr_in server;
2019 2018
 	const int serverNumber = s % numServers;
2020 2019
 	struct session *session = &sessions[s];
2021 2020
 	const struct protoent *proto;
2021
+	struct sockaddr_in server;
2022 2022
 
2023 2023
 	cli_dbgmsg("createSession session %d, server %d\n", s, serverNumber);
2024 2024
 	assert(s < max_children);
... ...
@@ -2040,7 +2059,7 @@ createSession(unsigned int s)
2040 2040
 	} else if(connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
2041 2041
 		perror("connect");
2042 2042
 		ret = 1;
2043
-	} else if(send(fd, "SESSION\n", 7, 0) < 7) {
2043
+	} else if(send(fd, "SESSION\n", 8, 0) < 8) {
2044 2044
 		perror("send");
2045 2045
 		ret = 1;
2046 2046
 	}
... ...
@@ -2287,10 +2306,10 @@ findServer(void)
2287 2287
 {
2288 2288
 	struct sockaddr_in *servers, *server;
2289 2289
 	int maxsock, i, j;
2290
-	fd_set rfds;
2291 2290
 	int retval;
2292 2291
 	pthread_t *tids;
2293 2292
 	struct try_server_struct *socks;
2293
+	fd_set rfds;
2294 2294
 
2295 2295
 	assert(tcpSocket != 0);
2296 2296
 	assert(numServers > 0);
... ...
@@ -2298,6 +2317,9 @@ findServer(void)
2298 2298
 	if(numServers == 1)
2299 2299
 		return 0;
2300 2300
 
2301
+	if(active_servers() <= 1)
2302
+		return 0;
2303
+
2301 2304
 	servers = (struct sockaddr_in *)cli_calloc(numServers, sizeof(struct sockaddr_in));
2302 2305
 	if(servers == NULL)
2303 2306
 		return 0;
... ...
@@ -2432,6 +2454,30 @@ findServer(void)
2432 2432
 }
2433 2433
 
2434 2434
 /*
2435
+ * How many servers are up at the moment? If a server is marked as down,
2436
+ *	don't keep on flooding it with requests to see if it's now back up
2437
+ */
2438
+static int
2439
+active_servers(void)
2440
+{
2441
+	int server, count;
2442
+	time_t now = (time_t)0;
2443
+
2444
+	for(count = server = 0; server < numServers; server++)
2445
+		if(last_failed_pings[server] == (time_t)0)
2446
+			count++;
2447
+		else {
2448
+			if(now == (time_t)0)
2449
+				time(&now);
2450
+			if(now - last_failed_pings[server] >= RETRY_SECS)
2451
+				/* Try this server again next time */
2452
+				last_failed_pings[server] = (time_t)0;
2453
+		}
2454
+
2455
+	return count;
2456
+}
2457
+
2458
+/*
2435 2459
  * Connecting to remote servers can take some time, so let's connect to
2436 2460
  *	them in parallel. This routine is started as a thread
2437 2461
  */
... ...
@@ -2443,6 +2489,11 @@ try_server(void *var)
2443 2443
 	struct sockaddr *server = (struct sockaddr *)s->server;
2444 2444
 	int server_index = s->server_index;
2445 2445
 
2446
+	if(last_failed_pings[server_index]) {
2447
+		s->rc = 0;
2448
+		return var;
2449
+	}
2450
+
2446 2451
 	logg("*try_server: sock %d\n", sock);
2447 2452
 
2448 2453
 	if((connect(sock, server, sizeof(struct sockaddr)) < 0) ||
... ...
@@ -2467,6 +2518,7 @@ try_server(void *var)
2467 2467
 		free(hostname);
2468 2468
 #endif
2469 2469
 		broadcast(_("Check clamd server - it may be down\n"));
2470
+		time(&last_failed_pings[server_index]);
2470 2471
 	}
2471 2472
 
2472 2473
 	return var;
... ...
@@ -2520,7 +2572,7 @@ clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
2520 2520
 		remoteIP = "127.0.0.1";
2521 2521
 	else {
2522 2522
 #ifdef HAVE_INET_NTOP
2523
-		switch (hostaddr->sa_family) {
2523
+		switch(hostaddr->sa_family) {
2524 2524
 			case AF_INET:
2525 2525
 				remoteIP = (char *)inet_ntop(AF_INET, &((struct sockaddr_in *)(hostaddr))->sin_addr, ip, sizeof(ip));
2526 2526
 				break;
... ...
@@ -4272,8 +4324,8 @@ connect2clamd(struct privdata *privdata)
4272 4272
 		cli_dbgmsg("Saving message to %s to scan later\n", privdata->filename);
4273 4273
 	} else {	/* communicate to clamd */
4274 4274
 		int freeServer, nbytes;
4275
+		in_port_t p;
4275 4276
 		struct sockaddr_in reply;
4276
-		unsigned short p;
4277 4277
 		char buf[64];
4278 4278
 
4279 4279
 #ifdef	SESSION