git-svn: trunk@3114
Nigel Horne authored on 2007/06/25 19:24:49... | ... |
@@ -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 |