ospfd: Extend 'ip ospf area' to take address argument + rationalise ospf enable

* ospfd.c: (general) Clean up the whole running of OSPF on interfaces.
  (add_ospf_interface) taking (struct interface *) arg is pointless here.
  (ospf_is_ready) new helper.
  (ospf_network_run_subnet) Put all the code for choosing whether to enable
  OSPF on a subnet, and if so which area configuration to use, here. If a
  subnet should not be enabled, ensure an existing oi is freed.
  (ospf_network_run_interface) Just call run_subnet for all subnets on an
  interface.
  (ospf_network_run) Just call run_interface for all interfaces.
  (ospf_if_update) Just call run_interface for the given interface.
  (ospf_network_unset) Just call run_subnet for existing ois.
  (ospf_update_interface_area) helper: update area on an oi, or create it.
  (ospf_interface_set) renamed to ospf_interface_area_set for clarity.
  Ensures OSPF is created, then into if_update.
  (ospf_interface_unset) renamed to ospf_interface_area_unset and collapses
  down to simple loop to call run_subnet for all ois.
* ospf_interface.h: add a more general OSPF_IF_PARAM_IS_SET, which does the
  right thing and takes default config into account.
* ospf_vty.c: (OSPF_VTY_GET_IF_PARAMS) new macro with common code for handling
  interface parameter commands - only used for 'ip ospf area' in this commit.
  (OSPF_VTY_PARAM_UNSET) similar
  ({no,}ip_ospf_area) Use said macros.
* doc/ospfd.texi: add 'ip ospf area' command.

Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
diff --git a/doc/ospfd.texi b/doc/ospfd.texi
index 856a2ba..7ddc9db 100644
--- a/doc/ospfd.texi
+++ b/doc/ospfd.texi
@@ -216,6 +216,7 @@
 @deffnx {OSPF Command} {network @var{a.b.c.d/m} area @var{<0-4294967295>}} {}
 @deffnx {OSPF Command} {no network @var{a.b.c.d/m} area @var{a.b.c.d}} {}
 @deffnx {OSPF Command} {no network @var{a.b.c.d/m} area @var{<0-4294967295>}} {}
+@anchor{OSPF network command}
 This command specifies the OSPF enabled interface(s).  If the interface has
 an address from range 192.168.1.0/24 then the command below enables ospf
 on this interface so router can provide network information to the other
@@ -239,6 +240,10 @@
 then we test whether the prefix in the network command contains
 the destination prefix.  Otherwise, we test whether the network command prefix
 contains the local address prefix of the interface. 
+
+In some cases it may be more convenient to enable OSPF on a per
+interface/subnet basis (@pxref{OSPF ip ospf area command}).
+
 @end deffn
 
 @node OSPF area
@@ -406,6 +411,19 @@
 @node OSPF interface
 @section OSPF interface
 
+@deffn {Interface Command} {ip ospf area @var{AREA} [@var{ADDR}]} {} 
+@deffnx {Interface Command} {no ip ospf area [@var{ADDR}]} {}
+@anchor{OSPF ip ospf area command}
+
+Enable OSPF on the interface, optionally restricted to just the IP address
+given by @var{ADDR}, putting it in the @var{AREA} area. Per interface area
+settings take precedence to network commands (@pxref{OSPF network command}).
+
+If you have a lot of interfaces, and/or a lot of subnets, then enabling OSPF
+via this command may result in a slight performance improvement.
+
+@end deffn
+
 @deffn {Interface Command} {ip ospf authentication-key @var{AUTH_KEY}} {}
 @deffnx {Interface Command} {no ip ospf authentication-key} {}
 Set OSPF authentication key to a simple password.  After setting @var{AUTH_KEY},
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index a437bfb..2ed426f 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -30,8 +30,17 @@
 #define IF_DEF_PARAMS(I) (IF_OSPF_IF_INFO (I)->def_params)
 #define IF_OIFS(I)  (IF_OSPF_IF_INFO (I)->oifs)
 #define IF_OIFS_PARAMS(I) (IF_OSPF_IF_INFO (I)->params)
-			    
+
+/* Despite the name, this macro probably is for specialist use only */
 #define OSPF_IF_PARAM_CONFIGURED(S, P) ((S) && (S)->P##__config)
+
+/* Test whether an OSPF interface parameter is set, generally, given some
+ * existing ospf interface
+ */
+#define OSPF_IF_PARAM_IS_SET(O,P) \
+      (OSPF_IF_PARAM_CONFIGURED ((O)->params, P) || \
+      OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp)->P))
+
 #define OSPF_IF_PARAM(O, P) \
         (OSPF_IF_PARAM_CONFIGURED ((O)->params, P)?\
                         (O)->params->P:IF_DEF_PARAMS((O)->ifp)->P)
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index dd4d312..45a19c0 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -292,6 +292,41 @@
     }
 }
 
