Add GeoIP IPv6 database support. Tested with GeoIP 1.4.7, but older
authorgerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 5 Oct 2011 22:27:51 +0000 (22:27 +0000)
committergerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 5 Oct 2011 22:27:51 +0000 (22:27 +0000)
versions *should* be supported.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@39280 f5534014-38df-0310-8fa8-9805f1628bb7

acinclude.m4
docbook/release-notes.xml
epan/dissectors/packet-ipv6.c
epan/geoip_db.c
epan/geoip_db.h
epan/libwireshark.def
gtk/hostlist_table.c

index 9309a523c1b490326c7b73e45ea9353d338baac2..7c2736419044b496494335c8934f7176a733c89f 100644 (file)
@@ -1544,6 +1544,13 @@ AC_DEFUN([AC_WIRESHARK_GEOIP_CHECK],
                have_good_geoip=yes
                  ],,
                )
+               if test "x$have_good_geoip" = "xyes"; then
+                       AC_CHECK_LIB(GeoIP, GeoIP_country_name_by_ipnum_v6,
+                         [
+                               AC_DEFINE(HAVE_GEOIP_V6, 1, [Define if GeoIP supports IPv6 (GeoIP 1.4.5 and later)])
+                         ],,
+                       )
+               fi
        else
                AC_MSG_RESULT(not required)
        fi
index 89435bbcc7f2abb3e24fe017e8e9cc3b7a899dcd..b92b6009ef931ea8f14ba6b6c6373eddff6d71cb 100644 (file)
@@ -103,6 +103,12 @@ Wireshark Info
           </para>
         </listitem>
 
+        <listitem>
+          <para>
+            GeoIP IPv6 databases are now supported.
+          </para>
+        </listitem>
+
       </itemizedlist>
 
     </para>
index 73fcd5f566d585be062a1c75600f4505b4ec1943..f8da7fc1ad4f57fbca84ea2c56afb997eaef89b5 100644 (file)
 #include "packet-ipsec.h"
 #include "packet-ipv6.h"
 
+#ifdef HAVE_GEOIP_V6
+#include "GeoIP.h"
+#include <epan/geoip_db.h>
+#endif /* HAVE_GEOIP_V6 */
+
 /*
  * NOTE: ipv6.nxt is not very useful as we will have chained header.
  * now testing ipv6.final, but it raises SEGV.
@@ -207,6 +212,30 @@ static int hf_ipv6_traffic_class_dscp = -1;
 static int hf_ipv6_traffic_class_ect  = -1;
 static int hf_ipv6_traffic_class_ce   = -1;
 
+#ifdef HAVE_GEOIP_V6
+static int hf_geoip_country = -1;
+static int hf_geoip_city = -1;
+static int hf_geoip_org = -1;
+static int hf_geoip_isp = -1;
+static int hf_geoip_asnum = -1;
+static int hf_geoip_lat = -1;
+static int hf_geoip_lon = -1;
+static int hf_geoip_src_country = -1;
+static int hf_geoip_src_city = -1;
+static int hf_geoip_src_org = -1;
+static int hf_geoip_src_isp = -1;
+static int hf_geoip_src_asnum = -1;
+static int hf_geoip_src_lat = -1;
+static int hf_geoip_src_lon = -1;
+static int hf_geoip_dst_country = -1;
+static int hf_geoip_dst_city = -1;
+static int hf_geoip_dst_org = -1;
+static int hf_geoip_dst_isp = -1;
+static int hf_geoip_dst_asnum = -1;
+static int hf_geoip_dst_lat = -1;
+static int hf_geoip_dst_lon = -1;
+#endif /* HAVE_GEOIP_V6 */
+
 static gint ett_ipv6                     = -1;
 static gint ett_ipv6_version   = -1;
 static gint ett_ipv6_shim6               = -1;
@@ -223,6 +252,11 @@ static gint ett_ipv6_fragments               = -1;
 static gint ett_ipv6_fragment            = -1;
 static gint ett_ipv6_traffic_class        = -1;
 
