diff options
author | Gerald Combs <gerald@wireshark.org> | 2011-10-05 22:27:51 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2011-10-05 22:27:51 +0000 |
commit | b9b05239f1ea9404752e74111f27117242b1431b (patch) | |
tree | f1b179a3e5bbf30b76e363c1962964779bfb60d7 | |
parent | c9f750537555a97f81713c97b50b25b5481ad21e (diff) | |
download | wireshark-b9b05239f1ea9404752e74111f27117242b1431b.tar.gz |
Add GeoIP IPv6 database support. Tested with GeoIP 1.4.7, but older
versions *should* be supported.
svn path=/trunk/; revision=39280
-rw-r--r-- | acinclude.m4 | 7 | ||||
-rw-r--r-- | docbook/release-notes.xml | 6 | ||||
-rw-r--r-- | epan/dissectors/packet-ipv6.c | 289 | ||||
-rw-r--r-- | epan/geoip_db.c | 141 | ||||
-rw-r--r-- | epan/geoip_db.h | 15 | ||||
-rw-r--r-- | epan/libwireshark.def | 1 | ||||
-rw-r--r-- | gtk/hostlist_table.c | 9 |
7 files changed, 450 insertions, 18 deletions
diff --git a/acinclude.m4 b/acinclude.m4 index 9309a523c1..7c27364190 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 diff --git a/docbook/release-notes.xml b/docbook/release-notes.xml index 89435bbcc7..b92b6009ef 100644 --- a/docbook/release-notes.xml +++ b/docbook/release-notes.xml @@ -103,6 +103,12 @@ Wireshark Info </para> </listitem> + <listitem> + <para> + GeoIP IPv6 databases are now supported. + </para> + </listitem> + </itemizedlist> </para> diff --git a/epan/dissectors/packet-ipv6.c b/epan/dissectors/packet-ipv6.c index 73fcd5f566..f8da7fc1ad 100644 --- a/epan/dissectors/packet-ipv6.c +++ b/epan/dissectors/packet-ipv6.c @@ -51,6 +51,11 @@ #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); diff --git a/epan/geoip_db.c b/epan/geoip_db.c index d63cfd591e..7374ca10aa 100644 --- a/epan/geoip_db.c +++ b/epan/geoip_db.c @@ -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; diff --git a/epan/geoip_db.h b/epan/geoip_db.h index 61a69e4fae..35073b9f3e 100644 --- a/epan/geoip_db.h +++ b/epan/geoip_db.h @@ -27,11 +27,12 @@ #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) /** @@ -73,6 +74,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 * * @return String with all paths separated by a path separator diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 62fa47fece..fcfc2e6770 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -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 diff --git a/gtk/hostlist_table.c b/gtk/hostlist_table.c index 7f88fbc88c..7ad1ad4f1f 100644 --- a/gtk/hostlist_table.c +++ b/gtk/hostlist_table.c @@ -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; } |