Sfoglia il codice sorgente

Separate IPv4 and IPv6 geoip file loading.

Also add IPv6 geoip file digest to extra info.

Also also, add support for IPv6 addresses in control command
"ip-to-country".
Linus Nordberg 13 anni fa
parent
commit
817ff962f8
5 ha cambiato i file con 59 aggiunte e 46 eliminazioni
  1. 6 6
      src/or/config.c
  2. 44 34
      src/or/geoip.c
  3. 2 2
      src/or/geoip.h
  4. 6 3
      src/or/router.c
  5. 1 1
      src/or/routerset.c

+ 6 - 6
src/or/config.c

@@ -1512,10 +1512,10 @@ options_act(const or_options_t *old_options)
       connection_or_update_token_buckets(get_connection_array(), options);
   }
 
-  /* Maybe load geoip file */
+  /* Maybe load IPv4 geoip file */
   if (options->GeoIPFile &&
       ((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile))
-       || !geoip_is_loaded())) {
+       || !geoip_is_loaded(AF_INET))) {
     /* XXXX Don't use this "<default>" junk; make our filename options
      * understand prefixes somehow. -NM */
     /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */
@@ -1530,11 +1530,11 @@ options_act(const or_options_t *old_options)
     geoip_load_file(AF_INET, actual_fname, options);
     tor_free(actual_fname);
   }
-  /* And maybe load geoip ipv6 file */
+  /* And maybe load IPv6 geoip file */
   if (options->GeoIPv6File &&
       ((!old_options || !opt_streq(old_options->GeoIPv6File,
                                    options->GeoIPv6File))
-       || !geoip_is_loaded())) {
+       || !geoip_is_loaded(AF_INET6))) {
     /* XXXX Don't use this "<default>" junk; make our filename options
      * understand prefixes somehow.  See also comment for GeoIPFile. */
     /* XXXX024 Reload GeoIPV6File on SIGHUP.  See also comment for
@@ -1573,7 +1573,7 @@ options_act(const or_options_t *old_options)
     }
     if ((!old_options || !old_options->DirReqStatistics) &&
         options->DirReqStatistics) {
-      if (geoip_is_loaded()) {
+      if (geoip_is_loaded(AF_INET)) {
         geoip_dirreq_stats_init(now);
         print_notice = 1;
       } else {
@@ -1588,7 +1588,7 @@ options_act(const or_options_t *old_options)
     }
     if ((!old_options || !old_options->EntryStatistics) &&
         options->EntryStatistics && !should_record_bridge_info(options)) {
-      if (geoip_is_loaded()) {
+      if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) {
         geoip_entry_stats_init(now);
         print_notice = 1;
       } else {

+ 44 - 34
src/or/geoip.c

@@ -52,8 +52,9 @@ static strmap_t *country_idxplus1_by_lc_code = NULL;
  * by their respective ip_low. */
 static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL;
 
-/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */
+/** SHA1 digest of the GeoIP files to include in extra-info descriptors. */
 static char geoip_digest[DIGEST_LEN];
+static char geoip6_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.
@@ -376,22 +377,20 @@ geoip_load_file(sa_family_t family, const char *filename,
   /*XXXX abort and return -1 if no entries/illformed?*/
   fclose(f);
 
-  if (family == AF_INET)
+  /* Sort list and remember file digests so that we can include it in
+   * our extra-info descriptors. */
+  if (family == AF_INET) {
     smartlist_sort(geoip_ipv4_entries, geoip_ipv4_compare_entries_);
-  else /* AF_INET6 */
+    /* Okay, now we need to maybe change our mind about what is in
+     * which country. We do this for IPv4 only since that's what we
+     * store in node->country. */
+    refresh_all_country_info();
+    crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN);
+  }
+  else {                        /* AF_INET6 */
     smartlist_sort(geoip_ipv6_entries, geoip_ipv6_compare_entries_);
-
-  /* Okay, now we need to maybe change our mind about what is in which
-   * country. */
-  refresh_all_country_info();
-
-  /* Remember file digest so that we can include it in our extra-info
-   * descriptors. */
-  /* XXX5053 This is a bug!  We overwrite geoip_digest with whichever file
-   * we parse last.  We'll want to add a separate geoip6_digest and write
-   * a geoip6-db-digest line to our extra-info descriptor.  Needs a
-   * dir-spec.txt patch, too. -KL */
-  crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN);
+    crypto_digest_get_digest(geoip_digest_env, geoip6_digest, DIGEST_LEN);
+  }
   crypto_digest_free(geoip_digest_env);
 
   return 0;
@@ -471,22 +470,28 @@ geoip_get_country_name(country_t num)
 
 /** Return true iff we have loaded a GeoIP database.*/
 int
