ospf6d: handle Prefix and Router Options bits correctly

Ensure that prefixes with the NU/LA bit set do not get added to the routing
table. Ensure that routers with the V6/R bit set do not get added as transit
routes.

Signed-off-by: Dinesh Dutt <ddutt at cumulusnetworks.com>
[DL: adjust to rebase]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index 379a62e..54404ab 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -537,13 +537,13 @@
   int i;
   char buf[64];
   int is_debug = 0;
+  struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
+  struct ospf6_inter_router_lsa *router_lsa = NULL;
 
   memset (&prefix, 0, sizeof (prefix));
 
   if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
     {
-      struct ospf6_inter_prefix_lsa *prefix_lsa;
-
       if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
         {
           is_debug++;
@@ -564,8 +564,6 @@
     }
   else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
     {
-      struct ospf6_inter_router_lsa *router_lsa;
-
       if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
         {
           is_debug++;
@@ -632,6 +630,7 @@
     }
 
   /* (3) if the prefix is equal to an active configured address range */
+  /*     or if the NU bit is set in the prefix */
   if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
     {
       range = ospf6_route_lookup (&prefix, oa->range_table);
@@ -643,6 +642,32 @@
             ospf6_route_remove (old, table);
           return;
         }
+
+      if (CHECK_FLAG (prefix_lsa->prefix.prefix_options,
+		      OSPF6_PREFIX_OPTION_NU) ||
+	  CHECK_FLAG (prefix_lsa->prefix.prefix_options,
+		      OSPF6_PREFIX_OPTION_LA))
+	{
+          if (is_debug)
+            zlog_debug ("Prefix has NU/LA bit set, ignore");
+          if (old)
+            ospf6_route_remove (old, table);
+          return;
+	}
+    }
+
+  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
+    {
+      /* To pass test suites */
+      if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) ||
+	  ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6))
+	{
+          if (is_debug)
+            zlog_debug ("Prefix has NU/LA bit set, ignore");
+          if (old)
+            ospf6_route_remove (old, table);
+          return;
+	}
     }
 
   /* (4) if the routing table entry for the ABR does not exist */
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 27726c6..60df6e6 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -181,6 +181,13 @@
       return;
     }
 
+  if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
+    {
+      if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
+        zlog_debug ("Ignore LSA with NU bit set Metric");
+      return;
+    }
+
   ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
   asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
   if (asbr_entry == NULL ||
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 9c84e65..e86e46b 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -1562,6 +1562,10 @@
           ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
         continue;
 
+      if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) ||
+	  ! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R))
+	continue;
+
       copy = ospf6_route_copy (brouter);
       copy->type = OSPF6_DEST_TYPE_ROUTER;
       copy->path.area_id = oa->area_id;