git-svn: trunk@3022
Nigel Horne authored on 2007/04/18 13:42:39... | ... |
@@ -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 |
/* |