freshclam: improve mirror management

0.96
Tomasz Kojm 15 years ago
parent 027b853894
commit 090057005c
  1. 4
      ChangeLog
  2. 104
      freshclam/manager.c
  3. 78
      freshclam/mirman.c
  4. 3
      freshclam/mirman.h

@ -1,3 +1,7 @@
Mon Nov 15 16:04:31 CET 2010 (tk)
---------------------------------
* freshclam: improve mirror management
Fri Nov 12 15:47:09 CET 2010 (tk)
---------------------------------
* libclamav: fix possible use of uninitialized values (bb#2291)

@ -302,7 +302,7 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
loadbal_rp = rp;
strncpy(loadbal_ipaddr, ipaddr, sizeof(loadbal_ipaddr));
} else {
if(md->succ < minsucc && md->fail <= minfail) {
if(md->succ <= minsucc && md->fail <= minfail) {
minsucc = md->succ;
minfail = md->fail;
loadbal_rp = rp;
@ -324,7 +324,12 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
}
rp = loadbal_rp;
strncpy(ipaddr, loadbal_ipaddr, sizeof(ipaddr));
#ifdef SUPPORT_IPv6
if(rp->ai_family == AF_INET6)
addr = &((struct sockaddr_in6 *) rp->ai_addr)->sin6_addr;
else
#endif
addr = &((struct sockaddr_in *) rp->ai_addr)->sin_addr;
} else if(loadbal_rp == rp) {
i++;
continue;
@ -920,13 +925,13 @@ static struct cl_cvd *remote_cvdhead(const char *cvdfile, const char *localfile,
return cvd;
}
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, int logerr, unsigned int can_whitelist, const char *ims)
static int getfile_mirman(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, int logerr, unsigned int can_whitelist, const char *ims, const char *ipaddr, int sd)
{
char cmd[512], uastr[128], buffer[FILEBUFF], *ch;
int bread, fd, totalsize = 0, rot = 0, totaldownloaded = 0,
percentage = 0, sd;
percentage = 0;
unsigned int i;
char *remotename = NULL, *authorization = NULL, *headerline, ipaddr[46];
char *remotename = NULL, *authorization = NULL, *headerline;
const char *rotation = "|/-\\", *fname;
@ -973,24 +978,13 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
if(authorization)
free(authorization);
memset(ipaddr, 0, sizeof(ipaddr));
if(ip && ip[0]) /* use ip to connect */
sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
else
sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
if(sd < 0) {
return 52;
} else {
logg("*Trying to download http://%s/%s (IP: %s)\n", hostname, srcfile, ipaddr);
}
logg("*Trying to download http://%s/%s (IP: %s)\n", hostname, srcfile, ipaddr);
if(ip && !ip[0])
strcpy(ip, ipaddr);
if(send(sd, cmd, strlen(cmd), 0) < 0) {
logg("%cgetfile: Can't write to socket\n", logerr ? '!' : '^');
closesocket(sd);
return 52;
}
@ -1007,7 +1001,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
logg("%cgetfile: Error while reading database from %s (IP: %s): %s\n", logerr ? '!' : '^', hostname, ipaddr, strerror(errno));
if(mdat)
mirman_update(mdat->currip, mdat->af, mdat, 1);
closesocket(sd);
return 52;
}
@ -1026,7 +1019,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
logg("^getfile: %s not found on remote server (IP: %s)\n", srcfile, ipaddr);
if(mdat)
mirman_update(mdat->currip, mdat->af, mdat, 2);
closesocket(sd);
return 58;
}
@ -1034,7 +1026,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
if(strstr(buffer, "HTTP/1.1 304") || strstr(buffer, "HTTP/1.0 304")) {
if(mdat)
mirman_update(mdat->currip, mdat->af, mdat, 0);
closesocket(sd);
return 1;
}
@ -1043,7 +1034,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
logg("%cgetfile: Unknown response from remote server (IP: %s)\n", logerr ? '!' : '^', ipaddr);
if(mdat)
mirman_update(mdat->currip, mdat->af, mdat, 1);
closesocket(sd);
return 58;
}
@ -1069,7 +1059,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
logg("!getfile: Can't create new file %s in the current directory\n", destfile);
logg("Hint: The database directory must be writable for UID %d or GID %d\n", getuid(), getgid());
closesocket(sd);
return 57;
}
@ -1087,7 +1076,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
logg("getfile: Can't write %d bytes to %s\n", bread, destfile);
unlink(destfile);
close(fd);
closesocket(sd);
return 57; /* FIXME */
}
@ -1106,7 +1094,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
fflush(stdout);
}
}
closesocket(sd);
close(fd);
if(bread == -1) {
@ -1129,14 +1116,45 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
return 0;
}
static int getcvd(const char *cvdfile, const char *newfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, unsigned int newver, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist)
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, int logerr, unsigned int can_whitelist, const char *ims, const struct optstruct *opts)
{
int ret, sd;
char ipaddr[46];
memset(ipaddr, 0, sizeof(ipaddr));
if(ip && ip[0]) /* use ip to connect */
sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
else
sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
if(sd < 0)
return 52;
if(mdat) {
mirman_update_sf(mdat->currip, mdat->af, mdat, 0, 1);
mirman_write("mirrors.dat", optget(opts, "DatabaseDirectory")->strarg, mdat);
}
ret = getfile_mirman(srcfile, destfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, ims, ipaddr, sd);
closesocket(sd);
if(mdat) {
mirman_update_sf(mdat->currip, mdat->af, mdat, 0, -1);
mirman_write("mirrors.dat", optget(opts, "DatabaseDirectory")->strarg, mdat);
}
return ret;
}
static int getcvd(const char *cvdfile, const char *newfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, unsigned int newver, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist, const struct optstruct *opts)
{
struct cl_cvd *cvd;
int ret;
logg("*Retrieving http://%s/%s\n", hostname, cvdfile);
if((ret = getfile(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL))) {
if((ret = getfile(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL, opts))) {
logg("%cCan't download %s from %s\n", logerr ? '!' : '^', cvdfile, hostname);
unlink(newfile);
return ret;
@ -1201,7 +1219,7 @@ static int chdir_tmp(const char *dbname, const char *tmpdir)
return 0;
}
static int getpatch(const char *dbname, const char *tmpdir, 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, int logerr, unsigned int can_whitelist)
static int getpatch(const char *dbname, const char *tmpdir, 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, int logerr, unsigned int can_whitelist, const struct optstruct *opts)
{
char *tempname, patch[32], olddir[512];
int ret, fd;
@ -1219,7 +1237,7 @@ static int getpatch(const char *dbname, const char *tmpdir, int version, const c
snprintf(patch, sizeof(patch), "%s-%d.cdiff", dbname, version);
logg("*Retrieving http://%s/%s\n", hostname, patch);
if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL))) {
if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL, opts))) {
if(ret == 53)
logg("Empty script %s, need to download entire database\n", patch);
else
@ -1731,7 +1749,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
newfile = cli_gentemp(updtmpdir);
if(nodb) {
ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist);
ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist, opts);
if(ret) {
memset(ip, 0, 16);
free(newfile);
@ -1749,7 +1767,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
int llogerr = logerr;
if(logerr)
llogerr = (j == maxattempts - 1);
ret = getpatch(dbname, tmpdir, i, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, llogerr, can_whitelist);
ret = getpatch(dbname, tmpdir, i, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, llogerr, can_whitelist, opts);
if(ret == 52 || ret == 58) {
memset(ip, 0, 16);
continue;
@ -1767,7 +1785,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
if(ret != 53)
logg("^Incremental update failed, trying to download %s\n", cvdfile);
mirman_whitelist(mdat, 2);
ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist);
ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist, opts);
if(ret) {
free(newfile);
return ret;
@ -1925,7 +1943,7 @@ static int updatecustomdb(const char *url, int *signo, const struct optstruct *o
Rfc2822DateTime(mtime, sb.st_mtime);
newfile = cli_gentemp(updtmpdir);
ret = getfile(rpath, newfile, host, NULL, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, NULL, logerr, 0, *mtime ? mtime : NULL);
ret = getfile(rpath, newfile, host, NULL, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, NULL, logerr, 0, *mtime ? mtime : NULL, opts);
if(ret == 1) {
logg("%s is up to date (version: custom database)\n", dbname);
unlink(newfile);
@ -2138,7 +2156,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
if(newver)
free(newver);
mirman_write("mirrors.dat", &mdat);
mirman_write("mirrors.dat", dbdir, &mdat);
mirman_free(&mdat);
cli_rmdirs(updtmpdir);
return ret;
@ -2153,7 +2172,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
if(newver)
free(newver);
mirman_write("mirrors.dat", &mdat);
mirman_write("mirrors.dat", dbdir, &mdat);
mirman_free(&mdat);
cli_rmdirs(updtmpdir);
return ret;
@ -2182,7 +2202,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
if(newver)
free(newver);
mirman_write("mirrors.dat", &mdat);
mirman_write("mirrors.dat", dbdir, &mdat);
mirman_free(&mdat);
cli_rmdirs(updtmpdir);
return ret;
} else if(ret == 0)
@ -2209,7 +2230,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
if(newver)
free(newver);
mirman_write("mirrors.dat", &mdat);
mirman_write("mirrors.dat", dbdir, &mdat);
mirman_free(&mdat);
cli_rmdirs(updtmpdir);
return ret;
} else if(ret == 0)
@ -2223,7 +2245,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
if((ret = updatedb(opt->strarg, hostname, ipaddr, &signo, opts, NULL, localip, outdated, &mdat, logerr, 1)) > 50) {
if(newver)
free(newver);
mirman_write("mirrors.dat", &mdat);
mirman_write("mirrors.dat", dbdir, &mdat);
mirman_free(&mdat);
cli_rmdirs(updtmpdir);
return ret;
} else if(ret == 0)
@ -2232,6 +2255,10 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
}
}
mirman_write("mirrors.dat", dbdir, &mdat);
mirman_free(&mdat);
cli_rmdirs(updtmpdir);
/* custom dbs */
if((opt = optget(opts, "DatabaseCustomURL"))->enabled) {
while(opt) {
@ -2241,9 +2268,6 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
}
}
mirman_write("mirrors.dat", &mdat);
cli_rmdirs(updtmpdir);
if(updated) {
if(optget(opts, "HTTPProxyServer")->enabled || !ipaddr[0]) {
logg("Database updated (%d signatures) from %s\n", signo, hostname);

@ -152,7 +152,7 @@ int mirman_check(uint32_t *ip, int af, struct mirdat *mdat, struct mirdat_ip **m
return 0;
}
int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
static int mirman_update_int(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken, int succ, int fail)
{
unsigned int i, found = 0;
@ -169,24 +169,32 @@ int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
if(found) {
mdat->mirtab[i].atime = 0; /* will be updated in mirman_write() */
if(broken)
mdat->mirtab[i].fail++;
else
mdat->mirtab[i].succ++;
if(broken == 2) {
mdat->mirtab[i].ignore = 2;
if(succ || fail) {
mdat->mirtab[i].fail += fail;
if(mdat->mirtab[i].fail < 0)
mdat->mirtab[i].fail = 0;
mdat->mirtab[i].succ += succ;
if(mdat->mirtab[i].succ < 0)
mdat->mirtab[i].succ = 0;
} else {
/*
* If the total number of failures is less than 3 then never
* mark a permanent failure, in other case use the real status.
*/
if(mdat->mirtab[i].fail < 3)
mdat->mirtab[i].ignore = 0;
if(broken)
mdat->mirtab[i].fail++;
else
mdat->mirtab[i].ignore = broken;
mdat->mirtab[i].succ++;
if(broken == 2) {
mdat->mirtab[i].ignore = 2;
} else {
/*
* If the total number of failures is less than 3 then never
* mark a permanent failure, in other case use the real status.
*/
if(mdat->mirtab[i].fail < 3)
mdat->mirtab[i].ignore = 0;
else
mdat->mirtab[i].ignore = broken;
}
}
} else {
mdat->mirtab = (struct mirdat_ip *) realloc(mdat->mirtab, (mdat->num + 1) * sizeof(struct mirdat_ip));
if(!mdat->mirtab) {
@ -200,20 +208,32 @@ int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
memcpy(mdat->mirtab[mdat->num].ip6, ip, 4 * sizeof(uint32_t));
}
mdat->mirtab[mdat->num].atime = 0;
mdat->mirtab[mdat->num].succ = 0;
mdat->mirtab[mdat->num].fail = 0;
mdat->mirtab[mdat->num].succ = (succ > 0) ? succ : 0;
mdat->mirtab[mdat->num].fail = (fail > 0) ? fail : 0;
mdat->mirtab[mdat->num].ignore = (broken == 2) ? 2 : 0;
memset(&mdat->mirtab[mdat->num].res, 0xff, sizeof(mdat->mirtab[mdat->num].res));
if(broken)
mdat->mirtab[mdat->num].fail++;
else
mdat->mirtab[mdat->num].succ++;
if(!succ && !fail) {
if(broken)
mdat->mirtab[mdat->num].fail++;
else
mdat->mirtab[mdat->num].succ++;
}
mdat->num++;
}
return 0;
}
int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
{
return mirman_update_int(ip, af, mdat, broken, 0, 0);
}
int mirman_update_sf(uint32_t *ip, int af, struct mirdat *mdat, int succ, int fail)
{
return mirman_update_int(ip, af, mdat, 0, succ, fail);
}
void mirman_list(const struct mirdat *mdat)
{
unsigned int i;
@ -252,18 +272,20 @@ void mirman_whitelist(struct mirdat *mdat, unsigned int mode)
mdat->mirtab[i].ignore = 0;
}
int mirman_write(const char *file, struct mirdat *mdat)
int mirman_write(const char *file, const char *dir, struct mirdat *mdat)
{
int fd;
unsigned int i;
char path[512];
snprintf(path, sizeof(path), "%s/%s", dir, file);
path[sizeof(path) - 1] = 0;
if(!mdat->num)
return 0;
if((fd = open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) == -1) {
logg("!Can't open %s for writing\n", file);
mirman_free(mdat);
if((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) == -1) {
logg("!Can't open %s for writing\n", path);
return -1;
}
@ -272,13 +294,11 @@ int mirman_write(const char *file, struct mirdat *mdat)
mdat->mirtab[i].atime = (uint32_t) time(NULL);
if(write(fd, mdat->mirtab, mdat->num * sizeof(struct mirdat_ip)) == -1) {
logg("!Can't write to %s\n", file);
mirman_free(mdat);
logg("!Can't write to %s\n", path);
close(fd);
return -1;
}
mirman_free(mdat);
close(fd);
return 0;
}

@ -43,9 +43,10 @@ struct mirdat {
int mirman_read(const char *file, struct mirdat *mdat, uint8_t active);
int mirman_check(uint32_t *ip, int af, struct mirdat *mdat, struct mirdat_ip **md);
int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken);
int mirman_update_sf(uint32_t *ip, int af, struct mirdat *mdat, int succ, int fail);
void mirman_list(const struct mirdat *mdat);
void mirman_whitelist(struct mirdat *mdat, unsigned int mode);
int mirman_write(const char *file, struct mirdat *mdat);
int mirman_write(const char *file, const char *dir, struct mirdat *mdat);
void mirman_free(struct mirdat *mdat);
#endif

Loading…
Cancel
Save