git-svn: trunk@2590
Tomasz Kojm authored on 2007/01/07 01:00:14... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Sat Jan 6 16:57:23 CET 2007 (tk) |
|
2 |
+--------------------------------- |
|
3 |
+ * freshclam: initial version of mirror manager; new option --list-mirrors |
|
4 |
+ |
|
1 | 5 |
Fri Jan 5 14:45:29 GMT 2007 (njh) |
2 | 6 |
---------------------------------- |
3 | 7 |
* libclamav/pst.c: Commit fix from upstream detecting Outlook tasks |
... | ... |
@@ -74,7 +74,7 @@ am_freshclam_OBJECTS = output.$(OBJEXT) cfgparser.$(OBJEXT) \ |
74 | 74 |
getopt.$(OBJEXT) memory.$(OBJEXT) misc.$(OBJEXT) \ |
75 | 75 |
options.$(OBJEXT) cdiff.$(OBJEXT) freshclam.$(OBJEXT) \ |
76 | 76 |
manager.$(OBJEXT) notify.$(OBJEXT) dns.$(OBJEXT) \ |
77 |
- execute.$(OBJEXT) nonblock.$(OBJEXT) |
|
77 |
+ execute.$(OBJEXT) nonblock.$(OBJEXT) mirman.$(OBJEXT) |
|
78 | 78 |
freshclam_OBJECTS = $(am_freshclam_OBJECTS) |
79 | 79 |
freshclam_LDADD = $(LDADD) |
80 | 80 |
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) |
... | ... |
@@ -243,7 +243,9 @@ freshclam_SOURCES = \ |
243 | 243 |
execute.c \ |
244 | 244 |
execute.h \ |
245 | 245 |
nonblock.c \ |
246 |
- nonblock.h |
|
246 |
+ nonblock.h \ |
|
247 |
+ mirman.c \ |
|
248 |
+ mirman.h |
|
247 | 249 |
|
248 | 250 |
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav |
249 | 251 |
all: all-am |
... | ... |
@@ -325,6 +327,7 @@ distclean-compile: |
325 | 325 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ |
326 | 326 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manager.Po@am__quote@ |
327 | 327 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory.Po@am__quote@ |
328 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mirman.Po@am__quote@ |
|
328 | 329 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ |
329 | 330 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonblock.Po@am__quote@ |
330 | 331 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify.Po@am__quote@ |
... | ... |
@@ -57,6 +57,7 @@ |
57 | 57 |
|
58 | 58 |
#include "execute.h" |
59 | 59 |
#include "manager.h" |
60 |
+#include "mirman.h" |
|
60 | 61 |
|
61 | 62 |
static short terminate = 0; |
62 | 63 |
extern int active_children; |
... | ... |
@@ -142,6 +143,7 @@ void help(void) |
142 | 142 |
mprintf(" --on-update-execute=COMMAND execute COMMAND after successful update\n"); |
143 | 143 |
mprintf(" --on-error-execute=COMMAND execute COMMAND if errors occured\n"); |
144 | 144 |
mprintf(" --on-outdated-execute=COMMAND execute COMMAND when software is outdated\n"); |
145 |
+ mprintf(" --list-mirrors print mirrors from mirrors.dat\n"); |
|
145 | 146 |
|
146 | 147 |
mprintf("\n"); |
147 | 148 |
} |
... | ... |
@@ -174,7 +176,7 @@ int download(const struct cfgstruct *copt, const struct optstruct *opt) |
174 | 174 |
logg("Giving up on %s...\n", cpt->strarg); |
175 | 175 |
cpt = (struct cfgstruct *) cpt->nextarg; |
176 | 176 |
if(!cpt) { |
177 |
- logg("^Update failed. Your network may be down or none of the mirrors listed in freshclam.conf is working.\n"); |
|
177 |
+ logg("Update failed. Your network may be down or none of the mirrors listed in freshclam.conf is working. Check http://www.clamav.net/support/mirror-problem for possible reasons.\n"); |
|
178 | 178 |
} |
179 | 179 |
try = 0; |
180 | 180 |
} |
... | ... |
@@ -203,6 +205,7 @@ int main(int argc, char **argv) |
203 | 203 |
struct passwd *user; |
204 | 204 |
#endif |
205 | 205 |
struct stat statbuf; |
206 |
+ struct mirdat mdat; |
|
206 | 207 |
struct optstruct *opt; |
207 | 208 |
const char *short_options = "hvdp:Vl:c:u:a:"; |
208 | 209 |
static struct option long_options[] = { |
... | ... |
@@ -228,6 +231,7 @@ int main(int argc, char **argv) |
228 | 228 |
{"on-update-execute", 1, 0, 0}, |
229 | 229 |
{"on-error-execute", 1, 0, 0}, |
230 | 230 |
{"on-outdated-execute", 1, 0, 0}, |
231 |
+ {"list-mirrors", 0, 0, 0}, |
|
231 | 232 |
{0, 0, 0, 0} |
232 | 233 |
}; |
233 | 234 |
|
... | ... |
@@ -403,6 +407,17 @@ int main(int argc, char **argv) |
403 | 403 |
} else |
404 | 404 |
logg("*Current working dir is %s\n", newdir); |
405 | 405 |
|
406 |
+ |
|
407 |
+ if(opt_check(opt, "list-mirrors")) { |
|
408 |
+ if(mirman_read("mirrors.dat", &mdat) == -1) { |
|
409 |
+ printf("Can't read mirrors.dat\n"); |
|
410 |
+ return 55; |
|
411 |
+ } |
|
412 |
+ mirman_list(&mdat); |
|
413 |
+ mirman_free(&mdat); |
|
414 |
+ return 0; |
|
415 |
+ } |
|
416 |
+ |
|
406 | 417 |
#ifdef C_WINDOWS |
407 | 418 |
{ |
408 | 419 |
WSADATA wsaData; |
... | ... |
@@ -47,6 +47,7 @@ |
47 | 47 |
#include "dns.h" |
48 | 48 |
#include "execute.h" |
49 | 49 |
#include "nonblock.h" |
50 |
+#include "mirman.h" |
|
50 | 51 |
|
51 | 52 |
#include "shared/options.h" |
52 | 53 |
#include "shared/cfgparser.h" |
... | ... |
@@ -64,9 +65,9 @@ |
64 | 64 |
#endif |
65 | 65 |
|
66 | 66 |
|
67 |
-static int wwwconnect(const char *server, const char *proxy, int pport, char *ip, const char *localip, int ctimeout) |
|
67 |
+static int wwwconnect(const char *server, const char *proxy, int pport, char *ip, const char *localip, int ctimeout, struct mirdat *mdat) |
|
68 | 68 |
{ |
69 |
- int socketfd = -1, port, i; |
|
69 |
+ int socketfd = -1, port, i, ret; |
|
70 | 70 |
struct sockaddr_in name; |
71 | 71 |
struct hostent *host; |
72 | 72 |
char ipaddr[16]; |
... | ... |
@@ -187,6 +188,14 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip |
187 | 187 |
ia = (unsigned char *) host->h_addr_list[i]; |
188 | 188 |
sprintf(ipaddr, "%u.%u.%u.%u", ia[0], ia[1], ia[2], ia[3]); |
189 | 189 |
|
190 |
+ if((ret = mirman_check(((struct in_addr *) ia)->s_addr, mdat))) { |
|
191 |
+ if(ret == 1) |
|
192 |
+ logg("Ignoring mirror %s (due to previous errors)\n", ipaddr); |
|
193 |
+ else |
|
194 |
+ logg("Ignoring mirror %s (too often connections with outdated version)\n", ipaddr); |
|
195 |
+ continue; |
|
196 |
+ } |
|
197 |
+ |
|
190 | 198 |
if(ip) |
191 | 199 |
strcpy(ip, ipaddr); |
192 | 200 |
|
... | ... |
@@ -204,6 +213,7 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip |
204 | 204 |
logg("Can't connect to port %d of host %s (IP: %s)\n", port, hostpt, ipaddr); |
205 | 205 |
continue; |
206 | 206 |
} else { |
207 |
+ mdat->currip = ((struct in_addr *) ia)->s_addr; |
|
207 | 208 |
return socketfd; |
208 | 209 |
} |
209 | 210 |
} |
... | ... |
@@ -288,7 +298,7 @@ static char *proxyauth(const char *user, const char *pass) |
288 | 288 |
return auth; |
289 | 289 |
} |
290 | 290 |
|
291 |
-static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int *ims, int ctimeout, int rtimeout) |
|
291 |
+static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, unsigned int *ims, int ctimeout, int rtimeout, struct mirdat *mdat) |
|
292 | 292 |
{ |
293 | 293 |
char cmd[512], head[513], buffer[FILEBUFF], ipaddr[16], *ch, *tmp; |
294 | 294 |
int bread, cnt, sd; |
... | ... |
@@ -352,9 +362,9 @@ static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, cha |
352 | 352 |
memset(ipaddr, 0, sizeof(ipaddr)); |
353 | 353 |
|
354 | 354 |
if(ip[0]) /* use ip to connect */ |
355 |
- sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout); |
|
355 |
+ sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout, mdat); |
|
356 | 356 |
else |
357 |
- sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout); |
|
357 |
+ sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout, mdat); |
|
358 | 358 |
|
359 | 359 |
if(sd < 0) { |
360 | 360 |
return NULL; |
... | ... |
@@ -388,11 +398,13 @@ static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, cha |
388 | 388 |
|
389 | 389 |
if(bread == -1) { |
390 | 390 |
logg("!remote_cvdhead: Error while reading CVD header from %s\n", hostname); |
391 |
+ mirman_update(mdat->currip, mdat, 1); |
|
391 | 392 |
return NULL; |
392 | 393 |
} |
393 | 394 |
|
394 | 395 |
if((strstr(buffer, "HTTP/1.1 404")) != NULL || (strstr(buffer, "HTTP/1.0 404")) != NULL) { |
395 | 396 |
logg("!CVD file not found on remote server\n"); |
397 |
+ mirman_update(mdat->currip, mdat, 1); |
|
396 | 398 |
return NULL; |
397 | 399 |
} |
398 | 400 |
|
... | ... |
@@ -400,6 +412,7 @@ static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, cha |
400 | 400 |
if((strstr(buffer, "HTTP/1.1 304")) != NULL || (strstr(buffer, "HTTP/1.0 304")) != NULL) { |
401 | 401 |
*ims = 0; |
402 | 402 |
logg("OK (IMS)\n"); |
403 |
+ mirman_update(mdat->currip, mdat, 0); |
|
403 | 404 |
return NULL; |
404 | 405 |
} else { |
405 | 406 |
*ims = 1; |
... | ... |
@@ -408,6 +421,7 @@ static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, cha |
408 | 408 |
if(!strstr(buffer, "HTTP/1.1 200") && !strstr(buffer, "HTTP/1.0 200") && |
409 | 409 |
!strstr(buffer, "HTTP/1.1 206") && !strstr(buffer, "HTTP/1.0 206")) { |
410 | 410 |
logg("!Unknown response from remote server\n"); |
411 |
+ mirman_update(mdat->currip, mdat, 1); |
|
411 | 412 |
return NULL; |
412 | 413 |
} |
413 | 414 |
|
... | ... |
@@ -425,6 +439,7 @@ static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, cha |
425 | 425 |
|
426 | 426 |
if(sizeof(buffer) - i < 512) { |
427 | 427 |
logg("!remote_cvdhead: Malformed CVD header (too short)\n"); |
428 |
+ mirman_update(mdat->currip, mdat, 1); |
|
428 | 429 |
return NULL; |
429 | 430 |
} |
430 | 431 |
|
... | ... |
@@ -433,20 +448,24 @@ static struct cl_cvd *remote_cvdhead(const char *file, const char *hostname, cha |
433 | 433 |
for(j = 0; j < 512; j++) { |
434 | 434 |
if(!ch || (ch && !*ch) || (ch && !isprint(ch[j]))) { |
435 | 435 |
logg("!remote_cvdhead: Malformed CVD header (bad chars)\n"); |
436 |
+ mirman_update(mdat->currip, mdat, 1); |
|
436 | 437 |
return NULL; |
437 | 438 |
} |
438 | 439 |
head[j] = ch[j]; |
439 | 440 |
} |
440 | 441 |
|
441 |
- if(!(cvd = cl_cvdparse(head))) |
|
442 |
- logg("!Malformed CVD header (can't parser)\n"); |
|
443 |
- else |
|
442 |
+ if(!(cvd = cl_cvdparse(head))) { |
|
443 |
+ logg("!Malformed CVD header (can't parse)\n"); |
|
444 |
+ mirman_update(mdat->currip, mdat, 1); |
|
445 |
+ } else { |
|
444 | 446 |
logg("OK\n"); |
447 |
+ mirman_update(mdat->currip, mdat, 0); |
|
448 |
+ } |
|
445 | 449 |
|
446 | 450 |
return cvd; |
447 | 451 |
} |
448 | 452 |
|
449 |
-static int getfile(const char *srcfile, const char *destfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout) |
|
453 |
+static int getfile(const char *srcfile, const char *destfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat) |
|
450 | 454 |
{ |
451 | 455 |
char cmd[512], buffer[FILEBUFF], *ch; |
452 | 456 |
int bread, fd, totalsize = 0, rot = 0, totaldownloaded = 0, |
... | ... |
@@ -493,9 +512,9 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
493 | 493 |
memset(ipaddr, 0, sizeof(ipaddr)); |
494 | 494 |
|
495 | 495 |
if(ip[0]) /* use ip to connect */ |
496 |
- sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout); |
|
496 |
+ sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout, mdat); |
|
497 | 497 |
else |
498 |
- sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout); |
|
498 |
+ sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout, mdat); |
|
499 | 499 |
|
500 | 500 |
if(sd < 0) { |
501 | 501 |
return 52; |
... | ... |
@@ -527,7 +546,8 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
527 | 527 |
#else |
528 | 528 |
if((i >= sizeof(buffer) - 1) || recv(sd, buffer + i, 1, 0) == -1) { |
529 | 529 |
#endif |
530 |
- logg("!getfile: Error while reading database from %s\n", hostname); |
|
530 |
+ logg("!getfile: Error while reading database from %s (IP: %s)\n", hostname, ipaddr); |
|
531 |
+ mirman_update(mdat->currip, mdat, 1); |
|
531 | 532 |
return 52; |
532 | 533 |
} |
533 | 534 |
|
... | ... |
@@ -543,14 +563,16 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
543 | 543 |
|
544 | 544 |
/* check whether the resource actually existed or not */ |
545 | 545 |
if((strstr(buffer, "HTTP/1.1 404")) != NULL || (strstr(buffer, "HTTP/1.0 404")) != NULL) { |
546 |
- logg("!getfile: %s not found on remote server\n", srcfile); |
|
546 |
+ logg("!getfile: %s not found on remote server (IP: %s)\n", srcfile, ipaddr); |
|
547 |
+ mirman_update(mdat->currip, mdat, 1); |
|
547 | 548 |
close(sd); |
548 | 549 |
return 58; |
549 | 550 |
} |
550 | 551 |
|
551 | 552 |
if(!strstr(buffer, "HTTP/1.1 200") && !strstr(buffer, "HTTP/1.0 200") && |
552 | 553 |
!strstr(buffer, "HTTP/1.1 206") && !strstr(buffer, "HTTP/1.0 206")) { |
553 |
- logg("!getfile: Unknown response from remote server\n"); |
|
554 |
+ logg("!getfile: Unknown response from remote server (IP: %s)\n", ipaddr); |
|
555 |
+ mirman_update(mdat->currip, mdat, 1); |
|
554 | 556 |
return 58; |
555 | 557 |
} |
556 | 558 |
|
... | ... |
@@ -611,10 +633,11 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna |
611 | 611 |
else |
612 | 612 |
logg("Downloading %s [*]\n", srcfile); |
613 | 613 |
|
614 |
+ mirman_update(mdat->currip, mdat, 0); |
|
614 | 615 |
return 0; |
615 | 616 |
} |
616 | 617 |
|
617 |
-static int getcvd(const char *dbfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int nodb, int newver, int ctimeout, int rtimeout) |
|
618 |
+static int getcvd(const char *dbfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int nodb, unsigned int newver, int ctimeout, int rtimeout, struct mirdat *mdat) |
|
618 | 619 |
{ |
619 | 620 |
char *tempname; |
620 | 621 |
struct cl_cvd *cvd; |
... | ... |
@@ -624,8 +647,8 @@ static int getcvd(const char *dbfile, const char *hostname, char *ip, const char |
624 | 624 |
tempname = cli_gentemp("."); |
625 | 625 |
|
626 | 626 |
logg("*Retrieving http://%s/%s\n", hostname, dbfile); |
627 |
- if((ret = getfile(dbfile, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout))) { |
|
628 |
- logg("!Can't download %s from %s (IP: %s)\n", dbfile, hostname, ip); |
|
627 |
+ if((ret = getfile(dbfile, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat))) { |
|
628 |
+ logg("!Can't download %s from %s\n", dbfile, hostname); |
|
629 | 629 |
unlink(tempname); |
630 | 630 |
free(tempname); |
631 | 631 |
return ret; |
... | ... |
@@ -704,7 +727,7 @@ static int chdir_inc(const char *dbname) |
704 | 704 |
return 0; |
705 | 705 |
} |
706 | 706 |
|
707 |
-static int getpatch(const char *dbname, int version, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout) |
|
707 |
+static int getpatch(const char *dbname, int version, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat) |
|
708 | 708 |
{ |
709 | 709 |
char *tempname, patch[32], olddir[512]; |
710 | 710 |
int ret, fd; |
... | ... |
@@ -722,8 +745,8 @@ static int getpatch(const char *dbname, int version, const char *hostname, char |
722 | 722 |
snprintf(patch, sizeof(patch), "%s-%d.cdiff", dbname, version); |
723 | 723 |
|
724 | 724 |
logg("*Retrieving http://%s/%s\n", hostname, patch); |
725 |
- if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout))) { |
|
726 |
- logg("!getpatch: Can't download %s from %s (IP: %s)\n", patch, hostname, ip); |
|
725 |
+ if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat))) { |
|
726 |
+ logg("!getpatch: Can't download %s from %s\n", patch, hostname); |
|
727 | 727 |
unlink(tempname); |
728 | 728 |
free(tempname); |
729 | 729 |
chdir(olddir); |
... | ... |
@@ -775,7 +798,7 @@ static struct cl_cvd *currentdb(const char *dbname, unsigned int *inc) |
775 | 775 |
return cvd; |
776 | 776 |
} |
777 | 777 |
|
778 |
-int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, const struct cfgstruct *copt, const char *dnsreply, char *localip, int outdated) |
|
778 |
+static int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, const struct cfgstruct *copt, const char *dnsreply, char *localip, int outdated, struct mirdat *mdat) |
|
779 | 779 |
{ |
780 | 780 |
struct cl_cvd *current, *remote; |
781 | 781 |
struct cfgstruct *cpt; |
... | ... |
@@ -809,6 +832,8 @@ int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, con |
809 | 809 |
} |
810 | 810 |
} |
811 | 811 |
} |
812 |
+ } else { |
|
813 |
+ mdat->dbflevel = current->fl; |
|
812 | 814 |
} |
813 | 815 |
|
814 | 816 |
if(!nodb && dnsreply) { |
... | ... |
@@ -869,7 +894,7 @@ int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, con |
869 | 869 |
|
870 | 870 |
if(!nodb && !newver) { |
871 | 871 |
|
872 |
- remote = remote_cvdhead(dbfile, hostname, ip, localip, proxy, port, user, pass, uas, &ims, ctimeout, rtimeout); |
|
872 |
+ remote = remote_cvdhead(dbfile, hostname, ip, localip, proxy, port, user, pass, uas, &ims, ctimeout, rtimeout, mdat); |
|
873 | 873 |
|
874 | 874 |
if(!nodb && !ims) { |
875 | 875 |
logg("%s is up to date (version: %d, sigs: %d, f-level: %d, builder: %s)\n", inc ? dbinc : dbfile, current->version, current->sigs, current->fl, current->builder); |
... | ... |
@@ -928,7 +953,7 @@ int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, con |
928 | 928 |
*/ |
929 | 929 |
|
930 | 930 |
if(nodb) { |
931 |
- ret = getcvd(dbfile, hostname, ip, localip, proxy, port, user, pass, uas, nodb, newver, ctimeout, rtimeout); |
|
931 |
+ ret = getcvd(dbfile, hostname, ip, localip, proxy, port, user, pass, uas, nodb, newver, ctimeout, rtimeout, mdat); |
|
932 | 932 |
if(ret) |
933 | 933 |
return ret; |
934 | 934 |
|
... | ... |
@@ -940,7 +965,7 @@ int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, con |
940 | 940 |
* !!! FIXME !!!: Redesign this code to make more than one attempt |
941 | 941 |
* to download a single cdiff. |
942 | 942 |
*/ |
943 |
- ret = getpatch(dbname, i, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout); |
|
943 |
+ ret = getpatch(dbname, i, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat); |
|
944 | 944 |
if(ret) { |
945 | 945 |
logg("^Removing incremental directory %s\n", dbinc); |
946 | 946 |
rmdirs(dbinc); |
... | ... |
@@ -951,7 +976,7 @@ int updatedb(const char *dbname, const char *hostname, char *ip, int *signo, con |
951 | 951 |
if(ret) { |
952 | 952 |
logg("^Incremental update failed, downloading complete database\n"); |
953 | 953 |
|
954 |
- ret = getcvd(dbfile, hostname, ip, localip, proxy, port, user, pass, uas, 1, newver, ctimeout, rtimeout); |
|
954 |
+ ret = getcvd(dbfile, hostname, ip, localip, proxy, port, user, pass, uas, 1, newver, ctimeout, rtimeout, mdat); |
|
955 | 955 |
if(ret) |
956 | 956 |
return ret; |
957 | 957 |
} else { |
... | ... |
@@ -986,6 +1011,7 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c |
986 | 986 |
char ipaddr[16], *dnsreply = NULL, *pt, *localip = NULL, *newver = NULL; |
987 | 987 |
const char *arg = NULL; |
988 | 988 |
struct cfgstruct *cpt; |
989 |
+ struct mirdat mdat; |
|
989 | 990 |
#ifdef HAVE_RESOLV_H |
990 | 991 |
const char *dnsdbinfo; |
991 | 992 |
#endif |
... | ... |
@@ -1069,28 +1095,32 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c |
1069 | 1069 |
localip = cpt->strarg; |
1070 | 1070 |
} |
1071 | 1071 |
|
1072 |
+ mirman_read("mirrors.dat", &mdat); |
|
1073 |
+ |
|
1072 | 1074 |
memset(ipaddr, 0, sizeof(ipaddr)); |
1073 | 1075 |
|
1074 |
- if((ret = updatedb("main", hostname, ipaddr, &signo, copt, dnsreply, localip, outdated)) > 50) { |
|
1076 |
+ if((ret = updatedb("main", hostname, ipaddr, &signo, copt, dnsreply, localip, outdated, &mdat)) > 50) { |
|
1075 | 1077 |
if(dnsreply) |
1076 | 1078 |
free(dnsreply); |
1077 | 1079 |
|
1078 | 1080 |
if(newver) |
1079 | 1081 |
free(newver); |
1080 | 1082 |
|
1083 |
+ mirman_write("mirrors.dat", &mdat); |
|
1081 | 1084 |
return ret; |
1082 | 1085 |
|
1083 | 1086 |
} else if(ret == 0) |
1084 | 1087 |
updated = 1; |
1085 | 1088 |
|
1086 | 1089 |
/* if ipaddr[0] != 0 it will use it to connect to the web host */ |
1087 |
- if((ret = updatedb("daily", hostname, ipaddr, &signo, copt, dnsreply, localip, outdated)) > 50) { |
|
1090 |
+ if((ret = updatedb("daily", hostname, ipaddr, &signo, copt, dnsreply, localip, outdated, &mdat)) > 50) { |
|
1088 | 1091 |
if(dnsreply) |
1089 | 1092 |
free(dnsreply); |
1090 | 1093 |
|
1091 | 1094 |
if(newver) |
1092 | 1095 |
free(newver); |
1093 | 1096 |
|
1097 |
+ mirman_write("mirrors.dat", &mdat); |
|
1094 | 1098 |
return ret; |
1095 | 1099 |
|
1096 | 1100 |
} else if(ret == 0) |
... | ... |
@@ -1099,6 +1129,8 @@ int downloadmanager(const struct cfgstruct *copt, const struct optstruct *opt, c |
1099 | 1099 |
if(dnsreply) |
1100 | 1100 |
free(dnsreply); |
1101 | 1101 |
|
1102 |
+ mirman_write("mirrors.dat", &mdat); |
|
1103 |
+ |
|
1102 | 1104 |
if(updated) { |
1103 | 1105 |
if(cfgopt(copt, "HTTPProxyServer")->enabled) { |
1104 | 1106 |
logg("Database updated (%d signatures) from %s\n", signo, hostname); |
1105 | 1107 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,208 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2007 Tomasz Kojm <tkojm@clamav.net> |
|
2 |
+ * |
|
3 |
+ * This program is free software; you can redistribute it and/or modify |
|
4 |
+ * it under the terms of the GNU General Public License version 2 as |
|
5 |
+ * published by the Free Software Foundation. |
|
6 |
+ * |
|
7 |
+ * This program is distributed in the hope that it will be useful, |
|
8 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 |
+ * GNU General Public License for more details. |
|
11 |
+ * |
|
12 |
+ * You should have received a copy of the GNU General Public License |
|
13 |
+ * along with this program; if not, write to the Free Software |
|
14 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
15 |
+ * MA 02110-1301, USA. |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#if HAVE_CONFIG_H |
|
19 |
+#include "clamav-config.h" |
|
20 |
+#endif |
|
21 |
+ |
|
22 |
+#include <stdio.h> |
|
23 |
+#include <string.h> |
|
24 |
+#include <stdlib.h> |
|
25 |
+#ifdef HAVE_UNISTD_H |
|
26 |
+#include <unistd.h> |
|
27 |
+#endif |
|
28 |
+#include <sys/types.h> |
|
29 |
+#include <sys/stat.h> |
|
30 |
+#include <fcntl.h> |
|
31 |
+#include <time.h> |
|
32 |
+ |
|
33 |
+#include "mirman.h" |
|
34 |
+ |
|
35 |
+#include "libclamav/cltypes.h" |
|
36 |
+#include "libclamav/clamav.h" |
|
37 |
+ |
|
38 |
+#include "shared/output.h" |
|
39 |
+ |
|
40 |
+#ifndef O_BINARY |
|
41 |
+#define O_BINARY 0 |
|
42 |
+#endif |
|
43 |
+ |
|
44 |
+#define IGNTIME 3 * 86400 |
|
45 |
+ |
|
46 |
+void mirman_free(struct mirdat *mdat) |
|
47 |
+{ |
|
48 |
+ if(mdat && mdat->num) { |
|
49 |
+ free(mdat->mirtab); |
|
50 |
+ mdat->num = 0; |
|
51 |
+ } |
|
52 |
+} |
|
53 |
+ |
|
54 |
+int mirman_read(const char *file, struct mirdat *mdat) |
|
55 |
+{ |
|
56 |
+ struct mirdat_ip mip; |
|
57 |
+ int fd, bread; |
|
58 |
+ |
|
59 |
+ |
|
60 |
+ memset(mdat, 0, sizeof(struct mirdat)); |
|
61 |
+ |
|
62 |
+ if((fd = open(file, O_RDONLY|O_BINARY)) == -1) |
|
63 |
+ return -1; |
|
64 |
+ |
|
65 |
+ while((bread = read(fd, &mip, sizeof(mip))) == sizeof(mip)) { |
|
66 |
+ mdat->mirtab = (struct mirdat_ip *) realloc(mdat->mirtab, (mdat->num + 1) * sizeof(mip)); |
|
67 |
+ if(!mdat->mirtab) { |
|
68 |
+ logg("!Can't allocate memory for mdat->mirtab\n"); |
|
69 |
+ mirman_free(mdat); |
|
70 |
+ close(fd); |
|
71 |
+ return -1; |
|
72 |
+ } |
|
73 |
+ memcpy(&mdat->mirtab[mdat->num], &mip, sizeof(mip)); |
|
74 |
+ mdat->num++; |
|
75 |
+ } |
|
76 |
+ |
|
77 |
+ close(fd); |
|
78 |
+ |
|
79 |
+ if(bread) { |
|
80 |
+ logg("^Removing broken %s file.\n"); |
|
81 |
+ unlink(file); |
|
82 |
+ mirman_free(mdat); |
|
83 |
+ return -1; |
|
84 |
+ } |
|
85 |
+ |
|
86 |
+ return 0; |
|
87 |
+} |
|
88 |
+ |
|
89 |
+int mirman_check(uint32_t ip, struct mirdat *mdat) |
|
90 |
+{ |
|
91 |
+ unsigned int i, flevel = cl_retflevel(); |
|
92 |
+ |
|
93 |
+ |
|
94 |
+ for(i = 0; i < mdat->num; i++) { |
|
95 |
+ if(mdat->mirtab[i].ip == ip) { |
|
96 |
+ |
|
97 |
+ if(mdat->dbflevel && (mdat->dbflevel > flevel) && (mdat->dbflevel - flevel > 3)) |
|
98 |
+ if(time(NULL) - mdat->mirtab[i].atime < 4 * 3600) |
|
99 |
+ return 2; |
|
100 |
+ |
|
101 |
+ if(mdat->mirtab[i].ignore) { |
|
102 |
+ if(time(NULL) - mdat->mirtab[i].atime > IGNTIME) { |
|
103 |
+ mdat->mirtab[i].ignore = 0; |
|
104 |
+ return 0; |
|
105 |
+ } else { |
|
106 |
+ return 1; |
|
107 |
+ } |
|
108 |
+ } |
|
109 |
+ } |
|
110 |
+ } |
|
111 |
+ |
|
112 |
+ return 0; |
|
113 |
+} |
|
114 |
+ |
|
115 |
+int mirman_update(uint32_t ip, struct mirdat *mdat, uint8_t broken) |
|
116 |
+{ |
|
117 |
+ unsigned int i, found = 0; |
|
118 |
+ |
|
119 |
+ |
|
120 |
+ for(i = 0; i < mdat->num; i++) { |
|
121 |
+ if(mdat->mirtab[i].ip == ip) { |
|
122 |
+ found = 1; |
|
123 |
+ break; |
|
124 |
+ } |
|
125 |
+ } |
|
126 |
+ |
|
127 |
+ if(found) { |
|
128 |
+ mdat->mirtab[i].atime = (uint32_t) time(NULL); |
|
129 |
+ if(broken) |
|
130 |
+ mdat->mirtab[i].fail++; |
|
131 |
+ else |
|
132 |
+ mdat->mirtab[i].succ++; |
|
133 |
+ |
|
134 |
+ /* |
|
135 |
+ * If the total number of failures is less than 3 then never |
|
136 |
+ * enable the ignore flag, in other case use the real status. |
|
137 |
+ */ |
|
138 |
+ if(mdat->mirtab[i].fail < 3) |
|
139 |
+ mdat->mirtab[i].ignore = 0; |
|
140 |
+ else |
|
141 |
+ mdat->mirtab[i].ignore = broken; |
|
142 |
+ |
|
143 |
+ } else { |
|
144 |
+ mdat->mirtab = (struct mirdat_ip *) realloc(mdat->mirtab, (mdat->num + 1) * sizeof(struct mirdat_ip)); |
|
145 |
+ if(!mdat->mirtab) { |
|
146 |
+ logg("!Can't allocate memory for new element in mdat->mirtab\n"); |
|
147 |
+ return -1; |
|
148 |
+ } |
|
149 |
+ mdat->mirtab[mdat->num].ip = ip; |
|
150 |
+ mdat->mirtab[mdat->num].atime = (uint32_t) time(NULL); |
|
151 |
+ mdat->mirtab[mdat->num].succ = 0; |
|
152 |
+ mdat->mirtab[mdat->num].fail = 0; |
|
153 |
+ mdat->mirtab[mdat->num].ignore = 0; |
|
154 |
+ memset(&mdat->mirtab[mdat->num].res, 0xff, sizeof(mdat->mirtab[mdat->num].res)); |
|
155 |
+ if(broken) |
|
156 |
+ mdat->mirtab[mdat->num].fail++; |
|
157 |
+ else |
|
158 |
+ mdat->mirtab[mdat->num].succ++; |
|
159 |
+ mdat->num++; |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ return 0; |
|
163 |
+} |
|
164 |
+ |
|
165 |
+void mirman_list(const struct mirdat *mdat) |
|
166 |
+{ |
|
167 |
+ unsigned int i; |
|
168 |
+ unsigned char *ip; |
|
169 |
+ |
|
170 |
+ for(i = 0; i < mdat->num; i++) { |
|
171 |
+ printf("Mirror #%u\n", i + 1); |
|
172 |
+ ip = (unsigned char *) &mdat->mirtab[i].ip; |
|
173 |
+ printf("IP: %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]); |
|
174 |
+ printf("Successes: %u\n", mdat->mirtab[i].succ); |
|
175 |
+ printf("Failures: %u\n", mdat->mirtab[i].fail); |
|
176 |
+ printf("Last access: %s", ctime((time_t *) &mdat->mirtab[i].atime)); |
|
177 |
+ printf("Ignore: %s\n", mdat->mirtab[i].ignore ? "Yes" : "No"); |
|
178 |
+ if(i != mdat->num - 1) |
|
179 |
+ printf("-------------------------------------\n"); |
|
180 |
+ } |
|
181 |
+} |
|
182 |
+ |
|
183 |
+int mirman_write(const char *file, struct mirdat *mdat) |
|
184 |
+{ |
|
185 |
+ int fd; |
|
186 |
+ |
|
187 |
+ |
|
188 |
+ if(!mdat->num) |
|
189 |
+ return 0; |
|
190 |
+ |
|
191 |
+ if((fd = open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) == -1) { |
|
192 |
+ logg("!Can't open %s for writing\n", file); |
|
193 |
+ mirman_free(mdat); |
|
194 |
+ return -1; |
|
195 |
+ } |
|
196 |
+ |
|
197 |
+ if(write(fd, mdat->mirtab, mdat->num * sizeof(struct mirdat_ip)) == -1) { |
|
198 |
+ logg("!Can't write to %s\n", file); |
|
199 |
+ mirman_free(mdat); |
|
200 |
+ close(fd); |
|
201 |
+ return -1; |
|
202 |
+ } |
|
203 |
+ |
|
204 |
+ mirman_free(mdat); |
|
205 |
+ close(fd); |
|
206 |
+ return 0; |
|
207 |
+} |
0 | 208 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,47 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2007 Tomasz Kojm <tkojm@clamav.net> |
|
2 |
+ * |
|
3 |
+ * This program is free software; you can redistribute it and/or modify |
|
4 |
+ * it under the terms of the GNU General Public License version 2 as |
|
5 |
+ * published by the Free Software Foundation. |
|
6 |
+ * |
|
7 |
+ * This program is distributed in the hope that it will be useful, |
|
8 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 |
+ * GNU General Public License for more details. |
|
11 |
+ * |
|
12 |
+ * You should have received a copy of the GNU General Public License |
|
13 |
+ * along with this program; if not, write to the Free Software |
|
14 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
15 |
+ * MA 02110-1301, USA. |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#ifndef __MIRMAN_H |
|
19 |
+#define __MIRMAN_H |
|
20 |
+ |
|
21 |
+#include "libclamav/cltypes.h" |
|
22 |
+ |
|
23 |
+struct mirdat_ip { |
|
24 |
+ uint32_t ip; /* IP address */ |
|
25 |
+ uint32_t atime; /* last access time */ |
|
26 |
+ uint32_t succ; /* number of successful downloads from this ip */ |
|
27 |
+ uint32_t fail; /* number of failures */ |
|
28 |
+ uint8_t ignore; /* ignore flag */ |
|
29 |
+ char res[32]; /* reserved */ |
|
30 |
+}; |
|
31 |
+ |
|
32 |
+struct mirdat { |
|
33 |
+ unsigned int num; |
|
34 |
+ uint32_t currip; |
|
35 |
+ uint32_t dbflevel; |
|
36 |
+ struct mirdat_ip *mirtab; |
|
37 |
+}; |
|
38 |
+ |
|
39 |
+int mirman_read(const char *file, struct mirdat *mdat); |
|
40 |
+int mirman_check(uint32_t ip, struct mirdat *mdat); |
|
41 |
+int mirman_update(uint32_t ip, struct mirdat *mdat, uint8_t broken); |
|
42 |
+void mirman_list(const struct mirdat *mdat); |
|
43 |
+int mirman_write(const char *file, struct mirdat *mdat); |
|
44 |
+void mirman_free(struct mirdat *mdat); |
|
45 |
+ |
|
46 |
+#endif |