-geoip_is_loaded(void)
+geoip_is_loaded(sa_family_t family)
 {
-  /* XXX5053 Saying that we have loaded a GeoIP database if have _either_
-   * a v4 or v6 database might be problematic.  Maybe we need to add an
-   * address parameter to this function? -KL */
-  return geoip_countries != NULL &&
-    (geoip_ipv4_entries != NULL || geoip_ipv6_entries != NULL);
+  tor_assert(family == AF_INET || family == AF_INET6);
+  if (geoip_countries == NULL)
+    return 0;
+  if (family == AF_INET)
+    return geoip_ipv4_entries != NULL;
+  else                          /* AF_INET6 */
+    return geoip_ipv6_entries != NULL;
 }
 
 /** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The
  * result does not need to be deallocated, but will be overwritten by the
  * next call of hex_str(). */
 const char *
-geoip_db_digest(void)
+geoip_db_digest(sa_family_t family)
 {
-  return hex_str(geoip_digest, DIGEST_LEN);
+  tor_assert(family == AF_INET || family == AF_INET6);
+  if (family == AF_INET)
+    return hex_str(geoip_digest, DIGEST_LEN);
+  else                          /* AF_INET6 */
+    return hex_str(geoip6_digest, DIGEST_LEN);
 }
 
 /** Entry in a map from IP address to the last time we've seen an incoming
@@ -1011,7 +1016,7 @@ geoip_get_client_history(geoip_client_action_t action, int *total_ipv4,
   unsigned total = 0;
   unsigned ipv4_count = 0, ipv6_count = 0;
 
-  if (!geoip_is_loaded())
+  if (!geoip_is_loaded(AF_INET) && !geoip_is_loaded(AF_INET6))
     return NULL;
 
   counts = tor_malloc_zero(sizeof(unsigned)*n_countries);
@@ -1639,20 +1644,25 @@ getinfo_helper_geoip(control_connection_t *control_conn,
                      const char **errmsg)
 {
   (void)control_conn;
-  if (!geoip_is_loaded()) {
-    *errmsg = "GeoIP data not loaded";
-    return -1;
-  }
   if (!strcmpstart(question, "ip-to-country/")) {
     int c;
-    uint32_t ip;
-    struct in_addr in;
+    sa_family_t family;
+    tor_addr_t addr;
     question += strlen("ip-to-country/");
-    if (tor_inet_aton(question, &in) != 0) {
-      ip = ntohl(in.s_addr);
-      c = geoip_get_country_by_ipv4(ip);
-      *answer = tor_strdup(geoip_get_country_name(c));
+    family = tor_addr_parse(&addr, question);
+    if (family != AF_INET && family != AF_INET6) {
+      *errmsg = "Invalid address family";
+      return -1;
+    }
+    if (!geoip_is_loaded(family)) {
+      *errmsg = "GeoIP data not loaded";
+      return -1;
     }
+    if (family == AF_INET)
+      c = geoip_get_country_by_ipv4(tor_addr_to_ipv4h(&addr));
+    else                      /* AF_INET6 */
+      c = geoip_get_country_by_ipv6(tor_addr_to_in6(&addr));
+    *answer = tor_strdup(geoip_get_country_name(c));
   }
   return 0;
 }

+ 2 - 2
src/or/geoip.h

@@ -24,8 +24,8 @@ int geoip_load_file(sa_family_t family, const char *filename,
 int geoip_get_country_by_addr(const tor_addr_t *addr);
 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);
+int geoip_is_loaded(sa_family_t family);
+const char *geoip_db_digest(sa_family_t family);
 country_t geoip_get_country(const char *countrycode);
 
 void geoip_note_client_seen(geoip_client_action_t action,

+ 6 - 3
src/or/router.c

@@ -2313,9 +2313,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
   tor_free(bandwidth_usage);
   smartlist_add(chunks, pre);
 
-  if (geoip_is_loaded()) {
-    smartlist_add_asprintf(chunks, "geoip-db-digest %s\n", geoip_db_digest());
-  }
+  if (geoip_is_loaded(AF_INET))
+    smartlist_add_asprintf(chunks, "geoip-db-digest %s\n",
+                           geoip_db_digest(AF_INET));
+  if (geoip_is_loaded(AF_INET6))
+    smartlist_add_asprintf(chunks, "geoip6-db-digest %s\n",
+                           geoip_db_digest(AF_INET6));
 
   if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
     log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");

+ 1 - 1
src/or/routerset.c

@@ -82,7 +82,7 @@ routerset_refresh_countries(routerset_t *target)
   int cc;
   bitarray_free(target->countries);
 
-  if (!geoip_is_loaded()) {
+  if (!geoip_is_loaded(AF_INET)) {
     target->countries = NULL;
     target->n_countries = 0;
     return;