+/* get the appropriate ospf parameters structure, checking if
+ * there's a valid interface address at the argi'th argv index
+ */
+enum {
+  VTY_SET = 0,
+  VTY_UNSET,
+};
+#define OSPF_VTY_GET_IF_PARAMS(ifp,params,argi,addr,set) \
+  (params) = IF_DEF_PARAMS ((ifp));           \
+                                              \
+  if (argc == (argi) + 1)                     \
+    {                                         \
+      int ret = inet_aton(argv[(argi)], &(addr)); \
+      if (!ret)                               \
+	{                                     \
+	  vty_out (vty, "Please specify interface address by A.B.C.D%s", \
+		   VTY_NEWLINE);              \
+	  return CMD_WARNING;                 \
+	}                                     \
+      (params) = ospf_get_if_params ((ifp), (addr)); \
+                                              \
+      if (set)                                \
+        ospf_if_update_params ((ifp), (addr));  \
+      else if ((params) == NULL)              \
+        return CMD_SUCCESS;                   \
+    }
+
+#define OSPF_VTY_PARAM_UNSET(params,var,ifp,addr) \
+  UNSET_IF_PARAM ((params), var);               \
+    if ((params) != IF_DEF_PARAMS ((ifp)))        \
+    {                                             \
+      ospf_free_if_params ((ifp), (addr));        \
+      ospf_if_update_params ((ifp), (addr));      \
+    }
+
 DEFUN (ospf_passive_interface,
        ospf_passive_interface_addr_cmd,
        "passive-interface IFNAME A.B.C.D",
@@ -453,7 +488,7 @@
        "OSPF area ID in IP address format\n"
        "OSPF area ID as a decimal value\n")
 {
-  struct ospf *ospf= vty->index;
+  struct ospf *ospf = vty->index;
   struct prefix_ipv4 p;
   struct in_addr area_id;
   int ret, format;
@@ -5885,31 +5920,28 @@
 
 DEFUN (ip_ospf_area,
        ip_ospf_area_cmd,
-       "ip ospf area (A.B.C.D|<0-4294967295>)",
+       "ip ospf area (A.B.C.D|<0-4294967295>) [A.B.C.D]",
        "IP Information\n"
        "OSPF interface commands\n"
        "Enable OSPF on this interface\n"
        "OSPF area ID in IP address format\n"
-       "OSPF area ID as a decimal value\n")
+       "OSPF area ID as a decimal value\n"
+       "Address of interface\n")
 {
   struct interface *ifp = vty->index;
-  int format, ret;
   struct in_addr area_id;
-  struct ospf *ospf;
+  struct in_addr addr;
+  int format;
   struct ospf_if_params *params;
 
-  ret = ospf_str2area_id (argv[0], &area_id, &format);
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
 
-  if (ret < 0)
-    {
-      vty_out (vty, "Please specify area by A.B.C.D|<0-4294967295>%s",
-	       VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-  params = IF_DEF_PARAMS (ifp);
+  OSPF_VTY_GET_IF_PARAMS(ifp, params, 1, addr, VTY_SET);
+  
   if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
     {
-      vty_out (vty, "There is already a interface statement.%s", VTY_NEWLINE);
+      vty_out (vty, "There is already an interface area statement.%s",
+              VTY_NEWLINE);
       return CMD_WARNING;
     }
   if (memcmp (ifp->name, "VLINK", 5) == 0)
@@ -5917,33 +5949,36 @@
       vty_out (vty, "Cannot enable OSPF on a virtual link.%s", VTY_NEWLINE);
       return CMD_WARNING;
     }
-
+  
   SET_IF_PARAM (params, if_area);
   params->if_area = area_id;
-  ospf_interface_set (ifp);
+  ospf_interface_area_set (ifp);
 
   return CMD_SUCCESS;
 }
 
 DEFUN (no_ip_ospf_area,
        no_ip_ospf_area_cmd,
-       "no ip ospf area",
+       "no ip ospf area [A.B.C.D]",
        NO_STR
        "IP Information\n"
        "OSPF interface commands\n"
-       "Disable OSPF on this interface\n")
+       "Disable OSPF on this interface\n"
+       "Address of interface\n")
 {
   struct interface *ifp = vty->index;
-  struct ospf *ospf;
   struct ospf_if_params *params;
+  struct in_addr addr;
 
-  params = IF_DEF_PARAMS (ifp);
+  OSPF_VTY_GET_IF_PARAMS(ifp, params, 0, addr, VTY_UNSET);
+  
   if (!OSPF_IF_PARAM_CONFIGURED(params, if_area))
     return CMD_SUCCESS;
+  
+  OSPF_VTY_PARAM_UNSET(params, if_area, ifp, addr);
+  
+  ospf_interface_area_unset (ifp);
 
-  UNSET_IF_PARAM (params, if_area);
-
-  ospf_interface_unset (ifp);
   return CMD_SUCCESS;
 }
 