+#ifdef HAVE_GEOIP_V6
+static gint ett_geoip_info = -1;
+#endif /* HAVE_GEOIP_V6 */
+
+
 static const fragment_items ipv6_frag_items = {
        &ett_ipv6_fragment,
        &ett_ipv6_fragments,
@@ -249,6 +283,11 @@ static gboolean ipv6_reassemble = TRUE;
 /* Place IPv6 summary in proto tree */
 static gboolean ipv6_summary_in_tree = TRUE;
 
+#ifdef HAVE_GEOIP_V6
+/* Look up addresses in GeoIP */
+static gboolean ipv6_use_geoip = FALSE;
+#endif /* HAVE_GEOIP_V6 */
+
 #ifndef offsetof
 #define        offsetof(type, member)  ((size_t)(&((type *)0)->member))
 #endif
@@ -360,6 +399,152 @@ again:
   }
 }
 
+#ifdef HAVE_GEOIP_V6
+static void
+add_geoip_info(proto_tree *tree, tvbuff_t *tvb, gint offset, struct e_in6_addr src, struct e_in6_addr dst)
+{
+  guint dbnum, num_dbs;
+  int geoip_hf, geoip_src_hf, geoip_dst_hf;
+  const char *geoip_src_str, *geoip_dst_str;
+  proto_item *geoip_info_item;
+  proto_tree *geoip_info_tree;
+  proto_item *item;
+  guint item_cnt;
+
+  num_dbs = geoip_db_num_dbs();
+
+  geoip_info_item = proto_tree_add_text(tree, tvb, offset + IP6H_SRC, 16, "Source GeoIP: ");
+  geoip_info_tree = proto_item_add_subtree(geoip_info_item, ett_geoip_info);
+  PROTO_ITEM_SET_GENERATED(geoip_info_item);
+  item_cnt = 0;
+
+  for (dbnum = 0; dbnum < num_dbs; dbnum++) {
+    geoip_src_str = geoip_db_lookup_ipv6(dbnum, src, NULL);
+
+    switch (geoip_db_type(dbnum)) {
+      case GEOIP_COUNTRY_EDITION_V6:
+        geoip_hf = hf_geoip_country;
+        geoip_src_hf = hf_geoip_src_country;
+        break;
+#if NUM_DB_TYPES > 31
+      case GEOIP_CITY_EDITION_REV0_V6:
+        geoip_hf = hf_geoip_city;
+        geoip_src_hf = hf_geoip_src_city;
+        break;
+      case GEOIP_CITY_EDITION_REV1_V6:
+        geoip_hf = hf_geoip_city;
+        geoip_src_hf = hf_geoip_src_city;
+        break;
+      case GEOIP_ORG_EDITION_V6:
+        geoip_hf = hf_geoip_org;
+        geoip_src_hf = hf_geoip_src_org;
+        break;
+      case GEOIP_ISP_EDITION_V6:
+        geoip_hf = hf_geoip_isp;
+        geoip_src_hf = hf_geoip_src_isp;
+        break;
+      case GEOIP_ASNUM_EDITION_V6:
+        geoip_hf = hf_geoip_asnum;
+        geoip_src_hf = hf_geoip_src_asnum;
+        break;
+#endif /* DB_NUM_TYPES */
+      case WS_LAT_FAKE_EDITION:
+        geoip_hf = hf_geoip_lat;
+        geoip_src_hf = hf_geoip_src_lat;
+        break;
+      case WS_LON_FAKE_EDITION:
+        geoip_hf = hf_geoip_lon;
+        geoip_src_hf = hf_geoip_src_lon;
+        break;
+      default:
+        continue;
+        break;
+    }
+
+    if (geoip_src_str) {
+      item = proto_tree_add_string_format_value(geoip_info_tree, geoip_src_hf, tvb,
+        offset + IP6H_SRC, 16, geoip_src_str, "%s", geoip_src_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      item  = proto_tree_add_string_format_value(geoip_info_tree, geoip_hf, tvb,
+        offset + IP6H_SRC, 16, geoip_src_str, "%s", geoip_src_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      PROTO_ITEM_SET_HIDDEN(item);
+
+      item_cnt++;
+      proto_item_append_text(geoip_info_item, "%s%s", plurality(item_cnt, "", ", "), geoip_src_str);
+    }
+  }
+
+  if (item_cnt == 0)
+    proto_item_append_text(geoip_info_item, "Unknown");
+
+  geoip_info_item = proto_tree_add_text(tree, tvb, offset + IP6H_DST, 16, "Destination GeoIP: ");
+  geoip_info_tree = proto_item_add_subtree(geoip_info_item, ett_geoip_info);
+  PROTO_ITEM_SET_GENERATED(geoip_info_item);
+  item_cnt = 0;
+
+  for (dbnum = 0; dbnum < num_dbs; dbnum++) {
+    geoip_dst_str = geoip_db_lookup_ipv6(dbnum, dst, NULL);
+
+    switch (geoip_db_type(dbnum)) {
+      case GEOIP_COUNTRY_EDITION:
+        geoip_hf = hf_geoip_country;
+        geoip_dst_hf = hf_geoip_dst_country;
+        break;
+#if NUM_DB_TYPES > 31
+      case GEOIP_CITY_EDITION_REV0:
+        geoip_hf = hf_geoip_city;
+        geoip_dst_hf = hf_geoip_dst_city;
+        break;
+      case GEOIP_CITY_EDITION_REV1:
+        geoip_hf = hf_geoip_city;
+        geoip_dst_hf = hf_geoip_dst_city;
+        break;
+      case GEOIP_ORG_EDITION:
+        geoip_hf = hf_geoip_org;
+        geoip_dst_hf = hf_geoip_dst_org;
+        break;
+      case GEOIP_ISP_EDITION:
+        geoip_hf = hf_geoip_isp;
+        geoip_dst_hf = hf_geoip_dst_isp;
+        break;
+      case GEOIP_ASNUM_EDITION:
+        geoip_hf = hf_geoip_asnum;
+        geoip_dst_hf = hf_geoip_dst_asnum;
+        break;
+#endif /* DB_NUM_TYPES */
+      case WS_LAT_FAKE_EDITION:
+        geoip_hf = hf_geoip_lat;
+        geoip_dst_hf = hf_geoip_dst_lat;
+        break;
+      case WS_LON_FAKE_EDITION:
+        geoip_hf = hf_geoip_lon;
+        geoip_dst_hf = hf_geoip_dst_lon;
+        break;
+      default:
+        continue;
+        break;
+    }
+
+    if (geoip_dst_str) {
+      item = proto_tree_add_string_format_value(geoip_info_tree, geoip_dst_hf, tvb,
+        offset + IP6H_DST, 16, geoip_dst_str, "%s", geoip_dst_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      item  = proto_tree_add_string_format_value(geoip_info_tree, geoip_hf, tvb,
+        offset + IP6H_DST, 16, geoip_dst_str, "%s", geoip_dst_str);
+      PROTO_ITEM_SET_GENERATED(item);
+      PROTO_ITEM_SET_HIDDEN(item);
+
+      item_cnt++;
+      proto_item_append_text(geoip_info_item, "%s%s", plurality(item_cnt, "", ", "), geoip_dst_str);
+    }
+  }
+
+  if (item_cnt == 0)
+    proto_item_append_text(geoip_info_item, "Unknown");
+}
+#endif /* HAVE_GEOIP_V6 */
+
 static void
 ipv6_reassemble_init(void)
 {
@@ -469,9 +654,9 @@ dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
         cmprI >>= 4;
         pad >>= 4;
 
-        /* from draft-ietf-6man-rpl-routing-header-03: 
+        /* from draft-ietf-6man-rpl-routing-header-03:
         n = (((Hdr Ext Len * 8) - Pad - (16 - CmprE)) / (16 - CmprI)) + 1 */
-        segments = (((rt.ip6r_len * 8) - pad - (16 - cmprE)) / (16 - cmprI)) + 1;      
+        segments = (((rt.ip6r_len * 8) - pad - (16 - cmprE)) / (16 - cmprI)) + 1;
         ti = proto_tree_add_int(rthdr_tree, hf_ipv6_routing_hdr_rpl_segments, tvb, offset, 2, segments);
         PROTO_ITEM_SET_GENERATED(ti);
 
@@ -494,7 +679,7 @@ dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
                 offset += (16-cmprI);
                 segments--;
             }
-     
+
             /* We use cmprE for last address for how many bytes to elide, so actual bytes present = 16-CmprE */
             if (segments == 1) {
                 struct e_in6_addr addr;
@@ -506,10 +691,10 @@ dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo
                 ti = proto_tree_add_ipv6(rthdr_tree, hf_ipv6_routing_hdr_rpl_fulladdr, tvb, offset, (16-cmprE), (guint8 *)&addr);
                 PROTO_ITEM_SET_GENERATED(ti);
                 offset += (16-cmprE);
-            }  
-          
-        }   
-   
+            }
+
+        }
+
     }
     }
 
