Browse code

Wait longer for clamd to start on the localhost

git-svn: trunk@3022

Nigel Horne authored on 2007/04/18 13:42:39
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Apr 18 04:49:50 BST 2007 (njh)
2
+----------------------------------
3
+  * clamav-milter:	Wait longer for clamd to start on the localhost
4
+
1 5
 Mon Apr 16 11:58:30 BST 2007 (njh)
2 6
 ----------------------------------
3 7
   * libclamav/pdf.c:	Bug 459
... ...
@@ -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-070412"
36
+#define	CM_VERSION	"devel-070418"
37 37
 
38 38
 #if HAVE_CONFIG_H
39 39
 #include "clamav-config.h"
... ...
@@ -169,6 +169,7 @@ typedef	unsigned int	in_addr_t;
169 169
 
170 170
 #define	VERSION_LENGTH	128
171 171
 #define	DEFAULT_TIMEOUT	120
172
+#define	NTRIES	30	/* How long to wait for the local clamd to start */
172 173
 
173 174
 /*#define	SESSION*/
174 175
 		/* Keep one command connexion open to clamd, otherwise a new
... ...
@@ -197,6 +198,7 @@ typedef	unsigned int	in_addr_t;
197 197
  * TODO: allow each To: line in the whitelist file to specify a quarantine email
198 198
  *	address
199 199
  * TODO: optionally use zlib to compress data sent to remote hosts
200
+ * TODO: Finish IPv6 support (serverIPs array is IPv4 only)
200 201
  */
201 202
 