@@ -7014,9 +7049,10 @@
 	/* Area  print. */
 	if (OSPF_IF_PARAM_CONFIGURED (params, if_area))
 	  {
-	    vty_out (vty, " ip ospf area %s%s",
-		     inet_ntoa (params->if_area),
-		     VTY_NEWLINE);
+	    vty_out (vty, " ip ospf area %s", inet_ntoa (params->if_area));
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+            vty_out (vty, "%s", VTY_NEWLINE);
 	  }
 
     /* MTU ignore print. */
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index f6669d7..c317ed8 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -69,8 +69,10 @@
 static void ospf_network_free (struct ospf *, struct ospf_network *);
 static void ospf_area_free (struct ospf_area *);
 static void ospf_network_run (struct prefix *, struct ospf_area *);
-static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
-                                        struct interface *);
+static void ospf_network_run_interface (struct ospf *, struct interface *, 
+                                        struct prefix *, struct ospf_area *);
+static void ospf_network_run_subnet (struct ospf *, struct connected *, 
+                                     struct prefix *, struct ospf_area *);
 static int ospf_network_match_iface (const struct connected *,
 				     const struct prefix *);
 static void ospf_finish_final (struct ospf *);
@@ -256,6 +258,16 @@
   return listgetdata (listhead (om->ospf));
 }
 
+static int
+ospf_is_ready (struct ospf *ospf)
+{
+  /* OSPF must be on and Router-ID must be configured. */
+  if (!ospf || ospf->router_id.s_addr == 0)
+    return 0;
+  
+  return 1;
+}
+
 static void
 ospf_add (struct ospf *ospf)
 {
@@ -743,18 +755,17 @@
   return new;
 }
 
-static void
-add_ospf_interface (struct interface *ifp, struct ospf_area *area,
-                    struct connected *co)
+static void 
+add_ospf_interface (struct connected *co, struct ospf_area *area)
 {
   struct ospf_interface *oi;
 
-  oi = ospf_if_new (area->ospf, ifp, co->address);
+  oi = ospf_if_new (area->ospf, co->ifp, co->address);
   oi->connected = co;
 
   oi->area = area;
 
-  oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
+  oi->params = ospf_lookup_if_params (co->ifp, oi->address->u.prefix4);
   oi->output_cost = ospf_if_get_output_cost (oi);
 
   /* Add pseudo neighbor. */
@@ -766,7 +777,7 @@
   /* update network type as interface flag */
   /* If network type is specified previously,
      skip network type setting. */
-  oi->type = IF_DEF_PARAMS (ifp)->type;
+  oi->type = IF_DEF_PARAMS (co->ifp)->type;
 
   ospf_area_add_if (oi->area, oi);
 
@@ -776,7 +787,7 @@
    * whenever r-id is configured instead.
    */
   if ((area->ospf->router_id.s_addr != 0)
-      && if_is_operative (ifp)) 
+      && if_is_operative (co->ifp)) 
     ospf_if_up (oi);
 }
 
