Browse code

FreshClam mirror-sync issue: Keep & update again

If a new CVD download gets a version that is older than advertised, keep
the older version and retry the update so the incremental (CDIFF) update
gets us to the latest version.

Micah Snyder authored on 2021/03/23 05:36:02
Showing 2 changed files
... ...
@@ -657,9 +657,8 @@ fc_error_t fc_update_database(
657 657
                     break;
658 658
                 }
659 659
                 case FC_EMIRRORNOTSYNC: {
660
-                    logg("!Update failed for database: %s\n", database);
661
-                    status = ret;
662
-                    goto done;
660
+                    logg("Received an older %s CVD than was advertised. We'll retry so the incremental update will ensure we're up-to-date.\n", database);
661
+                    break;
663 662
                 }
664 663
                 case FC_EFORBIDDEN: {
665 664
                     logg("^FreshClam received error code 403 from the ClamAV Content Delivery Network (CDN).\n");
... ...
@@ -1401,24 +1401,11 @@ static fc_error_t getcvd(
1401 1401
     }
1402 1402
 
1403 1403
     if (cvd->version < remoteVersion) {
1404
-        if (cvd->version == remoteVersion - 1) {
1405
-            logg("*The %s database downloaded from %s is one version older than advertised in the DNS TXT record.\n",
1406
-                 cvdfile,
1407
-                 server);
1408
-
1409
-            /*
1410
-             * Tolerate an off-by-one version mismatch.
1411
-             * Chances are the new version was just published and the CDN is still updating.
1412
-             */
1413
-            status = FC_SUCCESS;
1414
-            goto done;
1415
-        } else {
1416
-            logg("!The %s database downloaded from %s is more than one version older than the version advertised in the DNS TXT record.\n",
1417
-                 cvdfile,
1418
-                 server);
1419
-            status = FC_EMIRRORNOTSYNC;
1420
-            goto done;
1421
-        }
1404
+        logg("*The %s database downloaded from %s is older than the version advertised in the DNS TXT record.\n",
1405
+             cvdfile,
1406
+             server);
1407
+        status = FC_EMIRRORNOTSYNC;
1408
+        goto done;
1422 1409
     }
1423 1410
 
1424 1411
     status = FC_SUCCESS;
... ...
@@ -1434,7 +1421,10 @@ done:
1434 1434
     if (NULL != url) {
1435 1435
         free(url);
1436 1436
     }
1437
-    if (FC_SUCCESS != status) {
1437
+    if (
1438
+        (FC_SUCCESS != status) &&
1439
+        (FC_EMIRRORNOTSYNC != status) /* Keep older version, it's better than nothing. */
1440
+    ) {
1438 1441
         if (NULL != tmpfile) {
1439 1442
             unlink(tmpfile);
1440 1443
         }
... ...
@@ -2222,6 +2212,12 @@ fc_error_t updatedb(
2222 2222
                 *dbFilename = cli_strdup(localFilename);
2223 2223
             }
2224 2224
             goto up_to_date;
2225
+        } else if (FC_EMIRRORNOTSYNC == ret) {
2226
+            /* Let's accept this older version, but keep the error code.
2227
+             * We'll have fc_update_database() retry using CDIFFs.
2228
+             */
2229
+            logg("*Received an older %s CVD than was advertised. We'll keep it and try updating to the latest version with CDIFFs.\n", database);
2230
+            status = ret;
2225 2231
         } else if (FC_SUCCESS != ret) {
2226 2232
             status = ret;
2227 2233
             goto done;
... ...
@@ -2289,8 +2285,17 @@ fc_error_t updatedb(
2289 2289
 
2290 2290
             ret = getcvd(remoteFilename, tmpfile, server, localTimestamp, remoteVersion, logerr);
2291 2291
             if (FC_SUCCESS != ret) {
2292
-                status = ret;
2293
-                goto done;
2292
+                if (FC_EMIRRORNOTSYNC == status) {
2293
+                    /* Note: We can't retry with CDIFF's if FC_EMIRRORNOTSYNC happened here.
2294
+                     * If we did there could be an infinite loop.
2295
+                     * Best option is to accept the older CVD.
2296
+                     */
2297
+                    logg("^Received an older %s CVD than was advertised. Incremental updates either failed or are disabled, so we'll have to settle for a slightly out-of-date database.\n", database);
2298
+                    status = FC_SUCCESS;
2299
+                } else {
2300
+                    status = ret;
2301
+                    goto done;
2302
+                }
2294 2303
             }
2295 2304
 
2296 2305
             newLocalFilename = cli_strdup(remoteFilename);
... ...
@@ -2394,7 +2399,9 @@ fc_error_t updatedb(
2394 2394
 
2395 2395
 up_to_date:
2396 2396
 
2397
-    status = FC_SUCCESS;
2397
+    if (status != FC_EMIRRORNOTSYNC) {
2398
+        status = FC_SUCCESS;
2399
+    }
2398 2400
 
2399 2401
 done:
2400 2402