Index: pace/lib/c/generic/adt/hash_set.c
===================================================================
--- uspace/lib/c/generic/adt/hash_set.c	(revision 0ca7286a618557bd1d13cded4ccbe25d62752237)
+++ 	(revision )
@@ -1,382 +1,0 @@
-/*
- * Copyright (c) 2008 Jakub Jermar
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#include <adt/hash_set.h>
-#include <adt/list.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <assert.h>
-#include <str.h>
-
-/** Create chained hash set
- *
- * @param     h         Hash set structure to be initialized.
- * @param[in] hash      Hash function
- * @param[in] equals    Equals function
- * @param[in] init_size Initial hash set size
- *
- * @return True on success
- *
- */
-int hash_set_init(hash_set_t *h, hash_set_hash hash, hash_set_equals equals,
-    size_t init_size)
-{
-	assert(h);
-	assert(hash);
-	assert(equals);
-	
-	if (init_size < HASH_SET_MIN_SIZE)
-		init_size = HASH_SET_MIN_SIZE;
-	
-	h->table = malloc(init_size * sizeof(link_t));
-	if (!h->table)
-		return false;
-	
-	for (size_t i = 0; i < init_size; i++)
-		list_initialize(&h->table[i]);
-	
-	h->size = init_size;
-	h->count = 0;
-	h->hash = hash;
-	h->equals = equals;
-	
-	return true;
-}
-
-/** Destroy a hash table instance.
- *
- * @param h Hash table to be destroyed.
- *
- */
-void hash_set_destroy(hash_set_t *h)
-{
-	assert(h);
-	free(h->table);
-}
-
-/** Rehash the internal table to new table
- *
- * @param h         Original hash set
- * @param new_table Memory for the new table
- * @param new_size  Size of the new table
- */
-static void hash_set_rehash(hash_set_t *h, list_t *new_table,
-    size_t new_size)
-{
-	assert(new_size >= HASH_SET_MIN_SIZE);
-	
-	for (size_t bucket = 0; bucket < new_size; bucket++)
-		list_initialize(&new_table[bucket]);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			next = cur->next;
-			list_append(cur, &new_table[h->hash(cur) % new_size]);
-		}
-	}
-	
-	list_t *old_table = h->table;
-	h->table = new_table;
-	free(old_table);
-	h->size = new_size;
-}
-
-/** Insert item into the set.
- *
- * If the set already contains equivalent object,
- * the function fails.
- *
- * @param h    Hash table.
- * @param key  Array of all keys necessary to compute hash index.
- * @param item Item to be inserted into the hash table.
- *
- * @return True if the object was inserted
- * @return Ffalse if the set already contained equivalent object.
- *
- */
-int hash_set_insert(hash_set_t *h, link_t *item)
-{
-	assert(item);
-	assert(h);
-	assert(h->hash);
-	assert(h->equals);
-	
-	unsigned long hash = h->hash(item);
-	unsigned long chain = hash % h->size;
-	
-	list_foreach(h->table[chain], cur) {
-		if (h->equals(cur, item))
-			return false;
-	}
-	
-	if (h->count + 1 > h->size) {
-		size_t new_size = h->size * 2;
-		list_t *temp = malloc(new_size * sizeof(list_t));
-		if (temp != NULL)
-			hash_set_rehash(h, temp, new_size);
-		
-		/*
-		 * If the allocation fails, just use the same
-		 * old table and try to rehash next time.
-		 */
-		chain = hash % h->size;
-	}
-	
-	h->count++;
-	list_append(item, &h->table[chain]);
-	
-	return true;
-}
-
-/** Search the hash set for a matching object and return it
- *
- * @param h    Hash set
- * @param item The item that should equal to the matched object
- *
- * @return Matching item on success, NULL if there is no such item.
- *
- */
-link_t *hash_set_find(hash_set_t *h, const link_t *item)
-{
-	assert(h);
-	assert(h->hash);
-	assert(h->equals);
-	
-	unsigned long chain = h->hash(item) % h->size;
-	
-	list_foreach(h->table[chain], cur) {
-		if (h->equals(cur, item))
-			return cur;
-	}
-	
-	return NULL;
-}
-
-/** Remove first matching object from the hash set and return it
- *
- * @param h    Hash set.
- * @param item The item that should be equal to the matched object
- *
- * @return The removed item or NULL if this is not found.
- *
- */
-link_t *hash_set_remove(hash_set_t *h, const link_t *item)
-{
-	assert(h);
-	assert(h->hash);
-	assert(h->equals);
-	
-	link_t *cur = hash_set_find(h, item);
-	if (cur) {
-		list_remove(cur);
-		
-		h->count--;
-		if (4 * h->count < h->size && h->size > HASH_SET_MIN_SIZE) {
-			size_t new_size = h->size / 2;
-			if (new_size < HASH_SET_MIN_SIZE)
-				/* possible e.g. if init_size == HASH_SET_MIN_SIZE + 1 */
-				new_size = HASH_SET_MIN_SIZE;
-			
-			list_t *temp = malloc(new_size * sizeof (list_t));
-			if (temp != NULL)
-				hash_set_rehash(h, temp, new_size);
-		}
-	}
-	
-	return cur;
-}
-
-/** Remove all elements for which the function returned non-zero
- *
- * The function can also destroy the element.
- *
- * @param h   Hash set.
- * @param f   Function to be applied.
- * @param arg Argument to be passed to the function.
- *
- */
-void hash_set_remove_selected(hash_set_t *h, int (*f)(link_t *, void *),
-    void *arg)
-{
-	assert(h);
-	assert(h->table);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *prev = &h->table[bucket].head;
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			next = cur->next;
-			if (f(cur, arg)) {
-				prev->next = next;
-				next->prev = prev;
-				h->count--;
-			} else
-				prev = cur;
-		}
-	}
-	
-	if (4 * h->count < h->size && h->size > HASH_SET_MIN_SIZE) {
-		size_t new_size = h->size / 2;
-		if (new_size < HASH_SET_MIN_SIZE)
-			/* possible e.g. if init_size == HASH_SET_MIN_SIZE + 1 */
-			new_size = HASH_SET_MIN_SIZE;
-		
-		list_t *temp = malloc(new_size * sizeof (list_t));
-		if (temp != NULL)
-			hash_set_rehash(h, temp, new_size);
-	}
-}
-
-/** Apply function to all items in hash set
- *
- * @param h   Hash set.
- * @param f   Function to be applied.
- * @param arg Argument to be passed to the function.
- *
- */
-void hash_set_apply(hash_set_t *h, void (*f)(link_t *, void *), void *arg)
-{
-	assert(h);
-	assert(h->table);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			
-			/*
-			 * The next pointer must be stored prior to the functor
-			 * call to allow using destructor as the functor (the
-			 * free function could overwrite the cur->next pointer).
-			 */
-			next = cur->next;
-			f(cur, arg);
-		}
-	}
-}
-
-/** Remove all elements from the set.
- *
- * The table is reallocated to the minimum size.
- *
- * @param h   Hash set
- * @param f   Function (destructor?) applied to all element. Can be NULL.
- * @param arg Argument to the destructor.
- *
- */
-void hash_set_clear(hash_set_t *h, void (*f)(link_t *, void *), void *arg)
-{
-	assert(h);
-	assert(h->table);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			next = cur->next;
-			list_remove(cur);
-			if (f != NULL)
-				f(cur, arg);
-		}
-	}
-	
-	assert(h->size >= HASH_SET_MIN_SIZE);
-	list_t *new_table =
-	    realloc(h->table, HASH_SET_MIN_SIZE * sizeof(list_t));
-	
-	/* We are shrinking, therefore we shouldn't get NULL */
-	assert(new_table);
-	
-	if (h->table != new_table) {
-		/* Init the lists, pointers to itself are used in them */
-		for (size_t bucket = 0; bucket < HASH_SET_MIN_SIZE; ++bucket)
-			list_initialize(&new_table[bucket]);
-		
-		h->table = new_table;
-	}
-	
-	h->count = 0;
-	h->size = HASH_SET_MIN_SIZE;
-}
-
-/** Get hash set size
- *
- * @param hHash set
- *
- * @return Number of elements in the set.
- *
- */
-size_t hash_set_count(const hash_set_t *h)
-{
-	assert(h);
-	return h->count;
-}
-
-/** Check whether element is contained in the hash set
- *
- * @param h    Hash set
- * @param item Item that should be equal to the matched object
- *
- * @return True if the hash set contains equal object
- * @return False otherwise
- *
- */
-int hash_set_contains(const hash_set_t *h, const link_t *item)
-{
-	/*
-	 * The hash_set_find cannot accept constant hash set,
-	 * because we can modify the returned element. But in
-	 * this case we are using it safely.
-	 */
-	return hash_set_find((hash_set_t *) h, item) != NULL;
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision 0ca7286a618557bd1d13cded4ccbe25d62752237)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision 2732c94b5bd8edf3ef46b0da6138cc7619bd3be5)
@@ -219,5 +219,5 @@
  *
  */