@@ -797,7 +808,7 @@
                 if (ospf_external_info_find_lsa (ospf, &ei->p))
                   if (!ospf_distribute_check_connected (ospf, ei))
                     ospf_external_lsa_flush (ospf, ei->type, &ei->p,
-                                             ei->ifindex /*, ei->nexthop */);
+                                              ei->ifindex /*, ei->nexthop */);
               }
             else
               {
@@ -840,7 +851,8 @@
   ospf_network_run ((struct prefix *)p, area);
 
   /* Update connected redistribute. */
-  update_redistributed(ospf, 1); /* interfaces possibly added */
+  update_redistributed(ospf, 1);
+  
   ospf_area_check_free (ospf, area_id);
 
   return 1;
@@ -871,131 +883,64 @@
   /* Find interfaces that not configured already.  */
   for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
     {
-      struct ospf_if_params *params;
-      int found = 0;
-      struct connected *co = oi->connected;
-      
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
         continue;
       
-      params = IF_DEF_PARAMS (oi->ifp);
-      if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
-        continue;
-      
-      for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
-        {
-          if (rn->info == NULL)
-            continue;
-          
-          if (ospf_network_match_iface(co,&rn->p))
-            {
-              found = 1;
-              route_unlock_node (rn);
-              break;
-            }
-        }
-
-      if (found == 0)
-	{
-	  ospf_if_free (oi);
-	  ospf_area_check_free (ospf, area_id);
-	}
+      ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
     }
   
   /* Update connected redistribute. */
-  update_redistributed(ospf, 0); /* interfaces possibly removed */
-  return 1;
-}
-
-int
-ospf_interface_set (struct interface *ifp)
-{
-  struct ospf_area *area;
-  struct listnode *cnode;
-  struct connected *co;
-  struct ospf *ospf;
-  struct ospf_if_params *params;
-  struct in_addr area_id;
-  int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
-
-  if ((ospf = ospf_lookup ()) == NULL)
-      return 1; /* Ospf not ready yet */
-
-  params = IF_DEF_PARAMS (ifp);
-  area_id = params->if_area;
-
-  area = ospf_area_get (ospf, area_id, ret);
- 
-  for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
-    {
-      struct ospf_interface *oi;
-
-      if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
-	continue;
-
-      oi = ospf_if_table_lookup(ifp, co->address);
-      if (oi) 
-	{ /* Just adjust area for existing interface */
-	  ospf_area_del_if (oi->area, oi);
-	  oi->area = area;
-	  ospf_area_add_if (oi->area, oi);
-	}
-      else
-	{
-	  add_ospf_interface(ifp, area, co);
-	}
-    }
-
-  /* Update connected redistribute. */
-  update_redistributed(ospf, 1); /* interface possibly added */
+  update_redistributed(ospf, 0);
+  
   ospf_area_check_free (ospf, area_id);
-
+  
   return 1;
 }
 
-int
-ospf_interface_unset (struct interface *ifp)
+/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
+ * there might not be any 'router ospf' config.
+ *
+ * Otherwise, doesn't do anything different to ospf_if_update for now
+ */
+void
+ospf_interface_area_set (struct interface *ifp)
 {
-  struct route_node *rn_oi, *rn;
+  struct ospf *ospf = ospf_get();
+  
+  ospf_if_update (ospf, ifp);
+  /* if_update does a update_redistributed */
+  
+  return;
+}
+
+void
+ospf_interface_area_unset (struct interface *ifp)
+{
+  struct route_node *rn_oi;
   struct ospf *ospf;
 
   if ((ospf = ospf_lookup ()) == NULL)
-    return 1; /* Ospf not ready yet */
-
+    return; /* Ospf not ready yet */
+  
   /* Find interfaces that may need to be removed. */
   for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi))
     {
       struct ospf_interface *oi;
-      struct connected *co;
-      int found = 0;
 
       if ( (oi = rn_oi->info) == NULL)
 	continue;
+      
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
 	continue;
-      co = oi->connected;
-
-      for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
-	{
-	  if (rn->info == NULL)
-	    continue;
-
-	  if (ospf_network_match_iface(co,&rn->p))
-	    {
-	      found = 1;
-	      route_unlock_node (rn);
-	      break;
-	    }
-	}
-
-      if (found == 0)
-	ospf_if_free (oi);
+      
+      ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
     }
 
   /* Update connected redistribute. */
