Browse code

FreshClam: Allow for slightly out-of-date mirrors

After the previous improvements, there is still an issue wherein a
private database mirror may not yet have the very latest CVD and CDIFF.
In this case, and if the clients are still using the official DNS server
to check the latest versions, then the clients will try several times to
update with CDIFFs before downloading the entire CVD. This is clearly
not desirable, especially because that CVD is probably also 1 version
older than expected.

This commit keeps track of the number of patches and will only ask for
the CVD after the patches failed if no patches were downloaded AND we're
more than 1 version behind. What that means is that if we're 1 version
behind and the server is too -- it will log some warnings but succeed.
Or if we are multple versions behind but we did get some patches, we'll
settle for a minor update.

This change will essentially allow FreshClam to be used with private
mirrors that aren't updated the second a new daily database is
published. Without this change, private mirror operators may end up
frequently serving the entire daily CVD to fussy FreshClam clients.

Micah Snyder authored on 2021/04/03 12:59:13
Showing 1 changed files
... ...
@@ -1596,7 +1596,7 @@ static fc_error_t downloadPatch(
1596 1596
         if (ret == FC_EEMPTYFILE) {
1597 1597
             logg("Empty script %s, need to download entire database\n", patch);
1598 1598
         } else {
1599
-            logg("%cgetpatch: Can't download %s from %s\n", logerr ? '!' : '^', patch, url);
1599
+            logg("%cdownloadPatch: Can't download %s from %s\n", logerr ? '!' : '^', patch, url);
1600 1600
         }
1601 1601
         status = ret;
1602 1602
         goto done;
... ...
@@ -2263,7 +2263,8 @@ fc_error_t updatedb(
2263 2263
         /*
2264 2264
          * Attempt scripted/CDIFF incremental update.
2265 2265
          */
2266
-        ret = FC_SUCCESS;
2266
+        ret                         = FC_SUCCESS;
2267
+        uint32_t numPatchesReceived = 0;
2267 2268
 
2268 2269
         tmpdir = cli_gentemp(g_tempDirectory);
2269 2270
         if (!tmpdir) {
... ...
@@ -2304,11 +2305,19 @@ fc_error_t updatedb(
2304 2304
                     break;
2305 2305
                 }
2306 2306
             }
2307
-            if (FC_SUCCESS != ret)
2307
+            if (FC_SUCCESS == ret) {
2308
+                numPatchesReceived += 1;
2309
+            } else {
2308 2310
                 break;
2311
+            }
2309 2312
         }
2310 2313
 
2311
-        if (FC_SUCCESS != ret) {
2314
+        if (
2315
+            (FC_EEMPTYFILE == ret) ||                                 /* Request a new CVD if we got an empty CDIFF.      */
2316
+            (FC_SUCCESS != ret && (                                   /* Or if the incremental update failed:             */
2317
+                                   (0 == numPatchesReceived) &&       /* 1. Ask for the CVD if we didn't get any patches, */
2318
+                                   (localVersion < remoteVersion - 1) /* 2. AND if we're more than 1 version out of date. */
2319
+                                   ))) {
2312 2320
             /*
2313 2321
              * Incremental update failed or intentionally disabled.
2314 2322
              */
... ...
@@ -2334,10 +2343,18 @@ fc_error_t updatedb(
2334 2334
             }
2335 2335
 
2336 2336
             newLocalFilename = cli_strdup(remoteFilename);
2337
+        } else if (0 == numPatchesReceived) {
2338
+            logg("The database server doesn't have the latest patch for the %s database (version %u). The server will likely have updated if you check again in a few hours.\n", database, remoteVersion);
2339
+            goto up_to_date;
2337 2340
         } else {
2338 2341
             /*
2339 2342
              * CDIFFs downloaded; Use CDIFFs to turn old CVD/CLD into new updated CLD.
2340 2343
              */
2344
+            if (numPatchesReceived < remoteVersion - localVersion) {
2345
+                logg("Downloaded %u patches for %s, which is fewer than the %u expected patches.\n", numPatchesReceived, database, remoteVersion - localVersion);
2346
+                logg("We'll settle for this partial-update, at least for now.\n");
2347
+            }
2348
+
2341 2349
             size_t newLocalFilenameLen = 0;
2342 2350
             if (FC_SUCCESS != buildcld(tmpdir, database, tmpfile, g_bCompressLocalDatabase)) {
2343 2351
                 logg("!updatedb: Incremental update failed. Failed to build CLD.\n");