@@ -1504,7 +1689,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     proto_tree_add_item(ipv6_tree, hf_ipv6_hlim, tvb,
                        offset + offsetof(struct ip6_hdr, ip6_hlim), 1, FALSE);
 
-    /* Adds the different items for the source address */
+    /* Add the different items for the source address */
     proto_tree_add_item(ipv6_tree, hf_ipv6_src, tvb,
                        offset + offsetof(struct ip6_hdr, ip6_src), 16, FALSE);
     ti = proto_tree_add_ipv6(ipv6_tree, hf_ipv6_addr, tvb,
@@ -1526,6 +1711,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     PROTO_ITEM_SET_GENERATED(ti);
     PROTO_ITEM_SET_HIDDEN(ti);
 
+    /* Extract embedded (IPv6 and MAC) address information */
     if (tvb_get_ntohs(tvb, offset + IP6H_SRC) == 0x2002) { /* RFC 3056 section 2 */
       ti = proto_tree_add_item(ipv6_tree, hf_ipv6_src_6to4_gateway_ipv4, tvb,
                                 offset + IP6H_SRC + 2, 4, FALSE);
@@ -1590,7 +1776,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
       PROTO_ITEM_SET_HIDDEN(ti);
     }
 
-    /* Adds different items for the destination address */
+    /* Add different items for the destination address */
     proto_tree_add_item(ipv6_tree, hf_ipv6_dst, tvb,
                        offset + offsetof(struct ip6_hdr, ip6_dst), 16, FALSE);
     ti = proto_tree_add_ipv6(ipv6_tree, hf_ipv6_addr, tvb,
@@ -1612,6 +1798,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     PROTO_ITEM_SET_GENERATED(ti);
     PROTO_ITEM_SET_HIDDEN(ti);
 
+    /* Extract embedded (IPv6 and MAC) address information */
     if (tvb_get_ntohs(tvb, offset + IP6H_DST) == 0x2002) { /* RFC 3056 section 2 */
       ti = proto_tree_add_item(ipv6_tree, hf_ipv6_dst_6to4_gateway_ipv4, tvb,
                                 offset + IP6H_DST + 2, 4, FALSE);
@@ -1677,6 +1864,12 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     }
   }
 
+#ifdef HAVE_GEOIP
+  if (tree && ipv6_use_geoip) {
+    add_geoip_info(ipv6_tree, tvb, offset, ipv6.ip6_src, ipv6.ip6_dst);
+  }
+#endif
+
   /* start of the new header (could be a extension header) */
   poffset = offset + offsetof(struct ip6_hdr, ip6_nxt);
   nxt = tvb_get_guint8(tvb, poffset);
@@ -2007,6 +2200,73 @@ proto_register_ipv6(void)
       { "Teredo Client IPv4",          "ipv6.tc_ipv4",
                                FT_IPv4, BASE_NONE, NULL, 0x0,
                                "IPv6 Teredo Client Encapsulated IPv4 Address", HFILL }},
