Преглед изворни кода

Add GeoIP file digest to extra-info descriptor.

Karsten Loesing пре 13 година
родитељ
комит
423c2a7a27
5 измењених фајлова са 40 додато и 0 уклоњено
  1. 4 0
      changes/enhancement1883
  2. 6 0
      doc/spec/dir-spec.txt
  3. 18 0
      src/or/geoip.c
  4. 1 0
      src/or/geoip.h
  5. 11 0
      src/or/router.c

+ 4 - 0
changes/enhancement1883

@@ -0,0 +1,4 @@
+  o Minor features:
+    - Add GeoIP file digest to extra-info descriptor. Implements
+      enhancement 1883.
+

+ 6 - 0
doc/spec/dir-spec.txt

@@ -622,6 +622,12 @@
 
         As documented in 2.1 above.  See migration notes in section 2.2.1.
 
+    "geoip-db-digest" Digest NL
+        [At most once.]
+
+        SHA1 digest of the GeoIP database file that is used to resolve IP
+        addresses to country codes.
+
     ("geoip-start" YYYY-MM-DD HH:MM:SS NL)
     ("geoip-client-origins" CC=N,CC=N,... NL)
 

+ 18 - 0
src/or/geoip.c

@@ -44,6 +44,9 @@ static strmap_t *country_idxplus1_by_lc_code = NULL;
 /** A list of all known geoip_entry_t, sorted by ip_low. */
 static smartlist_t *geoip_entries = NULL;
 
+/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */
+static char geoip_digest[DIGEST_LEN];
+
 /** Return the index of the <b>country</b>'s entry in the GeoIP DB
  * if it is a valid 2-letter country code, otherwise return -1.
  */
@@ -201,6 +204,7 @@ geoip_load_file(const char *filename, or_options_t *options)
   FILE *f;
   const char *msg = "";
   int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO;
+  crypto_digest_env_t *geoip_digest_env = NULL;
   clear_geoip_db();
   if (!(f = fopen(filename, "r"))) {
     log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s.  %s",
@@ -214,11 +218,13 @@ geoip_load_file(const char *filename, or_options_t *options)
     smartlist_free(geoip_entries);
   }
   geoip_entries = smartlist_create();
+  geoip_digest_env = crypto_new_digest_env();
   log_notice(LD_GENERAL, "Parsing GEOIP file.");
   while (!feof(f)) {
     char buf[512];
     if (fgets(buf, (int)sizeof(buf), f) == NULL)
       break;
+    crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf));
     /* FFFF track full country name. */
     geoip_parse_entry(buf);
   }
@@ -231,6 +237,11 @@ geoip_load_file(const char *filename, or_options_t *options)
    * country. */
   refresh_all_country_info();
 
+  /* Remember file digest so that we can include it in our extra-info
+   * descriptors. */
+  crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN);
+  crypto_free_digest_env(geoip_digest_env);
+
   return 0;
 }
 
@@ -278,6 +289,13 @@ geoip_is_loaded(void)
   return geoip_countries != NULL && geoip_entries != NULL;
 }
 
+/** Return the hex-encoded SHA1 digest of the loaded GeoIP file. */
+const char *
+geoip_db_digest(void)
+{
+  return hex_str(geoip_digest, DIGEST_LEN);
+}
+
 /** Entry in a map from IP address to the last time we've seen an incoming
  * connection from that IP address. Used by bridges only, to track which
  * countries have them blocked. */

+ 1 - 0
src/or/geoip.h

@@ -21,6 +21,7 @@ int geoip_get_country_by_ip(uint32_t ipaddr);
 int geoip_get_n_countries(void);
 const char *geoip_get_country_name(country_t num);
 int geoip_is_loaded(void);
+const char *geoip_db_digest(void);
 country_t geoip_get_country(const char *countrycode);
 
 void geoip_note_client_seen(geoip_client_action_t action,

+ 11 - 0
src/or/router.c

@@ -2015,6 +2015,17 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
   if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
     char *contents = NULL;
     log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
+    if (geoip_is_loaded()) {
+      size_t pos = strlen(s);
+      if (tor_snprintf(s + pos, maxlen - strlen(s),
+                       "geoip-db-digest %s\n",
+                       geoip_db_digest()) < 0) {
+        log_warn(LD_DIR, "Could not write geoip-db-digest to extra-info "
+                 "descriptor.");
+        s[pos] = '\0';
+        write_stats_to_extrainfo = 0;
+      }
+    }
     if (options->DirReqStatistics &&
         load_stats_file("stats"PATH_SEPARATOR"dirreq-stats",
                         "dirreq-stats-end", now, &contents) > 0) {