-link_t *hash_table_find(hash_table_t *h, unsigned long key[])
+link_t *hash_table_find(const hash_table_t *h, unsigned long key[])
 {
 	assert(h && h->bucket);
Index: pace/lib/c/include/adt/hash_set.h
===================================================================
--- uspace/lib/c/include/adt/hash_set.h	(revision 0ca7286a618557bd1d13cded4ccbe25d62752237)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2006 Jakub Jermar
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_HASH_SET_H_
-#define LIBC_HASH_SET_H_
-
-#include <adt/list.h>
-#include <unistd.h>
-
-#define HASH_SET_MIN_SIZE  8
-
-typedef unsigned long (*hash_set_hash)(const link_t *);
-typedef int (*hash_set_equals)(const link_t *, const link_t *);
-
-/** Hash table structure. */
-typedef struct {
-	list_t *table;
-	
-	/** Current table size */
-	size_t size;
-	
-	/**
-	 * Current number of entries. If count > size,
-	 * the table is rehashed into table with double
-	 * size. If (4 * count < size) && (size > min_size),
-	 * the table is rehashed into table with half the size.
-	 */
-	size_t count;
-	
-	/** Hash function */
-	hash_set_hash hash;
-	
-	/** Hash table item equals function */
-	hash_set_equals equals;
-} hash_set_t;
-
-extern int hash_set_init(hash_set_t *, hash_set_hash, hash_set_equals, size_t);
-extern int hash_set_insert(hash_set_t *, link_t *);
-extern link_t *hash_set_find(hash_set_t *, const link_t *);
-extern int hash_set_contains(const hash_set_t *, const link_t *);
-extern size_t hash_set_count(const hash_set_t *);
-extern link_t *hash_set_remove(hash_set_t *, const link_t *);
-extern void hash_set_remove_selected(hash_set_t *,
-    int (*)(link_t *, void *), void *);
-extern void hash_set_destroy(hash_set_t *);
-extern void hash_set_apply(hash_set_t *, void (*)(link_t *, void *), void *);
-extern void hash_set_clear(hash_set_t *, void (*)(link_t *, void *), void *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/adt/hash_table.h
===================================================================
--- uspace/lib/c/include/adt/hash_table.h	(revision 0ca7286a618557bd1d13cded4ccbe25d62752237)
+++ uspace/lib/c/include/adt/hash_table.h	(revision 2732c94b5bd8edf3ef46b0da6138cc7619bd3be5)
@@ -91,5 +91,5 @@
 extern void hash_table_insert(hash_table_t *, link_t *);
 extern bool hash_table_insert_unique(hash_table_t *, link_t *);
-extern link_t *hash_table_find(hash_table_t *, unsigned long []);
+extern link_t *hash_table_find(const hash_table_t *, unsigned long []);
 extern size_t hash_table_remove(hash_table_t *, unsigned long [], size_t);
 extern void hash_table_remove_item(hash_table_t *, link_t *);
@@ -98,4 +98,5 @@
 	void *);
 
+
 #endif
 
Index: uspace/lib/c/include/adt/list.h
===================================================================
--- uspace/lib/c/include/adt/list.h	(revision 0ca7286a618557bd1d13cded4ccbe25d62752237)
+++ uspace/lib/c/include/adt/list.h	(revision 2732c94b5bd8edf3ef46b0da6138cc7619bd3be5)
@@ -102,4 +102,9 @@
 		iterator = next_iter, next_iter = iterator->next)
 
