2004-04-08 Paul Jakma <paul@dishone.st>

        * ospf_spf.h: Add backlink field to struct vertex
        * ospf_spf.h: (ospf_vertex_new) initialise backlink
          (ospf_lsa_has_link) return index of link back to
          vertex V from candidate vertex W, or -1 if no link exists.
          (ospf_spf_next) save backlink index for candidate vertex
        * ospf_interface.c: (ospf_vl_set_params) Use the backlink index
          to determine correct address for virtual-link peers. Fall back
          to older "pick first link" method if no backlink index exists.
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index acce907..b487291 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -933,24 +933,49 @@
       }
 
   rl = (struct router_lsa *)v->lsa;
-  
-  for (i = 0; i < ntohs (rl->links); i++)
+
+  /* use SPF determined backlink index in struct vertex
+   * for virtual link destination address
+   */
+  if (v->backlink >= 0)
     {
-      switch (rl->link[i].type)
+      if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
+                           &rl->link[v->backlink].link_data))
+        changed = 1;
+      vl_data->peer_addr = rl->link[v->backlink].link_data;
+    }
+  else
+    {
+      /* This is highly odd, there is no backlink index
+       * there should be due to the ospf_spf_has_link() check
+       * in SPF. Lets warn and try pick a link anyway.
+       */
+      zlog_warn ("ospf_vl_set_params: No backlink for %s!",
+                 vl_data->vl_oi->ifp->name);
+      for (i = 0; i < ntohs (rl->links); i++)
         {
-          case LSA_LINK_TYPE_VIRTUALLINK:
-            if (IS_DEBUG_OSPF_EVENT)
-              zlog_info ("found back link through VL");
-          case LSA_LINK_TYPE_TRANSIT:
-          case LSA_LINK_TYPE_POINTOPOINT:
-            vl_data->peer_addr = rl->link[i].link_data;
-          if (IS_DEBUG_OSPF_EVENT)
-            zlog_info ("%s peer address is %s\n",
-        	           vl_data->vl_oi->ifp->name, 
-        	           inet_ntoa(vl_data->peer_addr));
-          return changed;
+          switch (rl->link[i].type)
+            {
+              case LSA_LINK_TYPE_VIRTUALLINK:
+                if (IS_DEBUG_OSPF_EVENT)
+                  zlog_info ("found back link through VL");
+              case LSA_LINK_TYPE_TRANSIT:
+              case LSA_LINK_TYPE_POINTOPOINT:
+                vl_data->peer_addr = rl->link[i].link_data;
+              if (IS_DEBUG_OSPF_EVENT)
+                zlog_info ("%s peer address is %s\n",
+                               vl_data->vl_oi->ifp->name, 
+                               inet_ntoa(vl_data->peer_addr));
+              return changed;
+            }
         }
     }
+    
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_vl_set_params: %s peer address is %s\n",
+               vl_data->vl_oi->ifp->name,
+               inet_ntoa(vl_data->peer_addr));
+               
   return changed;
 }