Initial revision
diff --git a/ospf6d/ospf6_linklist.c b/ospf6d/ospf6_linklist.c
new file mode 100644
index 0000000..8c17935
--- /dev/null
+++ b/ospf6d/ospf6_linklist.c
@@ -0,0 +1,193 @@
+
+#include <zebra.h>
+
+#include "ospf6_linklist.h"
+
+static struct linklist_node *
+linklist_lookup_node (void *data, struct linklist *linklist)
+{
+ struct linklist_node *node;
+
+ for (node = linklist->head; node; node = node->next)
+ {
+ if (linklist->cmp && (*linklist->cmp) (node->data, data) == 0)
+ return node;
+ if (node->data == data)
+ return node;
+ }
+
+ return NULL;
+}
+
+void *
+linklist_lookup (void *data, struct linklist *linklist)
+{
+ struct linklist_node *node;
+
+ node = linklist_lookup_node (data, linklist);
+ if (node)
+ return node->data;
+ return NULL;
+}
+
+int
+linklist_add (void *data, struct linklist *linklist)
+{
+ struct linklist_node *node = NULL, *add;
+
+ if (linklist_lookup_node (data, linklist))
+ return -1;
+
+ add = malloc (sizeof (struct linklist_node));
+ if (add == NULL)
+ return -1;
+ memset (add, 0, sizeof (struct linklist_node));
+ add->data = data;
+
+ if (linklist->cmp)
+ {
+ for (node = linklist->head; node; node = node->next)
+ {
+ if ((*linklist->cmp) (node->data, add->data) > 0)
+ break;
+ }
+ }
+
+ if (! node)
+ {
+ /* add to tail */
+ if (linklist->tail)
+ {
+ linklist->tail->next = add;
+ add->prev = linklist->tail;
+ }
+ else
+ {
+ linklist->head = add;
+ add->prev = NULL;
+ }
+
+ linklist->tail = add;
+ add->next = NULL;
+ }
+ else
+ {
+ /* insert just before 'node' */
+ if (node->prev)
+ {
+ node->prev->next = add;
+ add->prev = node->prev;
+ }
+ else
+ {
+ linklist->head = add;
+ add->prev = NULL;
+ }
+
+ add->next = node;
+ node->prev = add;
+ }
+
+ linklist->count++;
+ return 0;
+}
+
+int
+linklist_remove (void *data, struct linklist *linklist)
+{
+ struct linklist_node *rem;
+
+ rem = linklist_lookup_node (data, linklist);
+ if (rem == NULL)
+ return -1;
+
+ if (rem->prev)
+ rem->prev->next = rem->next;
+ else
+ linklist->head = rem->next;
+
+ if (rem->next)
+ rem->next->prev = rem->prev;
+ else
+ linklist->tail = rem->prev;
+
+ free (rem);
+ linklist->count--;
+ return 0;
+}
+
+void
+linklist_head (struct linklist *linklist, struct linklist_node *node)
+{
+ if (linklist->head == NULL)
+ {
+ node->prev = NULL;
+ node->next = NULL;
+ node->data = NULL;
+ return;
+ }
+
+ node->prev = linklist->head->prev;
+ node->next = linklist->head->next;
+ node->data = linklist->head->data;
+}
+
+int
+linklist_end (struct linklist_node *node)
+{
+ if (node->data == NULL && node->next == NULL)
+ return 1;
+ return 0;
+}
+
+void
+linklist_next (struct linklist_node *node)
+{
+ if (node->next == NULL)
+ {
+ node->prev = NULL;
+ node->next = NULL;
+ node->data = NULL;
+ return;
+ }
+
+ node->data = node->next->data;
+ node->prev = node->next->prev;
+ node->next = node->next->next;
+}
+
+struct linklist *
+linklist_create ()
+{
+ struct linklist *linklist;
+
+ linklist = malloc (sizeof (struct linklist));
+ if (linklist == NULL)
+ return NULL;
+ memset (linklist, 0, sizeof (struct linklist));
+
+ return linklist;
+}
+
+void
+linklist_remove_all (struct linklist *linklist)
+{
+ struct linklist_node node;
+
+ for (linklist_head (linklist, &node); ! linklist_end (&node);
+ linklist_next (&node))
+ linklist_remove (node.data, linklist);
+}
+
+void
+linklist_delete (struct linklist *linklist)
+{
+ linklist_remove_all (linklist);
+ assert (linklist->count == 0);
+ assert (linklist->head == NULL);
+ assert (linklist->tail == NULL);
+
+ free (linklist);
+}
+
+