+#ifndef member_to_inst
+#define member_to_inst(ptr_member, type, member_identif) \
+	((type*) (((void*)(ptr_member)) - ((void*)&(((type*)0)->member_identif))))
+#endif
+
 
 #define assert_link_not_used(link) \
Index: uspace/lib/nic/include/nic_addr_db.h
===================================================================
--- uspace/lib/nic/include/nic_addr_db.h	(revision 0ca7286a618557bd1d13cded4ccbe25d62752237)
+++ uspace/lib/nic/include/nic_addr_db.h	(revision 2732c94b5bd8edf3ef46b0da6138cc7619bd3be5)
@@ -43,14 +43,5 @@
 #endif
 
-#include <adt/hash_set.h>
-
-/**
- * Initial size of DB's hash set
- */
-#define NIC_ADDR_DB_INIT_SIZE 	8
-/**
- * Maximal length of addresses in the DB (in bytes).
- */
-#define NIC_ADDR_MAX_LENGTH		16
+#include <adt/hash_table.h>
 
 /**
@@ -58,25 +49,14 @@
  */
 typedef struct nic_addr_db {
-	hash_set_t set;
+	hash_table_t set;
 	size_t addr_len;
 } nic_addr_db_t;
 
-/**
- * Helper structure for keeping the address in the hash set.
- */
-typedef struct nic_addr_entry {
-	link_t item;
-	size_t addr_len;
-	uint8_t addr[NIC_ADDR_MAX_LENGTH];
-} nic_addr_entry_t;
 
 extern int nic_addr_db_init(nic_addr_db_t *db, size_t addr_len);
 extern void nic_addr_db_clear(nic_addr_db_t *db);
 extern void nic_addr_db_destroy(nic_addr_db_t *db);
