2005-09-29 Alain Ritoux <alain.ritoux@6wind.com>

    * ospfd/ospf_vty.c: forece default route LSA to be re_issued whenever
      cost is changed ( [no] ip ospf area XXX default-cost YYY)
      Support ignore-mtu option
    * ospfd/ospfd.h: define OSPF_MTU_IGNORE_DEFAULT
    * ospfd/ospf_packet.c: support ignore-mtu option
    * ospfd/ospf_interface.h: field added for skipping MTU check
    * ospfd/ospf_interface.c: fix memory leak in ospf_crypt_key_delete()
      Set mtu_ignore field to default value
    * ospfd/ospf_abr.[ch]: export ospf_abr_announce_network_to_area()
    * ospfd/ospf_ism.h: add MACRO to convert internal ISM status into SNMP
      correct values
    * ospfd/ospf_snmp.c: add sanity check on LSA type in lsdb_lookup_next()
      convert OSPFIFSTATE internal status into SNMP values
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index bef4c64..2cc9a4f 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,19 @@
+2005-09-29 Alain Ritoux <alain.ritoux@6wind.com>
+
+	* ospf_vty.c: forece default route LSA to be re_issued whenever
+	  cost is changed ( [no] ip ospf area XXX default-cost YYY)
+	  Support ignore-mtu option
+	* ospfd.h: define OSPF_MTU_IGNORE_DEFAULT
+	* ospf_packet.c: support ignore-mtu option
+	* ospf_interface.h: field added for skipping MTU check 
+	* ospf_interface.c: fix memory leak in ospf_crypt_key_delete()
+	  Set mtu_ignore field to default value
+	* ospf_abr.[ch]: export ospf_abr_announce_network_to_area()
+	* ospf_ism.h: add MACRO to convert internal ISM status into SNMP
+	  correct values
+	* ospf_snmp.c: add sanity check on LSA type in lsdb_lookup_next()
+	  convert OSPFIFSTATE internal status into SNMP values
+
 2005-09-28 Alain Ritoux <alain.ritoux@6wind.com>
 
 	* ospf_packet.c: use new md5 API
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index 486ad95..2d47efe 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -707,7 +707,7 @@
      for lsa installation and flooding... to be added... */
 }
 
-static void
+void
 ospf_abr_announce_network_to_area (struct prefix_ipv4 *p, u_int32_t cost,
 				   struct ospf_area *area)
 {
diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h
index a85ec84..e367e44 100644
--- a/ospfd/ospf_abr.h
+++ b/ospfd/ospf_abr.h
@@ -88,4 +88,7 @@
 extern void ospf_abr_task (struct ospf *);
 extern void ospf_schedule_abr_task (struct ospf *);
 
+extern void ospf_abr_announce_network_to_area (struct prefix_ipv4 *, 
+                                               u_int32_t,
+                                               struct ospf_area *);
 #endif /* _ZEBRA_OSPF_ABR_H */
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 45fa023..9d31b7a 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -692,6 +692,8 @@
   SET_IF_PARAM (IF_DEF_PARAMS (ifp), priority);
   IF_DEF_PARAMS (ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
 
+  IF_DEF_PARAMS (ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT;
+
   SET_IF_PARAM (IF_DEF_PARAMS (ifp), passive_interface);
   IF_DEF_PARAMS (ifp)->passive_interface = OSPF_IF_ACTIVE;
 
@@ -1223,6 +1225,7 @@
       if (ck->key_id == key_id)
         {
           listnode_delete (auth_crypt, ck);
+          XFREE (MTYPE_OSPF_CRYPT_KEY, ck);
           return 1;
         }
     }
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 0e7f22a..2b12985 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -53,6 +53,9 @@
   DECLARE_IF_PARAM (u_int32_t, v_hello);             /* Hello Interval */
   DECLARE_IF_PARAM (u_int32_t, v_wait);              /* Router Dead Interval */
 
+  /* MTU mismatch check (see RFC2328, chap 10.6) */ 
+  DECLARE_IF_PARAM (u_char, mtu_ignore);
+
   /* Authentication data. */
   u_char auth_simple[OSPF_AUTH_SIMPLE_SIZE + 1];       /* Simple password. */
   u_char auth_simple__config:1;
diff --git a/ospfd/ospf_ism.h b/ospfd/ospf_ism.h
index 58f80c3..94d75b4 100644
--- a/ospfd/ospf_ism.h
+++ b/ospfd/ospf_ism.h
@@ -35,6 +35,10 @@
 #define ISM_DR                            7
 #define OSPF_ISM_STATE_MAX   	          8
 
+/* Because DR/DROther values are exhanged wrt RFC */
+#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \
+                     ((x) == ISM_DR) ? ISM_DROther : (x))
+
 /* OSPF Interface State Machine Event. */
 #define ISM_NoEvent                       0
 #define ISM_InterfaceUp                   1
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index ceb6a20..c869d3d 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -1111,7 +1111,8 @@
     }
 
   /* Check MTU. */