+#ifdef HAVE_GEOIP_V6
+    { &hf_geoip_country,
+      { "Source or Destination GeoIP Country", "ipv6.geoip.country", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_city,
+      { "Source or Destination GeoIP City", "ipv6.geoip.city", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_org,
+      { "Source or Destination GeoIP Organization", "ipv6.geoip.org", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_isp,
+      { "Source or Destination GeoIP ISP", "ipv6.geoip.isp", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_asnum,
+      { "Source or Destination GeoIP AS Number", "ipv6.geoip.asnum", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_lat,
+      { "Source or Destination GeoIP Latitude", "ipv6.geoip.lat", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_lon,
+      { "Source or Destination GeoIP Longitude", "ipv6.geoip.lon", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_country,
+      { "Source GeoIP Country", "ipv6.geoip.src_country", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_city,
+      { "Source GeoIP City", "ipv6.geoip.src_city", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_org,
+      { "Source GeoIP Organization", "ipv6.geoip.src_org", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_isp,
+      { "Source GeoIP ISP", "ipv6.geoip.src_isp", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_asnum,
+      { "Source GeoIP AS Number", "ipv6.geoip.src_asnum", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_lat,
+      { "Source GeoIP Latitude", "ipv6.geoip.src_lat", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_src_lon,
+      { "Source GeoIP Longitude", "ipv6.geoip.src_lon", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_country,
+      { "Destination GeoIP Country", "ipv6.geoip.dst_country", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_city,
+      { "Destination GeoIP City", "ipv6.geoip.dst_city", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_org,
+      { "Destination GeoIP Organization", "ipv6.geoip.dst_org", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_isp,
+      { "Destination GeoIP ISP", "ipv6.geoip.dst_isp", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_asnum,
+      { "Destination GeoIP AS Number", "ipv6.geoip.dst_asnum", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_lat,
+      { "Destination GeoIP Latitude", "ipv6.geoip.dst_lat", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+    { &hf_geoip_dst_lon,
+      { "Destination GeoIP Longitude", "ipv6.geoip.dst_lon", FT_STRING, BASE_NONE, NULL, 0x0,
+           NULL, HFILL }},
+#endif /* HAVE_GEOIP_V6 */
+
+
     { &hf_ipv6_opt_pad1,
       { "Pad1",                        "ipv6.opt.pad1",
                                FT_NONE, BASE_NONE, NULL, 0x0,
@@ -2364,7 +2624,10 @@ proto_register_ipv6(void)
     &ett_ipv6_shim6_cksum,
     &ett_ipv6_fragments,
     &ett_ipv6_fragment,
-    &ett_ipv6_traffic_class
+    &ett_ipv6_traffic_class,
+#ifdef HAVE_GEOIP_V6
+    &ett_geoip_info
+#endif /* HAVE_GEOIP_V6 */
   };
   module_t *ipv6_module;
 
@@ -2382,6 +2645,12 @@ proto_register_ipv6(void)
        "Show IPv6 summary in protocol tree",
        "Whether the IPv6 summary line should be shown in the protocol tree",
        &ipv6_summary_in_tree);
+#ifdef HAVE_GEOIP_V6
+       prefs_register_bool_preference(ipv6_module, "use_geoip" ,
+                 "Enable GeoIP lookups",
+                 "Whether to look up IPv6 addresses in each GeoIP database we have loaded",
+                 &ipv6_use_geoip);
+#endif /* HAVE_GEOIP_V6 */
 
   register_dissector("ipv6", dissect_ipv6, proto_ipv6);
   register_init_routine(ipv6_reassemble_init);
index d63cfd591e78be0fa3ac83ab4334a6e0763b4ca3..7374ca10aa72b45da646955ef5cbb9908a2966b7 100644 (file)
@@ -62,9 +62,19 @@ value_string geoip_type_name_vals[] = {
     { GEOIP_ASNUM_EDITION,          "AS Number" },
     { GEOIP_NETSPEED_EDITION,       "Speed" },
     { GEOIP_DOMAIN_EDITION,         "Domain" },
-#ifdef GEOIP_COUNTRY_EDITION_V6
+#ifdef HAVE_GEOIP_V6
     { GEOIP_COUNTRY_EDITION_V6,     "Country" },
-#endif
+/* This is the closest thing to a version that GeoIP.h seems to provide. */
+#if NUM_DB_TYPES > 31 /* 1.4.7 */
+    { GEOIP_CITY_EDITION_REV0_V6,   "City"},
+    { GEOIP_CITY_EDITION_REV1_V6,   "City"},
+    { GEOIP_ASNUM_EDITION_V6,       "AS Number" },
+    { GEOIP_ISP_EDITION_V6,         "ISP" },
+    { GEOIP_ORG_EDITION_V6,         "Organization" },
+    { GEOIP_DOMAIN_EDITION_V6,      "Domain" },
+    { GEOIP_NETSPEED_EDITION_V6,    "Speed" },
+#endif /* NUM_DB_TYPES */
+#endif /* HAVE_GEOIP_V6 */
     { WS_LAT_FAKE_EDITION,          "Latitude" },   /* fake database */
     { WS_LON_FAKE_EDITION,          "Longitude" },  /* fake database */
     { 0, NULL }
@@ -208,7 +218,7 @@ geoip_db_type(guint dbnum) {
 }
 
 static int
-geoip_db_lookup_latlon(guint32 addr, float *lat, float *lon) {
+geoip_db_lookup_latlon4(guint32 addr, float *lat, float *lon) {
     GeoIP *gi;
     GeoIPRecord *gir;
     guint i;
@@ -274,7 +284,119 @@ geoip_db_lookup_ipv4(guint dbnum, guint32 addr, char *not_found) {
                 float lat;
                 float lon;
                 char *c;
-                if(geoip_db_lookup_latlon(addr, &lat, &lon) == 0) {
+                if(geoip_db_lookup_latlon4(addr, &lat, &lon) == 0) {
+                    g_snprintf(val, VAL_STR_LEN, "%f", lat);
+                    c = strchr(val, ',');
+                    if (c != NULL) *c = '.';
+                    ret = val;
+                }
+            }
+                break;
+
+            case WS_LON_FAKE_EDITION:
+            {
+                float lat;
+                float lon;
+                char *c;
+                if(geoip_db_lookup_latlon4(addr, &lat, &lon) == 0) {
+                    g_snprintf(val, VAL_STR_LEN, "%f", lon);
+                    c = strchr(val, ',');
+                    if (c != NULL) *c = '.';
+                    ret = val;
+                }
+            }
+                break;
+
+            default:
+                break;
+        }
+    }
+    if (ret) {
+        return ret;
+    }
+    return not_found;
+}
+
+#ifdef HAVE_GEOIP_V6
+
+static int
+#if NUM_DB_TYPES > 31 /* 1.4.7 */
+geoip_db_lookup_latlon6(geoipv6_t addr, float *lat, float *lon) {
+    GeoIP *gi;
+    GeoIPRecord *gir;
+    guint i;
+
+    for (i = 0; i < geoip_db_num_dbs(); i++) {
+        gi = g_array_index(geoip_dat_arr, GeoIP *, i);
+        if (gi) {
+            switch (gi->databaseType) {
+                case GEOIP_CITY_EDITION_REV0_V6:
+                case GEOIP_CITY_EDITION_REV1_V6:
+                    gir = GeoIP_record_by_ipnum_v6(gi, addr);
+                    if(gir) {
+                        *lat = gir->latitude;
+                        *lon = gir->longitude;
+                        return 0;
+                    }
+                    return -1;
+                    /*break;*/
+
+                default:
+                    break;
+            }
+        }
+    }
+    return -1;
+}
+#else /* NUM_DB_TYPES */
+geoip_db_lookup_latlon6(geoipv6_t addr _U_, float *lat _U_, float *lon _U_) {
+    return -1;
+}
+#endif /* NUM_DB_TYPES */
+
+const char *
+geoip_db_lookup_ipv6(guint dbnum, struct e_in6_addr addr, char *not_found) {
+    GeoIP *gi;
+    const geoipv6_t *gaddr = (geoipv6_t *) &addr;
+    const char *ret = not_found;
+    static char val[VAL_STR_LEN];
+#if NUM_DB_TYPES > 31
+    GeoIPRecord *gir;
+#endif
+
+    gi = g_array_index(geoip_dat_arr, GeoIP *, dbnum);
+    if (gi) {
+        switch (gi->databaseType) {
+            case GEOIP_COUNTRY_EDITION_V6:
+                ret = GeoIP_country_name_by_ipnum_v6(gi, *gaddr);
+                break;
+
+#if NUM_DB_TYPES > 31
+            case GEOIP_CITY_EDITION_REV0_V6:
+            case GEOIP_CITY_EDITION_REV1_V6:
+                gir = GeoIP_record_by_ipnum_v6(gi, *gaddr);
+                if (gir && gir->city && gir->region) {
+                    g_snprintf(val, VAL_STR_LEN, "%s, %s", gir->city, gir->region);
+                    ret = val;
+                } else if (gir && gir->city) {
+                    g_snprintf(val, VAL_STR_LEN, "%s", gir->city);
+                    ret = val;
+                }
+                break;
+
+            case GEOIP_ORG_EDITION_V6:
+            case GEOIP_ISP_EDITION_V6:
+            case GEOIP_ASNUM_EDITION_V6:
+                ret = GeoIP_name_by_ipnum_v6(gi, *gaddr);
+                break;
+#endif /* NUM_DB_TYPES */
+
+            case WS_LAT_FAKE_EDITION:
+            {
+                float lat;
+                float lon;
+                char *c;
+                if(geoip_db_lookup_latlon6(*gaddr, &lat, &lon) == 0) {
                     g_snprintf(val, VAL_STR_LEN, "%f", lat);
                     c = strchr(val, ',');
                     if (c != NULL) *c = '.';
@@ -288,7 +410,7 @@ geoip_db_lookup_ipv4(guint dbnum, guint32 addr, char *not_found) {
                 float lat;
                 float lon;
                 char *c;
-                if(geoip_db_lookup_latlon(addr, &lat, &lon) == 0) {
+                if(geoip_db_lookup_latlon6(*gaddr, &lat, &lon) == 0) {
                     g_snprintf(val, VAL_STR_LEN, "%f", lon);
                     c = strchr(val, ',');
                     if (c != NULL) *c = '.';
@@ -307,6 +429,15 @@ geoip_db_lookup_ipv4(guint dbnum, guint32 addr, char *not_found) {
     return not_found;
 }
 
+#else /* HAVE_GEOIP_V6 */
+
+const char *
+geoip_db_lookup_ipv6(guint dbnum _U_, struct e_in6_addr *addr _U_, char *not_found) {
+    return not_found;
+}
+
+#endif /* HAVE_GEOIP_V6 */
+
 gchar *
 geoip_db_get_paths(void) {
     GString* path_str = NULL;
index 61a69e4fae93abc6afda8064ee5c0df3da7ae12f..35073b9f3ea5694b1249bfde6359143c935b251e 100644 (file)
 #ifndef __GEOIP_DB_H__
 #define __GEOIP_DB_H__
 
+#include <epan/ipv6-utils.h>
 
 /* Fake databases to make lat/lon values available */
 /* XXX - find a better way to interface */
-#define WS_LAT_FAKE_EDITION 12
-#define WS_LON_FAKE_EDITION 13
+#define WS_LAT_FAKE_EDITION (NUM_DB_TYPES+1)
+#define WS_LON_FAKE_EDITION (NUM_DB_TYPES+2)
 
 
 /**
@@ -72,6 +73,16 @@ extern int geoip_db_type(guint dbnum);
  */
 extern const char *geoip_db_lookup_ipv4(guint dbnum, guint32 addr, char *not_found);
 
+/**
+ * Look up an IPv6 address in a database
+ *
+ * @param dbnum Database index
+ * @param addr IPv6 address to look up
+ * @param not_found The string to return if the lookup fails. May be NULL.
+ * @return The database entry if found, else not_found
+ */
+extern const char *geoip_db_lookup_ipv6(guint dbnum, struct e_in6_addr addr, char *not_found);
+
 /**
  * Get all configured paths
  *
index 62fa47fecef00fe0cd27adc1a6f00971da4a08f9..fcfc2e67701df87ff90440b2426cc813f0b0d4f1 100644 (file)
@@ -508,6 +508,7 @@ gbl_resolv_flags                DATA
 gcamel_StatSRT                  DATA
 geoip_db_get_paths
 geoip_db_lookup_ipv4
+geoip_db_lookup_ipv6
 geoip_db_name
 geoip_db_num_dbs
 geoip_db_type
index 7f88fbc88c0f77305c001b39056e979206f88ec7..7ad1ad4f1f2d68621b012efb6d9287b6630924d9 100644 (file)
@@ -41,6 +41,7 @@
 #include <epan/tap.h>
 #include <epan/strutil.h>
 #ifdef HAVE_GEOIP
+#include "GeoIP.h"
 #include <epan/geoip_db.h>
 #include <epan/pint.h>
 #include <epan/filesystem.h>
@@ -714,7 +715,7 @@ draw_hostlist_table_data(hostlist_table *hl)
             char geoip[NUM_GEOIP_COLS][COL_STR_LEN];
             guint j;
 
-            if (host->address.type == AT_IPv4 && !hl->geoip_visible) {
+            if ((host->address.type == AT_IPv4 || host->address.type == AT_IPv6) && !hl->geoip_visible) {
                 GList             *columns, *list;
                 GtkTreeViewColumn *column;
                 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(hl->table));
@@ -740,6 +741,12 @@ draw_hostlist_table_data(hostlist_table *hl)
                 if (host->address.type == AT_IPv4 && j < geoip_db_num_dbs()) {
                     const guchar *name = geoip_db_lookup_ipv4(j, pntohl(host->address.data), "-");
                     g_strlcpy(geoip[j], format_text (name, strlen(name)), COL_STR_LEN);
+                } else if (host->address.type == AT_IPv6 && j < geoip_db_num_dbs()) {
+                    const guchar *name;
+                    const struct e_in6_addr *addr = (struct e_in6_addr *) host->address.data;
+
+                    name = geoip_db_lookup_ipv6(j, *addr, "-");
+                    g_strlcpy(geoip[j], format_text (name, strlen(name)), COL_STR_LEN);
                 } else {
                   geoip[j][0] = 0;
                 }