-extern size_t nic_addr_db_count(const nic_addr_db_t *db);
 extern int nic_addr_db_insert(nic_addr_db_t *db, const uint8_t *addr);
 extern int nic_addr_db_remove(nic_addr_db_t *db, const uint8_t *addr);
-extern void nic_addr_db_remove_selected(nic_addr_db_t *db,
-	int (*func)(const uint8_t *, void *), void *arg);
 extern int nic_addr_db_contains(const nic_addr_db_t *db, const uint8_t *addr);
 extern void nic_addr_db_foreach(const nic_addr_db_t *db,
Index: uspace/lib/nic/src/nic_addr_db.c
===================================================================
--- uspace/lib/nic/src/nic_addr_db.c	(revision 0ca7286a618557bd1d13cded4ccbe25d62752237)
+++ uspace/lib/nic/src/nic_addr_db.c	(revision 2732c94b5bd8edf3ef46b0da6138cc7619bd3be5)
@@ -42,47 +42,75 @@
 
 #include "nic_addr_db.h"
-
-/**
- * Hash set helper function
- */
-static int nic_addr_equals(const link_t *item1, const link_t *item2)
-{
-	assert(item1 && item2);
-	size_t addr_len = ((const nic_addr_entry_t *) item1)->addr_len;
-
-	assert(addr_len	== ((const nic_addr_entry_t *) item2)->addr_len);
-
-	size_t i;
-	for (i = 0; i < addr_len; ++i) {
-		if (((nic_addr_entry_t *) item1)->addr[i] !=
-			((nic_addr_entry_t *) item2)->addr[i])
-			return false;
+#include "adt/hash_table.h"
+//#include "string.h"
+
+
+/* Couple address bytes into KEY_CNT key fields. Align up to fit all bytes. */
+//#define KEY_CNT ((NIC_ADDR_MAX_LENGTH + sizeof(unsigned long) - 1) / sizeof(unsigned long))
+#define KEY_CNT 1
+
+/**
+ * Maximal length of addresses in the DB (in bytes).
+ */
+#define NIC_ADDR_MAX_LENGTH		16
+
+/**
+ * Helper structure for keeping the address in the hash set.
+ */
+typedef struct nic_addr_entry {
+	link_t link;
+	uint8_t addr[NIC_ADDR_MAX_LENGTH];
+} nic_addr_entry_t;
+
+
+/* 
+ * Hash table helper functions 
+ */
+
+static bool nic_addr_match(unsigned long *key, size_t key_cnt, 
+	const link_t *item)
+{
+	/* Ugly type-punning hack. */
+	uint8_t *addr = (uint8_t*)key;
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+
+	return 0 == bcmp(entry->addr, addr, NIC_ADDR_MAX_LENGTH);
+}
+
+static size_t nic_addr_key_hash(unsigned long *key)
+{
+	uint8_t *addr = (uint8_t*)key;
+	size_t hash = 0;
+
+	for (int i = NIC_ADDR_MAX_LENGTH - 1; i >= 0; --i) {
+		hash = (hash << 8) ^ (hash >> 24) ^ addr[i];
 	}
-	return true;
-}
-
-/**
- * Hash set helper function
- */
-static unsigned long nic_addr_hash(const link_t *item)
-{
-	assert(item);
-	const nic_addr_entry_t *entry = (const nic_addr_entry_t *) item;
-	unsigned long hash = 0;
-
-	size_t i;
-	for (i = 0; i < entry->addr_len; ++i) {
-		hash = (hash << 8) ^ (hash >> 24) ^ entry->addr[i];
-	}
+	
 	return hash;
 }
 
-/**
- * Helper wrapper
- */
-static void nic_addr_destroy(link_t *item, void *unused)
-{
-	free(item);
-}
+static size_t nic_addr_hash(const link_t *item)
+{
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+	
+	/* Ugly type-punning hack. */
+	unsigned long *key = (unsigned long*)entry->addr;
+	return nic_addr_key_hash(key);
+}
+
+static void nic_addr_removed(link_t *item)
+{
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+	
+	free(entry);
+}
+
+static hash_table_ops_t set_ops = {
+	.hash = nic_addr_hash,
+	.key_hash = nic_addr_key_hash,
+	.match = nic_addr_match,
+	.equal = 0,
+	.remove_callback = nic_addr_removed
+};
 
 /**
@@ -102,8 +130,8 @@
 		return EINVAL;
 	}
-	if (!hash_set_init(&db->set, nic_addr_hash, nic_addr_equals,
-		NIC_ADDR_DB_INIT_SIZE)) {
+	
+	if (!hash_table_create(&db->set, 0, KEY_CNT, &set_ops))
 		return ENOMEM;
-	}
+	
 	db->addr_len = addr_len;
 	return EOK;
@@ -118,5 +146,5 @@
 {
 	assert(db);
-	hash_set_clear(&db->set, nic_addr_destroy, NULL);
+	hash_table_clear(&db->set);
 }
 
@@ -129,20 +157,8 @@
 {
 	assert(db);
-	hash_set_apply(&db->set, nic_addr_destroy, NULL);
-	hash_set_destroy(&db->set);
-}
-
-/**
- * Get number of addresses in the db
- *
- * @param	db
- *
- * @return Number of adresses
- */
-size_t nic_addr_db_count(const nic_addr_db_t *db)
-{
-	assert(db);
-	return hash_set_count(&db->set);
-}
+	nic_addr_db_clear(db);
+	hash_table_destroy(&db->set);
+}
+
 
 /**
@@ -160,12 +176,21 @@
 {
 	assert(db && addr);
-	nic_addr_entry_t *entry = malloc(sizeof (nic_addr_entry_t));
-	if (entry == NULL) {
+	/* Ugly type-punning hack. */
+	unsigned long *key = (unsigned long*)addr;
+	
+	if (hash_table_find(&db->set, key))
+		return EEXIST;
+	
+	nic_addr_entry_t *entry = malloc(sizeof(nic_addr_entry_t));
+	if (entry == NULL) 
 		return ENOMEM;
-	}
-	entry->addr_len = db->addr_len;
+	
+	link_initialize(&entry->link);
+	
+	bzero(entry->addr, NIC_ADDR_MAX_LENGTH);
 	memcpy(entry->addr, addr, db->addr_len);
-
-	return hash_set_insert(&db->set, &entry->item) ? EOK : EEXIST;
+	
+	hash_table_insert(&db->set, &entry->link);
+	return EOK;
 }
 
