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);
+}
+
+