-  if (ntohs (dd->mtu) > oi->ifp->mtu)
+  if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) && 
+      (ntohs (dd->mtu) > oi->ifp->mtu))
     {
       zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
 		 inet_ntoa (nbr->router_id), ntohs (dd->mtu),
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index 4ed1fab..d0c1290 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -1,4 +1,5 @@
 /* OSPFv2 SNMP support
+ * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
  * Copyright (C) 2000 IP Infusion Inc.
  *
  * Written by Kunihiro Ishiguro <kunihiro@zebra.org>
@@ -885,6 +886,14 @@
   else
     i = *type;
 
+  /* Sanity check, if LSA type unknwon
+     merley skip any LSA */
+  if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA))
+    {
+      zlog_debug("Strange request with LSA type %d\n", i);
+      return NULL;
+    }
+
   for (; i < OSPF_MAX_LSA; i++)
     {
       *type = i;
@@ -1673,7 +1682,7 @@
       return SNMP_INTEGER (OSPF_POLL_INTERVAL_DEFAULT);
       break;
     case OSPFIFSTATE:		/* 12 */
-      return SNMP_INTEGER (oi->state);
+      return SNMP_INTEGER (ISM_SNMP(oi->state));
       break;
     case OSPFIFDESIGNATEDROUTER: /* 13 */
       return SNMP_IPADDRESS (DR (oi));
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index e8d0a38..1a2afac 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -1,4 +1,5 @@
 /* OSPF VTY interface.
+ * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
  * Copyright (C) 2000 Toshiaki Takada
  *
  * This file is part of GNU Zebra.
@@ -1661,6 +1662,7 @@
   struct in_addr area_id;
   u_int32_t cost;
   int format;
+  struct prefix_ipv4 p;
 
   VTY_GET_OSPF_AREA_ID_NO_BB ("default-cost", area_id, format, argv[0]);
   VTY_GET_INTEGER_RANGE ("stub default cost", cost, argv[1], 0, 16777215);
@@ -1675,6 +1677,15 @@
 
   area->default_cost = cost;
 
+  p.family = AF_INET;
+  p.prefix.s_addr = OSPF_DEFAULT_DESTINATION;
+  p.prefixlen = 0;
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_debug ("ospf_abr_announce_stub_defaults(): "
+                "announcing 0.0.0.0/0 to area %s",
+               inet_ntoa (area->area_id));
+  ospf_abr_announce_network_to_area (&p, area->default_cost, area);
+
   return CMD_SUCCESS;
 }
 
@@ -1693,6 +1704,7 @@
   struct in_addr area_id;
   u_int32_t cost;
   int format;
+  struct prefix_ipv4 p;
 
   VTY_GET_OSPF_AREA_ID_NO_BB ("default-cost", area_id, format, argv[0]);
   VTY_GET_INTEGER_RANGE ("stub default cost", cost, argv[1], 0, 16777215);
@@ -1709,6 +1721,16 @@
 
   area->default_cost = 1;
 
+  p.family = AF_INET;
+  p.prefix.s_addr = OSPF_DEFAULT_DESTINATION;
+  p.prefixlen = 0;
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_debug ("ospf_abr_announce_stub_defaults(): "
+                "announcing 0.0.0.0/0 to area %s",
+               inet_ntoa (area->area_id));
+  ospf_abr_announce_network_to_area (&p, area->default_cost, area);
+
+
   ospf_area_check_free (ospf, area_id);
 
   return CMD_SUCCESS;
@@ -2617,6 +2639,9 @@
       vty_out (vty, " Area %s%s", ospf_area_desc_string (oi->area),
 	       VTY_NEWLINE);
 
+      vty_out (vty, "  MTU mismatch detection:%s%s",
+           OSPF_IF_PARAM(oi, mtu_ignore) ? "disabled" : "enabled", VTY_NEWLINE);
+
       vty_out (vty, "  Router ID %s, Network Type %s, Cost: %d%s",
 	       inet_ntoa (ospf->router_id), ospf_network_type_str[oi->type],
 	       oi->output_cost, VTY_NEWLINE);
@@ -6491,6 +6516,105 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (ip_ospf_mtu_ignore,
+       ip_ospf_mtu_ignore_addr_cmd,
+       "ip ospf mtu-ignore A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Disable mtu mismatch detection\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr addr;
+  int ret;
+ 	   
+  struct ospf_if_params *params;
+  params = IF_DEF_PARAMS (ifp);
+ 	 
+  if (argc == 1)
+    {
+      ret = inet_aton(argv[0], &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);
+      ospf_if_update_params (ifp, addr);
+    }
+  params->mtu_ignore = 1;
+  if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT)
+    SET_IF_PARAM (params, mtu_ignore);
+  else 
+    {
+      UNSET_IF_PARAM (params, mtu_ignore);
+      if (params != IF_DEF_PARAMS (ifp))
+        {
+          ospf_free_if_params (ifp, addr);
+          ospf_if_update_params (ifp, addr);
+        }
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_mtu_ignore,
+      ip_ospf_mtu_ignore_cmd,
+      "ip ospf mtu-ignore",
+      "IP Information\n"
+      "OSPF interface commands\n"
+      "Disable mtu mismatch detection\n")
+
+    
+DEFUN (no_ip_ospf_mtu_ignore,
+       no_ip_ospf_mtu_ignore_addr_cmd,
+       "no ip ospf mtu-ignore A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Disable mtu mismatch detection\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr addr;
+  int ret;
+ 	   
+  struct ospf_if_params *params;
+  params = IF_DEF_PARAMS (ifp);
+ 	 
+  if (argc == 1)
+    {
+      ret = inet_aton(argv[0], &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);
+      ospf_if_update_params (ifp, addr);
+    }
+  params->mtu_ignore = 0;
+  if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT)
+    SET_IF_PARAM (params, mtu_ignore);
+  else 
+    {
+      UNSET_IF_PARAM (params, mtu_ignore);
+      if (params != IF_DEF_PARAMS (ifp))
+        {
+          ospf_free_if_params (ifp, addr);
+          ospf_if_update_params (ifp, addr);
+        }
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_ip_ospf_mtu_ignore,
+       no_ip_ospf_mtu_ignore_cmd,
+      "no ip ospf mtu-ignore",
+      "IP Information\n"
+      "OSPF interface commands\n"
+      "Disable mtu mismatch detection\n")
+    
 static void
 show_ip_ospf_route_network (struct vty *vty, struct route_table *rt)
 {
@@ -6907,6 +7031,20 @@
 	    vty_out (vty, "%s", VTY_NEWLINE);
 	  }
 
+    /* MTU ignore print. */
+    if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) &&
+       params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT)
+      {
+        if (params->mtu_ignore == 0)
+          vty_out (vty, " no ip ospf mtu-ignore");
+        else
+          vty_out (vty, " ip ospf mtu-ignore");
+        if (params != IF_DEF_PARAMS (ifp))
+           vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+        vty_out (vty, "%s", VTY_NEWLINE);
+      }
+
+
 	while (1)
 	  {
 	    if (rn == NULL)
@@ -7456,6 +7594,12 @@
   install_element (INTERFACE_NODE, &no_ip_ospf_cost_addr_cmd);
   install_element (INTERFACE_NODE, &no_ip_ospf_cost_cmd);
 
+  /* "ip ospf mtu-ignore" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_mtu_ignore_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_mtu_ignore_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_mtu_ignore_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_mtu_ignore_cmd);
+
   /* "ip ospf dead-interval" commands. */
   install_element (INTERFACE_NODE, &ip_ospf_dead_interval_addr_cmd);
   install_element (INTERFACE_NODE, &ip_ospf_dead_interval_cmd);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 30d276f..95e4751 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -105,6 +105,8 @@
 #define OSPF_POLL_INTERVAL_DEFAULT         60
 #define OSPF_NEIGHBOR_PRIORITY_DEFAULT      0
 
+#define OSPF_MTU_IGNORE_DEFAULT             0
+
 /* OSPF options. */
 #define OSPF_OPTION_T                    0x01  /* TOS. */
 #define OSPF_OPTION_E                    0x02