@@ -182,11 +207,14 @@
 {
 	assert(db && addr);
-	nic_addr_entry_t entry;
-	entry.addr_len = db->addr_len;
-	memcpy(entry.addr, addr, db->addr_len);
-
-	link_t *removed = hash_set_remove(&db->set, &entry.item);
-	free(removed);
-	return removed != NULL ? EOK : ENOENT;
+	unsigned long *key = (unsigned long*)addr;
+	
+	link_t *item = hash_table_find(&db->set, key);
+	
+	if (item) {
+		hash_table_remove_item(&db->set, item);
+		return EOK;
+	} else {
+		return ENOENT;
+	}
 }
 
@@ -202,9 +230,7 @@
 {
 	assert(db && addr);
-	nic_addr_entry_t entry;
-	entry.addr_len = db->addr_len;
-	memcpy(entry.addr, addr, db->addr_len);
-
-	return hash_set_contains(&db->set, &entry.item);
+	unsigned long *key = (unsigned long*)addr;
+	
+	return 0 != hash_table_find(&db->set, key);
 }
 
@@ -220,7 +246,10 @@
  * Helper function for nic_addr_db_foreach
  */
-static void nic_addr_db_fe_helper(link_t *item, void *arg) {
+static bool nic_addr_db_fe_helper(link_t *item, void *arg) 
+{
 	nic_addr_db_fe_arg_t *hs = (nic_addr_db_fe_arg_t *) arg;
-	hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+	hs->func(entry->addr, hs->arg);
+	return true;
 }
 
@@ -237,39 +266,5 @@
 {
 	nic_addr_db_fe_arg_t hs = { .func = func, .arg = arg };
-	hash_set_apply((hash_set_t *) &db->set, nic_addr_db_fe_helper, &hs);
-}
-
-/**
- * Helper structure for nic_addr_db_remove_selected
- */
-typedef struct {
-	int (*func)(const uint8_t *, void *);
-	void *arg;
-} nic_addr_db_rs_arg_t;
-
-/**
- * Helper function for nic_addr_db_foreach
- */
-static int nic_addr_db_rs_helper(link_t *item, void *arg) {
-	nic_addr_db_rs_arg_t *hs = (nic_addr_db_rs_arg_t *) arg;
-	int retval = hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
-	if (retval) {
-		free(item);
-	}
-	return retval;
-}
-
-/**
- * Removes all addresses for which the function returns non-zero.
- *
- * @param	db
- * @param	func	User-defined function
- * @param	arg		Custom argument passed to the function
- */
-void nic_addr_db_remove_selected(nic_addr_db_t *db,
-	int (*func)(const uint8_t *, void *), void *arg)
-{
-	nic_addr_db_rs_arg_t hs = { .func = func, .arg = arg };
-	hash_set_remove_selected(&db->set, nic_addr_db_rs_helper, &hs);
+	hash_table_apply((hash_table_t*)&db->set, nic_addr_db_fe_helper, &hs);
 }
 