-  update_redistributed(ospf, 0); /* interfaces possibly removed */
-   return 1;
- }
+  update_redistributed (ospf, 0); /* interfaces possibly removed */
+  
+  return;
+}
 
 
 /* Check whether interface matches given network
@@ -1009,8 +954,101 @@
 }
 
 static void
-ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
-                            struct interface *ifp)
+ospf_update_interface_area (struct connected *co, struct ospf_area *area)
+{
+  struct ospf_interface *oi = ospf_if_table_lookup (co->ifp, co->address);
+  
+  /* nothing to be done case */
+  if (oi && oi->area == area)
+    return;
+  
+  if (oi) 
+    ospf_if_free (oi);
+  
+  add_ospf_interface (co, area);
+}
+
+/* Run OSPF for the given subnet, taking into account the following
+ * possible sources of area configuration, in the given order of preference:
+ *
+ * - Whether there is interface+address specific area configuration
+ * - Whether there is a default area for the interface
+ * - Whether there is an area given as a parameter.
+ * - If no specific network prefix/area is supplied, whether there's
+ *   a matching network configured.
+ */
+static void
+ospf_network_run_subnet (struct ospf *ospf, struct connected *co,
+                         struct prefix *p, struct ospf_area *given_area)
+{
+  struct ospf_interface *oi;
+  struct ospf_if_params *params;
+  struct ospf_area *area = NULL;
+  struct route_node *rn;
+  int configed = 0;
+  
+  if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
+    return;
+  
+  if (co->address->family != AF_INET)
+    return;
+  
+  /* Try determine the appropriate area for this interface + address
+   * Start by checking interface config 
+   */   
+  if (!(params = ospf_lookup_if_params (co->ifp, co->address->u.prefix4)))
+    params = IF_DEF_PARAMS (co->ifp);
+  
+  if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
+    area = (ospf_area_get (ospf, params->if_area,
+                           OSPF_AREA_ID_FORMAT_ADDRESS));
+  
+  /* If we've found an interface and/or addr specific area, then we're
+   * done
+   */
+  if (area)
+    {
+      ospf_update_interface_area (co, area);
+      return;
+    }
+  
+  /* Otherwise, only remaining possibility is a matching network statement */
+  if (p)
+    {
+      assert (given_area != NULL);
+      
+      /* Which either was supplied as a parameter.. (e.g. cause a new
+       * network/area was just added)..
+       */
+      if (p->family == co->address->family 
+          && ospf_network_match_iface (co, p))
+        ospf_update_interface_area (co, given_area);
+      
+      return;
+    }
+  
+  /* Else we have to search the existing network/area config to see
+   * if any match..
+   */
+  for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
+    if (rn->info != NULL
+        && ospf_network_match_iface (co, &rn->p))
+      {
+        struct ospf_network *network = (struct ospf_network *) rn->info;
+        area = ospf_area_get (ospf, network->area_id, network->format);
+        ospf_update_interface_area (co, area);
+        configed = 1;
+      }
+  
+  /* If the subnet isn't in any area, deconfigure */
+  if (!configed && (oi = ospf_if_table_lookup (co->ifp, co->address)))
+    ospf_if_free (oi);
+}
+
+static void
+ospf_network_run_interface (struct ospf *ospf, struct interface *ifp,
+                            struct prefix *p,
+                            struct ospf_area *given_area)
 {
   struct listnode *cnode;
   struct connected *co;
@@ -1018,21 +1056,14 @@
   if (memcmp (ifp->name, "VLINK", 5) == 0)
     return;
   
+  /* Network prefix without area is nonsensical */
+  if (p)
+    assert (given_area != NULL);
+  
   /* if interface prefix is match specified prefix,
      then create socket and join multicast group. */
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
-    {
-
-      if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
-        continue;
-
-      if (p->family == co->address->family 
-	  && ! ospf_if_table_lookup(ifp, co->address)
-          && ospf_network_match_iface(co,p))
-	{
-	  add_ospf_interface(ifp, area, co);
-	}
-    }
+    ospf_network_run_subnet (ospf, co, p, given_area);  
 }
 
 static void
@@ -1047,7 +1078,7 @@
   
   /* Get target interface. */
   for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
-    ospf_network_run_interface (p, area, ifp);
+    ospf_network_run_interface (area->ospf, ifp, p, area);
 }
 
 void
@@ -1080,30 +1111,17 @@
 void
 ospf_if_update (struct ospf *ospf, struct interface *ifp)
 {
-  struct route_node *rn;
-  struct ospf_network *network;
-  struct ospf_area *area;
-  
   if (!ospf)
     ospf = ospf_lookup ();
 
-  /* OSPF must be on and Router-ID must be configured. */
-  if (!ospf || ospf->router_id.s_addr == 0)
+  /* OSPF must be ready. */
+  if (!ospf_is_ready (ospf))
     return;
   
-  if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS (ifp), if_area))
-    ospf_interface_set (ifp);
-  else
-    {
-      /* Run each netowrk for this interface. */
-      for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
-	if (rn->info != NULL)
-	  {
-	    network = (struct ospf_network *) rn->info;
-	    area = ospf_area_get (ospf, network->area_id, network->format);
-	    ospf_network_run_interface (&rn->p, area, ifp);
-	  }
-    }
+  ospf_network_run_interface (ospf, ifp, NULL, NULL);
+  
+  /* Update connected redistribute. */
+  update_redistributed(ospf, 1);
 }
 
 void
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index c50e615..595c04f 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -563,6 +563,9 @@
 extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *);
 extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *);
 
+extern void ospf_interface_area_set (struct interface *);
+extern void ospf_interface_area_unset (struct interface *);
+
 extern void ospf_route_map_init (void);
 extern void ospf_snmp_init (void);