202 203
 struct header_node_t {
... ...
@@ -318,7 +320,7 @@ static	void	header_list_add(header_list_t list, const char *headerf, const char
318 318
 static	void	header_list_print(header_list_t list, FILE *fp);
319 319
 static	int	connect2clamd(struct privdata *privdata);
320 320
 static	int	sendToFrom(struct privdata *privdata);
321
-static	void	checkClamd(void);
321
+static	int	checkClamd(int log_result);
322 322
 static	int	sendtemplate(SMFICTX *ctx, const char *filename, FILE *sendmail, const char *virusname);
323 323
 static	int	qfile(struct privdata *privdata, const char *sendmailId, const char *virusname);
324 324
 static	int	move(const char *oldfile, const char *newfile);
... ...
@@ -474,9 +476,9 @@ static	char	*port = NULL;	/* sendmail->milter comms */
474 474
 
475 475
 static	const	char	*serverHostNames = "127.0.0.1";
476 476
 #if	HAVE_IN_ADDR_T
477
-static	in_addr_t	*serverIPs;	/* IPv4 only */
477
+static	in_addr_t	*serverIPs;	/* IPv4 only, in network byte order */
478 478
 #else
479
-static	long	*serverIPs;	/* IPv4 only */
479
+static	long	*serverIPs;	/* IPv4 only, in network byte order */
480 480
 #endif
481 481
 static	int	numServers;	/* number of elements in serverIPs array */
482 482
 
... ...
@@ -1404,7 +1406,7 @@ main(int argc, char **argv)
1404 1404
 
1405 1405
 		serverIPs = (in_addr_t *)cli_malloc(sizeof(in_addr_t));
1406 1406
 #ifdef	INADDR_LOOPBACK
1407
-		serverIPs[0] = INADDR_LOOPBACK;
1407
+		serverIPs[0] = htonl(INADDR_LOOPBACK);
1408 1408
 #else
1409 1409
 		serverIPs[0] = inet_addr("127.0.0.1");
1410 1410
 #endif
... ...
@@ -1521,26 +1523,45 @@ main(int argc, char **argv)
1521 1521
 				memcpy((char *)&serverIPs[i], h->h_addr, sizeof(serverIPs[i]));
1522 1522
 			}
1523 1523
 
1524
+#if	defined(NTRIES) && ((NTRIES > 1))
1524 1525
 #ifndef	SESSION
1526
+#ifdef	INADDR_LOOPBACK
1527
+			if(serverIPs[i] == htonl(INADDR_LOOPBACK)) {
1528
+#else
1525 1529
 #if	HAVE_IN_ADDR_T
1526 1530
 			if(serverIPs[i] == (in_addr_t)inet_addr("127.0.0.1")) {
1527 1531
 #else
1528 1532
 			if(serverIPs[i] == (long)inet_addr("127.0.0.1")) {
1529 1533
 #endif
1534
+#endif
1535
+				int tries;
1536
+
1530 1537
 				/*
1531 1538
 				 * Fudge to allow clamd to come up on
1532 1539
 				 * our local machine
1533 1540
 				 */
1534
-				sync();
1535
-				sleep(2);
1541
+				for(tries = 0; tries < NTRIES - 1; tries++) {
1542
+					if(pingServer(i))
1543
+						break;
1544
+					if(!checkClamd(1))
1545
+						break;
1546
+					logg(_("Waiting for clamd to come up\n"));
1547
+					/*
1548
+					 * something to do as the system starts
1549
+					 */
1550
+					sync();
1551
+					sleep(1);
1552
+				}
1553
+				/* Will try one more time */
1536 1554
 			}
1555
+#endif	/* NTRIES > 1 */
1537 1556
 
1538 1557
 			if(pingServer(i))
1539 1558
 				activeServers++;
1540 1559
 			else {
1541 1560
 				cli_warnmsg(_("Can't talk to clamd server %s on port %d\n"),
1542 1561
 					hostname, tcpSocket);
1543
-				if(serverIPs[i] == INADDR_LOOPBACK) {
1562
+				if(serverIPs[i] == htonl(INADDR_LOOPBACK)) {
1544 1563
 					if(cfgopt(copt, "TCPAddr")->enabled)
1545 1564
 						cli_warnmsg(_("Check the value for TCPAddr in %s\n"), cfgfile);
1546 1565
 				} else
... ...
@@ -1560,7 +1581,7 @@ main(int argc, char **argv)
1560 1560
 			if(createSession(i) < 0)
1561 1561
 				return EX_UNAVAILABLE;
1562 1562
 		if(activeServers == 0) {
1563
-			cli_warnmsg(_("Can't find any active clamd servers\n"));
1563
+			logg(_("!Can't find any clamd server\n"));
1564 1564
 			cli_warnmsg(_("Check your entry for TCPSocket in %s\n"),
1565 1565
 				cfgfile);
1566 1566
 		}
... ...
@@ -2079,7 +2100,7 @@ pingServer(int serverNumber)
2079 2079
 			perror(localSocket);
2080 2080
 			return 0;
2081 2081
 		}
2082
-		checkClamd();
2082
+		checkClamd(1);
2083 2083
 		if(connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
2084 2084
 			perror(localSocket);
2085 2085
 			close(sock);
... ...
@@ -2108,6 +2129,7 @@ pingServer(int serverNumber)
2108 2108
 		if(connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
2109 2109
 			int is_connected = 0;
2110 2110
 
2111
+#if	(!defined(NTRIES)) || ((NTRIES <= 1))
2111 2112
 			if(errno == ECONNREFUSED) {
2112 2113
 				/*
2113 2114
 				 * During startup there is a race condition:
... ...
@@ -2125,13 +2147,15 @@ pingServer(int serverNumber)
2125 2125
 				if(connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) >= 0)
2126 2126
 					is_connected = 1;
2127 2127
 			}
2128
+#endif
2128 2129
 			if(!is_connected) {
2129 2130
 				char *hostname = cli_strtok(serverHostNames,
2130 2131
 					serverNumber, ":");
2131 2132
 
2132 2133
 				perror(hostname ? hostname : "connect");
2133 2134
 				close(sock);
2134
-				free(hostname);
2135
+				if(hostname)
2136
+					free(hostname);
2135 2137
 				return 0;
2136 2138
 			}
2137 2139
 		}
... ...
@@ -2421,13 +2445,10 @@ try_server(void *var)
2421 2421
 
2422 2422
 	logg("*try_server: sock %d\n", sock);
2423 2423
 
2424
-	if(connect(sock, server, sizeof(struct sockaddr)) < 0) {
2425
-		perror("connect");
2426
-		s->rc = 0;
2427
-	} else if(send(sock, "PING\n", 5, 0) < 5) {
2428
-		perror("send");
2424
+	if((connect(sock, server, sizeof(struct sockaddr)) < 0) ||
2425
+	   (send(sock, "PING\n", 5, 0) < 5))
2429 2426
 		s->rc = 0;
2430
-	} else
2427
+	else
2431 2428
 		s->rc = 1;
2432 2429
 
2433 2430
 	if(s->rc == 0) {
... ...
@@ -2440,6 +2461,7 @@ try_server(void *var)
2440 2440
 #else
2441 2441
 		char *hostname = cli_strtok(serverHostNames, server_index, ":");
2442 2442
 #endif
2443
+		perror(hostname);
2443 2444
 		logg(_("^Check clamd server %s - it may be down\n"), hostname);
2444 2445
 #ifndef	MAXHOSTNAMELEN
2445 2446
 		free(hostname);
... ...
@@ -3986,7 +4008,7 @@ clamfi_send(struct privdata *privdata, size_t len, const char *format, ...)
3986 3986
 				logg(_("!write failure (%lu bytes) to clamd: %s\n"),
3987 3987
 					(unsigned long)len, strerror(errno));
3988 3988
 #endif
3989
-				checkClamd();
3989
+				checkClamd(1);
3990 3990
 			}
3991 3991
 
3992 3992
 			return -1;
... ...
@@ -4505,26 +4527,52 @@ sendToFrom(struct privdata *privdata)
4505 4505
 }
4506 4506
 
4507 4507
 /*
4508
- * If possible, check if clamd has died, and report if it has
4508
+ * If possible, check if clamd has died, and, if requested, report if it has
4509
+ * Returns true if OK or unknown, otherwise false
4509 4510
  */
4510
-static void
4511
-checkClamd(void)
4511
+static int
4512
+checkClamd(int log_result)
4512 4513
 {
4513 4514
 	pid_t pid;
4514 4515
 	int fd, nbytes;
4515 4516
 	char buf[9];
4516 4517
 
4517
-	if(!localSocket)
4518
-		return;	/* communicating via TCP */
4518
+	if(!localSocket) {
4519
+		/* communicating via TCP, is one of the servers localhost? */
4520
+		int i, onlocal;
4521
+
4522
+		onlocal = 0;
4523
+		for(i = 0; i < numServers; i++)
4524
+#ifdef	INADDR_LOOPBACK
4525
+			if(serverIPs[0] == htonl(INADDR_LOOPBACK)) {
4526
+#else
4527
+			if(serverIPs[0] == inet_addr("127.0.0.1")) {
4528
+#endif
4529
+				onlocal = 1;
4530
+				break;
4531
+			}
4532
+
4533
+		if(!onlocal) {
4534
+			/* No local clamd, use pingServer() to tell */
4535
+			for(i = 0; i < numServers; i++)
4536
+				if(pingServer(i))
4537
+					return 1;
4538
+			if(log_result)
4539
+				logg(_("!Can't find any clamd server\n"));
4540
+			return 0;
4541
+		}
4542
+	}
4519 4543
 
4520 4544
 	if(pidFile == NULL)
4521
-		return;	/* PidFile directive missing from clamd.conf */
4545
+		return 1;	/* PidFile directive missing from clamd.conf */
4522 4546
 
4523 4547
 	fd = open(pidFile, O_RDONLY);
4524 4548
 	if(fd < 0) {
4525
-		perror(pidFile);
4526
-		logg(_("!Can't open %s"), pidFile);
4527
-		return;
4549
+		if(log_result) {
4550
+			perror(pidFile);
4551
+			logg(_("!Can't open %s\n"), pidFile);
4552
+		}
4553
+		return 1;	/* unknown */
4528 4554
 	}
4529 4555
 	nbytes = read(fd, buf, sizeof(buf) - 1);
4530 4556
 	if(nbytes < 0)
... ...
@@ -4534,9 +4582,13 @@ checkClamd(void)
4534 4534
 	close(fd);
4535 4535
 	pid = atoi(buf);
4536 4536
 	if((kill(pid, 0) < 0) && (errno == ESRCH)) {
4537
-		perror("clamd");
4538
-		logg(_("!Clamd (pid %d) seems to have died"), (int)pid);
4537
+		if(log_result) {
4538
+			perror("clamd");
4539
+			logg(_("!Clamd (pid %d) seems to have died\n"), (int)pid);
4540
+		}
4541
+		return 0;	/* down */
4539 4542
 	}
4543
+	return 1;	/* up */
4540 4544
 }
4541 4545
 
4542 4546
 /*