[tor-commits] [tor/master] Separate IPv4 and IPv6 geoip file loading.

nickm at torproject.org nickm at torproject.org
Mon Nov 5 02:51:56 UTC 2012


commit 817ff962f830188ec4c1a907ebc389a856ea3288
Author: Linus Nordberg <linus at torproject.org>
Date:   Sat Oct 20 18:48:58 2012 +0200

    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".
---
 src/or/config.c    |   12 ++++----
 src/or/geoip.c     |   78 +++++++++++++++++++++++++++++----------------------
 src/or/geoip.h     |    4 +-
 src/or/router.c    |    9 ++++--
 src/or/routerset.c |    2 +-
 5 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/src/or/config.c b/src/or/config.c
index 3b95909..5b1f1ee 100644
--- a/src/or/config.c
+++ b/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 {
diff --git a/src/or/geoip.c b/src/or/geoip.c
index 7507918..e1c0009 100644
--- a/src/or/geoip.c
+++ b/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;
 }
diff --git a/src/or/geoip.h b/src/or/geoip.h
index 38f1289..1d0012f 100644
--- a/src/or/geoip.h
+++ b/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,
diff --git a/src/or/router.c b/src/or/router.c
index 2e80c54..926bf26 100644
--- a/src/or/router.c
+++ b/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.");
diff --git a/src/or/routerset.c b/src/or/routerset.c
index f3cd592..f9e3c9a 100644
--- a/src/or/routerset.c
+++ b/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;





More information about the tor-commits mailing list