summaryrefslogtreecommitdiff
path: root/epan/addr_resolv.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2013-08-18 19:02:48 +0000
committerAnders Broman <anders.broman@ericsson.com>2013-08-18 19:02:48 +0000
commitccb96fd73a17b294afe9f0511f708239fd787939 (patch)
tree0c489ddbc5b6579f92fbf410a13604aa68f8c1e1 /epan/addr_resolv.c
parent2cbe77751607fc3541333c83b59b84ba9af4d893 (diff)
downloadwireshark-ccb96fd73a17b294afe9f0511f708239fd787939.tar.gz
Use g_hastable() for IPv6 name reslution.
svn path=/trunk/; revision=51415
Diffstat (limited to 'epan/addr_resolv.c')
-rw-r--r--epan/addr_resolv.c141
1 files changed, 80 insertions, 61 deletions
diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c
index 2c1f44b8ad..b7382aa752 100644
--- a/epan/addr_resolv.c
+++ b/epan/addr_resolv.c
@@ -141,8 +141,6 @@
#define HASHETHSIZE 2048
#define HASHHOSTSIZE 2048
#define HASHIPXNETSIZE 256
-#define HASHMANUFSIZE 256
-#define HASHPORTSIZE 256
#define SUBNETLENGTHSIZE 32 /*1-32 inc.*/
/* g_int64_hash() and g_int64_equal() first appear in GLib 2.22, make a local copy here */
@@ -219,11 +217,8 @@ typedef struct sub_net_hashipv4 {
gchar name[MAXNAMELEN];
} sub_net_hashipv4_t;
-/* hash table used for IPv6 lookup */
-
-#define HASH_IPV6_ADDRESS(addr) \
- ((((addr).bytes[14] << 8)|((addr).bytes[15])) & (HASHHOSTSIZE - 1))
+#if 0
typedef struct hashipv6 {
struct e_in6_addr addr;
gboolean is_dummy_entry; /* name is IPv6 address in colon format */
@@ -232,7 +227,7 @@ typedef struct hashipv6 {
gchar ip6[MAX_IP6_STR_LEN]; /* XX */
gchar name[MAXNAMELEN];
} hashipv6_t;
-
+#endif
/* Array of entries of subnets of different lengths */
typedef struct {
gsize mask_length; /*1-32*/
@@ -240,10 +235,6 @@ typedef struct {
sub_net_hashipv4_t** subnet_addresses; /* Hash table of subnet addresses */
} subnet_length_entry_t;
-/* hash table used for TCP/UDP/SCTP port lookup */
-
-#define HASH_PORT(port) ((port) & (HASHPORTSIZE - 1))
-
#if 0
typedef struct serv_port {
@@ -295,9 +286,8 @@ typedef struct _ipxnet
char name[MAXNAMELEN];
} ipxnet_t;
-static hashipv6_t *ipv6_table[HASHHOSTSIZE];
-
static GHashTable *ipv4_hash_table = NULL;
+static GHashTable *ipv6_hash_table = NULL;
static gchar *cb_service;
static port_type cb_proto = PT_NONE;
@@ -322,6 +312,42 @@ static GPtrArray* extra_hosts_files = NULL;
static hashether_t *add_eth_name(const guint8 *addr, const gchar *name);
static void add_serv_port_cb(const guint32 port);
+
+/* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
+ * One-at-a-Time hash
+ */
+static guint32
+ipv6_oat_hash(gconstpointer key)
+{
+ int len = 16;
+ const unsigned char *p = (const unsigned char *)key;
+ guint32 h = 0;
+ int i;
+
+ for ( i = 0; i < len; i++ ) {
+ h += p[i];
+ h += ( h << 10 );
+ h ^= ( h >> 6 );
+ }
+
+ h += ( h << 3 );
+ h ^= ( h >> 11 );
+ h += ( h << 15 );
+
+ return h;
+}
+
+static gboolean
+ipv6_equal(gconstpointer v1, gconstpointer v2)
+{
+
+ if( memcmp(v1, v2, sizeof (struct e_in6_addr)) == 0 ) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/*
* Flag controlling what names to resolve.
*/
@@ -956,9 +982,8 @@ try_resolv:
static hashipv6_t *
new_ipv6(const struct e_in6_addr *addr)
{
- hashipv6_t *tp = se_new(hashipv6_t);
+ hashipv6_t *tp = g_new(hashipv6_t,1);
tp->addr = *addr;
- tp->next = NULL;
tp->resolve = FALSE;
tp->is_dummy_entry = FALSE;
ip6_to_str_buf(addr, tp->ip6);
@@ -969,7 +994,6 @@ new_ipv6(const struct e_in6_addr *addr)
static hashipv6_t *
host_lookup6(const struct e_in6_addr *addr, gboolean *found)
{
- int hash_idx;
hashipv6_t * volatile tp;
#ifdef INET6
#ifdef HAVE_C_ARES
@@ -980,30 +1004,25 @@ host_lookup6(const struct e_in6_addr *addr, gboolean *found)
*found = TRUE;
- hash_idx = HASH_IPV6_ADDRESS(*addr);
-
- tp = ipv6_table[hash_idx];
+ tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addr);
+ if(tp == NULL){
+ struct e_in6_addr *addr_key;
- if( tp == NULL ) {
- tp = ipv6_table[hash_idx] = new_ipv6(addr);
- } else {
- while(1) {
- if( memcmp(&tp->addr, addr, sizeof (struct e_in6_addr)) == 0 ) {
- if (tp->is_dummy_entry && !tp->resolve)
- break;
- if (tp->is_dummy_entry)
- *found = FALSE;
- return tp;
- }
- if (tp->next == NULL) {
- tp->next = new_ipv6(addr);
- tp = tp->next;
- break;
- }
- tp = tp->next;
+ addr_key = g_new(struct e_in6_addr,1);
+ tp = new_ipv6(addr);
+ memcpy(addr_key, addr, 16);
+ g_hash_table_insert(ipv6_hash_table, addr_key, tp);
+ }else{
+ if (tp->is_dummy_entry && !tp->resolve){
+ goto try_resolv;
}
+ if (tp->is_dummy_entry){
+ *found = FALSE;
+ }
+ return tp;
}
+try_resolv:
if (gbl_resolv_flags.network_name &&
gbl_resolv_flags.use_external_net_name_resolver) {
tp->resolve = TRUE;
@@ -2731,7 +2750,6 @@ add_ipv4_name(const guint addr, const gchar *name)
void
add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
{
- int hash_idx;
hashipv6_t *tp;
struct addrinfo *ai;
struct sockaddr_in6 *sa6;
@@ -2743,31 +2761,21 @@ add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
if (name[0] == '\0')
return;
- hash_idx = HASH_IPV6_ADDRESS(*addrp);
-
- tp = ipv6_table[hash_idx];
+ tp = (hashipv6_t *)g_hash_table_lookup(ipv6_hash_table, addrp);
+ if(tp){
+ g_strlcpy(tp->name, name, MAXNAMELEN);
+ tp->resolve = TRUE;
+ }else{
+ struct e_in6_addr *addr_key;
- if( tp == NULL ) {
- tp = ipv6_table[hash_idx] = new_ipv6(addrp);
- } else {
- while(1) {
- if (memcmp(&tp->addr, addrp, sizeof (struct e_in6_addr)) == 0) {
- /* address already known */
- if (!tp->is_dummy_entry) {
- return;
- } else {
- /* replace this dummy entry with the new one */
- break;
- }
- }
- if (tp->next == NULL) {
- tp->next = new_ipv6(addrp);
- tp = tp->next;
- break;
- }
- tp = tp->next;
- }
+ addr_key = g_new(struct e_in6_addr,1);
+ tp = new_ipv6(addrp);
+ memcpy(addr_key, addrp, 16);
+ g_strlcpy(tp->name, name, MAXNAMELEN);
+ tp->resolve = TRUE;
+ g_hash_table_insert(ipv6_hash_table, addr_key, tp);
}
+
g_strlcpy(tp->name, name, MAXNAMELEN);
tp->resolve = TRUE;
new_resolved_objects = TRUE;
@@ -2810,6 +2818,9 @@ host_name_lookup_init(void)
g_assert(ipv4_hash_table == NULL);
ipv4_hash_table = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
+ g_assert(ipv6_hash_table == NULL);
+ ipv6_hash_table = g_hash_table_new_full(ipv6_oat_hash, ipv6_equal, g_free, g_free);
+
if (!addrinfo_list) {
ai = se_new0(struct addrinfo);
addrinfo_list = addrinfo_list_last = ai;
@@ -2914,7 +2925,10 @@ host_name_lookup_cleanup(void)
g_hash_table_destroy(ipv4_hash_table);
ipv4_hash_table = NULL;
}
- memset(ipv6_table, 0, sizeof(ipv6_table));
+ if(ipv6_hash_table){
+ g_hash_table_destroy(ipv6_hash_table);
+ ipv6_hash_table = NULL;
+ }
memset(subnet_length_entries, 0, sizeof(subnet_length_entries));
@@ -3471,6 +3485,11 @@ get_ipv4_hash_table(void)
return ipv4_hash_table;
}
+GHashTable *
+get_ipv6_hash_table(void)
+{
+ return ipv6_hash_table;
+}
/* Initialize all the address resolution subsystems in this file */
void
addr_resolv_init(void)