Initial revision
diff --git a/ospfd/.cvsignore b/ospfd/.cvsignore
new file mode 100644
index 0000000..d7e3a7e
--- /dev/null
+++ b/ospfd/.cvsignore
@@ -0,0 +1,7 @@
+Makefile
+*.o
+ospfd
+ospfd.conf
+tags
+TAGS
+.deps
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
new file mode 100644
index 0000000..31c5b0f
--- /dev/null
+++ b/ospfd/ChangeLog
@@ -0,0 +1,2970 @@
+2002-10-23  endo@suri.co.jp (Masahiko Endo)
+
+	* ospf_opaque.c: Update Opaque LSA patch.
+
+2002-10-23  Ralph Keller <keller@tik.ee.ethz.ch>
+
+	* ospf_vty.c (show_ip_ospf_database): Fix CLI parse.
+
+2002-10-23  Juris Kalnins <juris@mt.lv>
+
+	* ospf_interface.c (ospf_if_stream_unset): When write queue
+	becomes empty stop write timer.
+
+2002-10-10  Greg Troxel <gdt@ir.bbn.com>
+
+	* ospf_packet.c (ospf_check_md5_digest): Change >= to > to make it
+	conform to RFC.
+
+2002-07-07  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* zebra-0.93 released.
+
+2002-06-19  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* ospf_spf.c (ospf_nexthop_calculation): Add NULL set to oi and
+	check of l2.  Reported by: Daniel Drown <dan-zebra@drown.org>
+	(ospf_lsa_has_link): LSA Length calculation fix.  Reported by:
+	Paul Jakma <paulj@alphyra.ie>.
+
+	* ospfd.c (ospf_if_update): Fix nextnode reference bug.  Reported
+	by: juris@mt.lv.
+
+2002-01-21  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* ospfd.c: Merge [zebra 11445] Masahiko ENDO's Opaque-LSA support.
+
+2001-08-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_interface.c (ospf_add_to_if): Use /32 address to register
+	OSPF interface information.
+	(ospf_delete_from_if): Likewise.
+
+	* ospf_zebra.c (ospf_interface_address_delete): Likewise.
+
+2001-08-23  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* ospf_zebra.c (ospf_redistribute_unset): When redistribute type
+	is OSPF, do not unset redistribute flag.
+
+2001-08-19  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* zebra-0.92a released.
+
+2001-08-15  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* zebra-0.92 released.
+
+2001-08-12  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* ospfd.c (ospf_config_write): auto-cost reference-bandwidth
+	configuration display.
+
+2001-07-24  David Watson <dwatson@eecs.umich.edu>
+
+	* ospf_spf.c (ospf_spf_next): Modify ospf_vertex_add_parent to
+	check for an existing link before connecting the parent and child.
+	ospf_nexthop_calculation is also modified to check for duplicate
+	entries when copying from the parent.  Finally, ospf_spf_next
+	removes duplicates when it merges two equal cost candidates.
+
+2001-07-23  itojun@iijlab.net
+
+	* ospfd.c (show_ip_ospf_neighbor): Check ospf_top before use it
+	[zebra 8549].
+
+2001-07-23  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* ospf_packet.c (ospf_write): Remove defined(__OpenBSD__) to make
+	it work on OpenBSD.
+
+2001-06-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_zebra.c (config_write_ospf_default_metric): Display
+	default-metric configuration.
+
+2001-06-18  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* ospf_ia.h (OSPF_EXAMINE_SUMMARIES_ALL): Remove old macros.
+
+2001-05-28  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* ospf_snmp.c (ospfIfEntry): Fix interface lookup bug to avoid
+	crush.
+	(ospfIfMetricEntry): Likewise.
+
+2001-03-18  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_packet.c (ospf_read): Fix typo.  Reported by: "Jen B
+	Lin'Kova" <jen@stack.net>.
+
+2001-03-15  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_interface.c (ip_ospf_network): Set interface parameter.
+	(interface_config_write): Add check for OSPF_IFTYPE_LOOPBACK.
+
+	* ospf_zebra.c (ospf_interface_add): Set interface parameter.
+
+2001-02-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_packet.c (ospf_recv_packet): Solaris also need to add
+	(iph.ip_hl << 2) to iph.ip_len.
+
+2001-02-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.h (OSPF_LS_REFRESH_TIME): Fix OSPF_LS_REFRESH_TIME value.
+	Suggested by: David Watson <dwatson@eecs.umich.edu>.
+
+	* ospf_zebra.c (zebra_init): Remove zebra node.
+
+	* ospfd.c (ospf_area_range_set): Function name is changed from
+	ospf_ara_range_cmd.
+	(ospf_area_range_unset): New function which separated from DEFUN.
+	New commands are added:
+	"no area A.B.C.D range A.B.C.D/M advertise"
+	"no area <0-4294967295> range A.B.C.D/M advertise"
+	"no area A.B.C.D range A.B.C.D/M not-advertise"
+	"no area <0-4294967295> range A.B.C.D/M not-advertise"
+	
+	* ospf_lsa.c (ospf_lsa_more_recent): Fix previous change.
+
+2001-02-08  Matthew Grant <grantma@anathoth.gen.nz>
+
+	* ospf_network.c (ospf_if_add_allspfrouters): Use
+	setsockopt_multicast_ipv4.
+	(ospf_if_drop_allspfrouters): Likewise.
+
+	* ospf_lsa.c (ospf_router_lsa_install): Add rt_recalc flag.
+	(ospf_network_lsa_install): Likewise.
+	(ospf_summary_lsa_install): Likewise.
+	(ospf_summary_asbr_lsa_install): Likewise.
+	(ospf_external_lsa_install): Likewise.
+	(ospf_lsa_install): Call ospf_lsa_different to check this LSA is
+	new one or not.
+
+2001-02-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_zebra.c (ospf_interface_delete): Do not free interface
+	structure when ospfd receive interface delete message to support
+	pseudo interface.
+
+2001-02-01  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospfd.c (area_range_notadvertise): Change area range "suppress"
+	command to "not-advertise".
+
+	* ospfd.h (OSPF_LS_REFRESH_TIME): Change OSPF_LS_REFRESH_TIME from
+	1800 to 60.
+
+	* ospf_abr.c (ospf_abr_update_aggregate): When update_aggregate is
+	updating the area-range, the lowest cost is now saved.
+
+	* ospf_lsa.c (ospf_lsa_more_recent): Routing to compare sequence
+	numbers rather than creating overflow during calculation.
+
+2001-02-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* zebra-0.91 is released.
+
+2001-01-31  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_packet.c (ospf_db_desc_proc): Do not continue process when
+	NSM_SeqNumberMismatch is scheduled.
+	(ospf_ls_req): Free ls_upd when return from this function.
+	(ospf_ls_upd_timer): When update list is empty do not call
+	ospf_ls_upd_send().  Suggested by: endo@suri.co.jp (Masahiko
+	Endo).
+
+2001-01-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_lsa.c (ospf_maxage_flood): Flood LSA when it reaches
+	MaxAge.  RFC2328 Section 14.
+	(ospf_maxage_lsa_remover): Call above function during removing
+	MaxAge LSA.
+
+2001-01-26  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospf_flood.c (ospf_flood_through_as): Function is updated for
+	NSSA Translations now done at ospf_abr.c with no change in P-bit.
+
+	* ospf_lsa.c (ospf_get_nssa_ip): Get 1st IP connection for Forward
+	Addr.
+	(ospf_install_flood_nssa):  Leave Type-7 LSA at Lock Count = 2. 
+
+	* ospf_ase.c (ospf_ase_calculate_route): Add debug codes.
+
+	* ospf_abr.c (ospf_abr_translate_nssa): Recalculate LSA checksum.
+
+	* ospf_packet.h (OSPF_SEND_PACKET_LOOP): Added for test packet.
+
+	* ospf_dump.c (ospf_lsa_type_msg): Add OSPF_GROUP_MEMBER_LSA and
+	OSPF_AS_NSSA_LSA.
+
+	* ospfd.c (data_injection): Function to inject LSA.  This is
+	debugging command.
+
+2001-01-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_route.c (ospf_route_match_same): Remove function.
+	(ospf_route_match_same_new): Renamed to ospf_route_match_same.
+
+	* ospf_zebra.c (ospf_interface_address_delete): Add check for
+	oi->address.  Suggested by Matthew Grant
+	<grantma@anathoth.gen.nz>.
+	(ospf_zebra_add): Remove function.
+	(ospf_zebra_add_multipath): Rename to ospf_zebra_add.
+
+	* ospf_interface.c: Remove HAVE_IF_PSEUDO part.
+
+	* ospf_zebra.c: Likewise.
+
+2001-01-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_ase.c: Remove OLD_RIB part.
+
+	* ospf_route.c: Likewise.
+
+	* zebra-0.90 is released.
+
+	* ospf_packet.c (ospf_recv_packet): Use ip_len adjestment code to
+	NetBSD.
+
+2001-01-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_route.c (ospf_route_delete): Use
+	ospf_zebra_delete_multipath.
+
+2001-01-09  Matthew Grant <grantma@anathoth.gen.nz>
+
+	* ospf_interface.c (ospf_if_cleanup): Function name is renamed
+	from ospf_if_free().  Rewrite whole procudure to support primary
+	address deletion.
+
+	* ospf_zebra.c (ospf_interface_address_delete): Add primary
+	address deletion process.
+
+2001-01-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_packet.c (ospf_recv_packet): OpenBSD has same ip_len
+	treatment like FreeBSD.
+
+2001-01-09  endo@suri.co.jp (Masahiko Endo)
+
+	* ospf_packet.c (ospf_recv_packet): FreeBSD kernel network code
+	strips IP header size from receiving IP Packet.  So we adjust
+	ip_len to whole IP packet size by adding IP header size.
+
+2001-01-08  endo@suri.co.jp (Masahiko Endo)
+
+	* ospf_network.c (ospf_serv_sock): When socket() is failed return
+	immediately.
+	(ospf_serv_sock): Close socket when it is not used.
+
+	* ospf_packet.c (ospf_write): Set sin_len when HAVE_SIN_LEN is
+	defined.
+	(ospf_write): When bind is fined, close sock.
+
+2001-01-07  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_zebra.c (ospf_interface_state_up): Fixes coredump that
+	appears when you try to configure bandwidth on the ppp interface
+	that is not yet configured in ospfd.
+
+2001-01-07  Michael Rozhavsky <mrozhavsky@opticalaccess.com>
+
+	* ospf_route.c (show_ip_ospf_route_external): "show ip ospf route"
+	will print nexthops for AS-external routes.
+
+	* ospf_ase.c (ospf_ase_route_match_same): New function to compare
+	ASE route under multipath environment.
+	(ospf_ase_compare_tables): Likewise.
+
+2001-01-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.h (OSPF_VTYSH_PATH): Change "/tmp/ospfd" to "/tmp/.ospfd".
+
+2000-12-28  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_route.c (ospf_route_install): Install multipath information
+	to zebra daemon.
+
+	* ospf_zebra.c (ospf_zebra_add_multipath): Function for passing
+	multipath information to zebra daemon.
+
+2000-12-25  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospf_packet.c (ospf_write): Call ospf_packet_delete when sendto
+	fail.
+	(DISCARD_LSA): Add argument N for logging point of DISCARD_LSA is
+	called.
+
+	* ospf_lsa.c (ospf_external_lsa_refresh): NSSA install_flood will
+	leave Type-7 LSA at Lock Count = 2.
+
+	* ospf_flood.c (ospf_flood_through): Flood_though_as updated for
+	NSSA no P-bit off during Area flooding, but P-bit is turned off
+	for mulitple NSSA AS flooding.
+
+	* ospf_ase.c (ospf_ase_calculate_timer): Added calculations for
+	Type-7 LSDB.
+
+	* ospf_abr.c (ospf_abr_translate_nssa): Removed one unlock call.
+	(ospf_abr_announce_nssa_defaults): Corrected Debug from EVENT to
+	NSSA.
+
+2000-12-25  Michael Rozhavsky <mrozhavsky@opticalaccess.com>
+
+	* ospf_zebra.c (ospf_zebra_read_ipv4): Checking the age of the
+	found LSA and if the LSA is MAXAGE we should call refresh instead
+	of originate.
+
+2000-12-18  Dick Glasspool <dick@ipinfusion.com>
+	   	   
+	* ospf_abr.c: Removed redundant "...flood" in
+	announce_network_to_area().  Repaired nssa Unlock by using
+	discard.
+
+	* ospf_packet.c: Removed old NSSA translate during mk_ls_update.
+	
+	* ospfd.c: Free up all data bases including NSSA.
+
+	* ospf_lsa.c: Now allow removal of XLATE LSA's Check in
+	discard_callback. Added routine to get ip addr from within the
+	ifp.
+
+	* ospf_flood.c: Now set Forward Address for outgoing Type-7.
+
+	* ospf_lsa.h: Added prototype for the below. struct in_addr
+	ospf_get_ip_from_ifp (struct interface *ifp).
+
+2000-12-14  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_packet.c (ospf_recv_packet): New OSPF pakcet read method.
+	Now maximum packet length may be 65535 bytes (maximum IP packet
+	length).
+
+	* ospf_interface.c (ospf_if_stream_set): Don't make input buffer.
+
+	* ospfd.c (config_write_network_area): Remove unnecessary area
+	lookup code.
+
+2000-12-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_packet.c (ospf_read): Accept packet bigger than MTU value.
+
+2000-12-13  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospfd.c (config_write_network_area): Fix bug in
+	config_write_network_area function.
+
+2000-12-12  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_abr.c (ospf_abr_announce_network_to_area): Make Summary
+	LSA's origination and refreshment as same as other type of LSA.
+
+	* ospf_lsa.c (ospf_summary_lsa_refresh): Return struct ospf_lsa *.
+
+	* ospf_lsa.c (ospf_summary_asbr_lsa_refresh): Likewise.
+
+2000-12-08  Dick Glasspool <dick@ipinfusion.com>
+
+	The bulk of NSSA changes are contained herein; This version will
+	require manual setting of "always" for NSSA Translator, and will
+	not perform aggregation yet.
+
+	* ospf_dump.c: "debug ospf nssa" is added.
+
+	* ospf_dump.h: Likewise.
+
+	* ospf_packet.c (ospf_hello): Display router ID on Bad NSSA Hello.
+
+	* ospfd.c: Discard_LSA to stay away from LOCAL_XLT Process NSSA
+	'never, candidate, always'.  Change "suppress" to "not-advertise".
+
+	* ospfd.h: Add TranslatorRole to struct ospf_area.  Add anyNSSA to
+	struct ospf.
+
+	* ospf_ase.c (ospf_ase_calculate_route): External to stay away
+	from LOCAL_XLT
+
+	* ospf_nsm.c (ospf_db_summary_add): External to stay away from
+	LOCAL_XLT
+
+	* ospf_abr.c: Major logic added for abr_nssa_task().  If ABR, and
+	NSSA translator, then do it.  Approve the global list, and flush
+	any unapproved.
+	
+	* ospf_lsa.h: New LSA flag OSPF_LSA_LOCAL_XLT to indicate that the
+	Type-5 resulted from a Local Type-7 translation; not used for
+	flooding, but used for flushing.
+
+	* ospf_flood.c: New NSSA flooding.
+
+2000-12-08  Michael Rozhavsky <mrozhavsky@opticalaccess.com>
+
+	* ospfd.c (ospf_find_vl_data): New function for looking up virtual
+	link data.
+	(ospf_vl_set_security): Virtual link configuration with
+	authentication.
+	(ospf_vl_set_timers): Set timers for virtual link.
+
+	* New commands are added.
+	"area A.B.C.D virtual-link A.B.C.D"
+	"area A.B.C.D virtual-link A.B.C.D hello-interval <1-65535> retransmit-interval <3-65535> transmit-delay <1-65535> dead-interval <1-65535>"
+	"area A.B.C.D virtual-link A.B.C.D hello-interval <1-65535> retransmit-interval <3-65535> transmit-delay <1-65535> dead-interval <1-65535> authentication-key AUTH_KEY"
+	"area A.B.C.D virtual-link A.B.C.D authentication-key AUTH_KEY"
+	"area A.B.C.D virtual-link A.B.C.D hello-interval <1-65535> retransmit-interval <3-65535> transmit-delay <1-65535> dead-interval <1-65535> message-digest-key <1-255> md5 KEY"
+	"area A.B.C.D virtual-link A.B.C.D message-digest-key <1-255> md5 KEY"
+
+	* ospf_packet.c (ospf_check_md5_digest): Add neighbor's
+	cryptographic sequence number treatment.
+	(ospf_check_auth): OSPF input buffer is added to argument.
+	(ospf_read): Save neighbor's cryptographic sequence number.
+
+	* ospf_nsm.c (nsm_change_status): Clear cryptographic sequence
+	number when neighbor status is changed to NSM down.
+
+	* ospf_neighbor.c (ospf_nbr_new): Set zero to crypt_seqnum.
+
+	* ospf_neighbor.h (struct ospf_neighbor): Add cryptographic
+	sequence number to neighbor structure.
+
+2000-11-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_snmp.c (ospfIfLookup): OSPF MIB updates.
+	(ospfExtLsdbEntry): Add OspfExtLsdbTable treatment.
+
+2000-11-28  Michael Rozhavsky <mrozhavsky@opticalaccess.com>
+
+	* ospfd.c (ospf_interface_down): Clear a ls_upd_queue queue of the
+	interface.
+	(ospf_ls_upd_queue_empty): New function to empty ls update queue
+	of the OSPF interface.
+	(no_router_ospf): 'no router ospf' unregister redistribution
+	requests from zebra.
+
+2000-11-28  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_ism.c (ism_change_status): Increment status change number.
+
+	* ospf_interface.h (struct ospf_interface): Add new member for
+	status change statistics.
+
+	* Makefile.am: Update dependencies.
+
+	* ospf_zebra.c (ospf_interface_add): OSPF SNMP interface update.
+	(ospf_interface_delete): OSPF SNMP interface delete.
+
+	* ospf_snmp.h: New file is added.
+
+2000-11-23  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospfd.h: Add new ospf_area structure member for
+	NSSATranslatorRole and NSSATranslator state.
+
+	* ospfd.c: Provided for eventual commands to specify NSSA
+	elections for "translator- ALWAYS/NEVER/CANDIDATE". Provided for
+	decimal integer version of area-suppress.
+
+	* ospf_flood.c: Flood Type-7's only into NSSA (not AS).
+
+	* ospf_lsa.c: Undo some previous changes for NSSA.  If NSSA
+	translator, advertise Nt bit.
+
+	* ospf_route.c: 1st version of "sh ip os border-routers".
+
+2000-11-23  Michael Rozhavsky <mrozhavsky@opticalaccess.com>
+
+	* ospfd.c (area_vlink): Virtual link can not configured in stub
+	area.
+
+2000-11-23  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_packet.c (ospf_db_desc): In states Loading and Full the
+	slave must resend its last Database Description packet in response
+	to duplicate Database Description packets received from the
+	master.  For this reason the slave must wait RouterDeadInterval
+	seconds before freeing the last Database Description packet.
+	Reception of a Database Description packet from the master after
+	this interval will generate a SeqNumberMismatch neighbor
+	event. RFC2328 Section 10.8
+	(ospf_make_db_desc): DD Master flag treatment.
+
+	* ospf_nsm.c (nsm_twoway_received): Move DD related procedure to
+	nsm_change_status().
+	(nsm_bad_ls_req): Likewise.
+	(nsm_adj_ok): Likewise.
+	(nsm_seq_number_mismatch): Likewise.
+	(nsm_oneway_received): Likewise.
+
+	* ospf_neighbor.h (struct ospf_neighbor): New structure member
+	last_send_ts for timestemp when last Database Description packet
+	was sent.
+
+	* ospf_nsm.c (ospf_db_desc_timer): Make it sure nbr->last_send is
+	there.  Call ospf_db_desc_resend() in any case.
+
+2000-11-16  Michael Rozhavsky <mrozhavsky@opticalaccess.com>
+
+	* ospf_lsa.c (lsa_link_broadcast_set): When there is no DR on
+	network (suppose you have only one router with interface priority
+	0). It's router LSA does not contain the link information about
+	this network.
+
+	* ospf_nsm.c (nsm_timer_set): When you change a priority of
+	interface from/to 0 ISM_NeighborChange event should be scheduled
+	in order to elect new DR/BDR on the network.
+
+	* ospf_interface.c (ip_ospf_priority): Likewise.
+
+	* ospf_flood.c (ospf_ls_retransmit_add): When we add some LSA into
+	retransmit list we need to check whether the present old LSA in
+	retransmit list is not more recent than the new
+	one.
+
+2000-11-09  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospf_packet.c: Allows for NSSA Type-7 LSA's throughout the NSSA
+	area.  Any that exit the NSSA area are translated to type-5 LSA's.
+	The instantiated image is restored after translation.
+	(ospf_ls_upd_send_list): Renamed to ospf_ls_upd_queu_send().
+	(ospf_ls_upd_send): Old function which enclosed by #ifdef 0 is
+	removed.
+	(ospf_ls_ack_send): Likewise.
+
+	* ospf_flood.c: NSSA-LSA's without P-bit will be restricted to
+	local area.  Otherwise they are allowed out the area to be
+	translated by ospf_packet.c.
+
+	* ospf_lsa.c: Undo some previous changes for NSSA.
+
+	* ospf_lsdb.h: New access for type 7.
+
+2000-11-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_route.c (ospf_path_exist): New function to check nexthop
+	and interface are in current OSPF path or not.
+	(ospf_route_copy_nexthops_from_vertex): Add nexthop to OSPF path
+	when it is not there.  Reported by Michael Rozhavsky
+	<mrozhavsky@opticalaccess.com>
+
+2000-11-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_dump.c (config_write_debug): Add seventh string "detail" is
+	added for flag is OSPF_DEBUG_SEND | OSPF_DEBUG_RECV |
+	OSPF_DEBUG_DETAIL.
+
+2000-11-06   Michael Rozhavsky <mrozhavsky@opticalaccess.com>
+
+	* ospf_lsa.c (router_lsa_flags): ASBR can't exit in stub area.
+
+2000-11-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_lsa.c (ospf_router_lsa_originate): Reduce unconditional
+	logging.
+
+2000-11-06  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospfd.h: Add ait_ntoa function prototype.
+
+	* ospfd.c (ait_ntoa): New function for displaying area ID and
+	Stub/NSSA status.
+	(show_ip_ospf_interface_sub): Use ait_ntoa.
+	(show_ip_ospf_nbr_static_detail_sub): Likewise.
+	(show_ip_ospf_neighbor_detail_sub): Likewise.
+
+	* ospf_route.c (ospf_intra_route_add): Set external routing type
+	to ospf route.
+	(ospf_intra_add_router): Likewise.
+	(ospf_intra_add_transit): Likewise.
+	(ospf_intra_add_stub): Likewise.
+	(ospf_add_discard_route): Likewise.
+	(show_ip_ospf_route_network): Use ait_ntoa.
+	(show_ip_ospf_route_network): Likewise.
+	(show_ip_ospf_route_router): Likewise.
+
+	* ospf_lsa.c (show_lsa_detail): Use ait_ntoa.
+	(show_lsa_detail_adv_router): Likewise.
+	(show_ip_ospf_database_summary): Likewise.
+
+	* ospf_route.h (struct route_standard): Add new member
+	external_routing.
+
+	* ospf_ia.c (process_summary_lsa): Set external routing tyep to ospf
+	route.
+	(ospf_update_network_route): Likewise.
+	(ospf_update_router_route): Likewise.
+
+2000-11-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_flood.c (ospf_process_self_originated_lsa): Enclose
+	OSPF_AS_NSSA_LSA treatment with #ifdef HAVE_NSSA.
+
+2000-11-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* Unconditional logging is enclosed with if (IS_DEBUG_OSPF_EVENT).
+	Please specify "debug ospf event" for enable logging.
+
+	* ospf_ism.c: Do not extern debug flag varible.  It is done by
+	ospf_debug.h
+	* ospf_asbr.c: Likewise.
+	* ospf_lsa.c: Likewise.
+	* ospf_nsm.c: Likewise.
+	* ospf_zebra.c: Likewise.
+
+	* ospf_dump.c (debug_ospf_event): New command "debug ospf event"
+	is added.
+
+	* ospfd.c (router_ospf): Change logging from vty_out() to
+	zlog_info().
+	(ospf_area_stub_cmd): Likewise.
+
+	* ospf_dump.h: Extern term_debug flags.
+	(OSPF_DEBUG_EVENT): Add new flag.
+	(IS_DEBUG_OSPF_EVENT): Add new macro.
+
+2000-11-03  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospf_flood.c (ospf_process_self_originated_lsa):
+	OSPF_AS_NSSA_LSA is treated as same as OSPF_AS_EXTERNAL_LSA.
+	(ospf_flood): Type-5's have no change.  Type-7's can be received,
+	and will Flood the AS as Type-5's They will also flood the local
+	NSSA Area as Type-7's.  The LSDB will be updated as Type-5's, and
+	during re-fresh will be converted back to Type-7's (if within an
+	NSSA).
+	(ospf_flood_through): Incoming Type-7's were allowed here if our
+	neighbor was an NSSA.  So Flood our area with the Type-7 and also
+	if we are an ABR, flood thru AS as Type-5.
+
+	* ospf_lsa.c (ospf_external_lsa_refresh): Flood NSSA both NSSA
+	area and other area.
+
+	* ospf_packet.c (ospf_db_desc_proc): When AS External LSA is
+	exists in DD packet, make it sure that this area is not stub.
+	(ospf_ls_upd_list_lsa): When LSA type is NSSA then set lsa's area
+	to NULL.
+	(ospf_ls_upd): If the LSA is AS External LSA and the area is stub
+	then discard the lsa.  If the LSA is NSSA LSA and the area is not
+	NSSA then discard the lsa.
+
+2000-11-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.c (ospf_interface_run): Fix bug of Hello packet's option
+	is not properly set when interface comes up.
+
+2000-11-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.h (OSPF_OPTION_O): Add new hello header option.
+
+2000-11-01  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospf_lsa.h: Define OSPF_MAX_LSA to 8 when HAVE_NSSA is enabled.
+	(OSPF_GROUP_MEMBER_LSA): Define OSPF_GROUP_MEMBER_LSA.
+
+	* ospf_lsa.c (show_database_desc): Add "Group Membership LSA"
+	string.
+
+2000-10-31  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospf_lsa.h (OSPF_AS_NSSA_LSA): Define OSPF_AS_NSSA_LSA.
+	
+	* ospf_lsa.c (show_ip_ospf_database): NSSA database display
+	function is added.  ALIASES which have "show ip ospf database
+	nssa-external" is added.
+	(show_ip_ospf_border_routers): New command "show ip ospf
+	border-routers" is added.
+
+2000-10-30  Dick Glasspool <dick@ipinfusion.com>
+
+	* ospfd.c (router_ospf): NSSA Enabled message is added for
+	testing.
+	(ospf_area_type_set): Are type set for NSSA area.
+	(ospf_area_stub_cmd): Special translation of no_summary into NSSA
+	and summary information. If NSSA is enabled pass the information
+	to ospf_area_type_set().
+	(area_nssa): New commands are added:
+	"area A.B.C.D nssa"
+	"area <0-4294967295> nssa"
+	"area A.B.C.D nssa no-summary"
+	"area <0-4294967295> nssa no-summary"
+	(ospf_no_area_stub_cmd): Special translation of no_summary into
+	NSSA and summary information.  If external_routing is
+	OSPF_AREA_NSSA unset area with ospf_area_type_set (area,
+	OSPF_AREA_DEFAULT).
+	(show_ip_ospf_area): Display NSSA status.
+	(config_write_ospf_area): Show NSSA configuration.
+
+	* ospf_packet.c (ospf_hello): For NSSA support, ensure that NP is
+	on and E is off.
+
+2000-10-26  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_lsa.c (ospf_network_lsa_body_set): The network-LSA lists
+	those routers that are fully adjacent to the Designated Router;
+	each fully adjacent router is identified by its OSPF Router ID.
+	The Designated Router includes itself in this list. RFC2328,
+	Section 12.4.2.
+
+2000-10-23  Jochen Friedrich <jochen@scram.de>
+
+	* ospf_snmp.c: ospf_oid and ospfd_oid are used in smux_open after
+	it is registered.  So those variables must be static.
+
+2000-10-18  K N Sridhar <sridhar@euler.ece.iisc.ernet.in>
+
+	* ospfd.c: Add area_default_cost_decimal_cmd and
+	no_area_default_cost_decimal_cmd alias.
+
+2000-10-05  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospfd.c (ospf_network_new): Fix setting area format.
+	(no_router_ospf): Check area existance when calling
+	ospf_interface_down().
+
+	* ospf_flood.c (ospf_external_info_check): Fix bug of refreshing
+	default route.
+
+2000-10-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* zebra-0.89 is released.
+
+2000-09-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_snmp.c (ospfHostEntry): OSPF Host MIB is implemented.
+
+	* ospfd.c (ospf_nbr_static_cmp): OSPF neighbor is sorted by it's
+	address.
+
+2000-09-28  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_interface.c (ospf_if_free):  Fix deleting self neighbor twice.
+
+2000-09-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_packet.c (ospf_read): Solaris on x86 has ip_len with host
+	byte order.
+
+2000-09-25  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (ospf_compatible_rfc1583), (no_ospf_compatible_rfc1583):
+	Add CISCO compatible command.
+
+2000-09-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_abr.c (ospf_area_range_lookup): New function is added for
+	area range lookup in OSPF-MIB.
+	(ospf_area_range_lookup_next): Likewise.
+
+2000-09-22  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.c (no_router_ospf): Delete virtual link before deleting
+	area structure.
+
+	* ospf_lsa.c (ospf_external_lsa_refresh_type): Check
+	EXTERNAL_INFO(type).
+
+	* ospfd.c (no_router_ospf): Call ospf_vl_delete() instead of
+	ospf_vl_data_free().
+
+	* ospf_interface.c (ospf_vl_shutdown): Execute ISM_InterfaceDown
+	when ospf_vl_shutdown is called.
+	(ospf_vl_delete): Call ospf_vl_shutdown() to delete virtual link
+	interface's thread.
+
+2000-09-21  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_lsa.c: New implementation of OSPF refresh.
+
+2000-09-20  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_snmp.c (ospfLsdbLookup): Add LSDB MIB implementation.
+
+2000-09-18  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_snmp.c (ospfStubAreaEntry): Add OSPF stub area MIB.
+
+2000-09-18  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_route.h (route_standard):  Change member from `struct area'
+	to area_id.
+
+	* ospf_abr.c (ospf_abr_announce_network), (ospf_abr_should_announce),
+	(ospf_abr_process_network_rt), (ospf_abr_announce_rtr), 
+	(ospf_abr_process_router_rt):
+	* ospf_ase.c (ospf_find_asbr_route),
+	(ospf_find_asbr_router_through_area),
+	* ospf_ia.c (ospf_find_abr_route), (ospf_ia_router_route),
+	(process_summary_lsa), (ospf_update_network_route),
+	(ospf_update_router_route):
+	* ospf_route.c (ospf_intra_route_add), (ospf_intra_add_router),
+	(ospf_intra_add_transit), (ospf_intra_add_stub),
+	(ospf_route_table_dump), (show_ip_ospf_route_network),
+	(show_ip_ospf_route_router), (ospf_asbr_route_cmp),
+	(ospf_prune_unreachable_routers):
+	* ospf_spf.c (ospf_rtrs_print):
+	* ospfd.c (ospf_rtrs_free):  Fix the struct change above.
+
+2000-09-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_network.c (ospf_serv_sock_init): Enclose SO_BINDTODEVICE
+	with ifdef.
+
+2000-09-13  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_ism.c (ospf_elect_dr), (ospf_elect_bdr):  Fix DR election.
+
+	* ospf_network.c (ospf_serv_sock_init):  Add socket option
+	SO_BINDTODEVICE on read socket.
+
+	* ospf_packet.c (ospf_hello):  Ignore Hello packet if E-bit does
+	not match.
+
+	* ospfd.c (ospf_area_check_free), (ospf_area_get),
+	(ospf_area_add_if):  New function added.
+	
+2000-09-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_route.c (ospf_intra_add_router): Update ABR and ASBR router
+	count.
+
+	* ospf_spf.c (ospf_spf_init): Rest ABR and ASBR router count
+	starting SPF calculation.
+
+	* ospfd.h (struct ospf_area): Add ABR and ASBR router count.
+
+2000-09-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.c (ospf_area_id_cmp): New area structure is sorted by area
+	ID.
+
+	* ospf_lsa.c (ospf_router_lsa_originate): For OSPF MIB update
+	lsa_originate_count.
+	(ospf_network_lsa_originate): Likewise.
+	(ospf_summary_lsa_originate): Likewise.
+	(ospf_summary_asbr_lsa_originate): Likewise.
+	(ospf_external_lsa_originate): Likewise.
+
+2000-09-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_snmp.c (ospf_variables): ospfRouterID's type RouterID
+	syntax is IpAddress.
+	(ospf_admin_stat): New function for OSPF administrative status
+	check.
+
+2000-09-10  Jochen Friedrich <jochen@scram.de>
+
+	* ospf_snmp.c: Implement OSPF MIB skeleton.
+
+2000-09-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_snmp.c: New file is added.
+
+2000-09-07  David Lipovkov <davidl@nbase.co.il>
+
+	* ospf_zebra.c (ospf_interface_delete): Add pseudo interface
+	treatment.
+
+	* ospf_interface.c (interface_config_write): Likewise.
+
+2000-08-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* zebra-0.88 is released.
+
+2000-08-17  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospfd.c (ospf_area_free):  Remove virtual link configuration only
+	when Area is removed.
+
+2000-08-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.c (network_area): Revert check for EXTERNAL_INFO
+	(ZEBRA_ROUTE_CONNECT).
+	(no_network_area): Likewise.
+
+2000-08-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospfd.h (struct ospf): Add distance_table and
+	distance_{all,intra,inter,external}.
+
+	* ospf_zebra.c: Add OSPF distance related functions.
+
+2000-08-15  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_asbr.c (ospf_external_info_find_lsa):  New function added.
+
+	* ospf_lsa.c (ospf_default_external_info),
+	(ospf_default_originate_timer), (ospf_external_lsa_refresh_default):
+	New function added.
+
+	* ospf_zebra.c
+	(ospf_default_information_originate_metric_type_routemap),
+	(ospf_default_information_originate_always_metric_type_routemap):
+	Change name and add route-map function.
+	(ospf_default_information_originate_metric_routemap),
+	(ospf_default_information_originate_routemap),
+	(ospf_default_information_originate_type_metric_routemap):
+	New DEFUN added.
+
+2000-08-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_zebra.c (zebra_interface_if_set_value): Change ifindex
+	restore size from two octet to four.
+
+2000-08-14  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_ase.c (ospf_ase_incremental_update):  Implement incremental
+	AS-external-LSA in 16.6 of RFC2328.
+
+2000-08-14  Matthew Grant  <grantma@anathoth.gen.nz>
+
+	* ospf_interface.c (ospf_if_get_output_cost):  Change cost
+	calculation algorithm.
+
+	* ospf_packet (ospf_ls_upd):  Fix problem of LSA retransmitting.
+
+2000-08-11  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_lsa.c (ospf_maxage_lsa_remover):  Fix maxage remover for
+	AS-external-LSAs.
+
+2000-08-10  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (auto_cost_reference_bandwidth):  New DEFUN added.
+	`auto-cost reference-bandwidth' OSPF router command added.
+
+2000-08-08  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_routemap.c (ospf_route_map_update):  New function added.
+	Add route-map event hook.
+
+2000-08-08  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_zebra.c (ospf_distribute_check_connected):  If redistribute
+	prefix is connected route on OSPF enabled interface, suppress to
+	announce it.
+
+2000-08-08  Matthew Grant  <grantma@anathoth.gen.nz>
+
+	* ospf_interface.c (ospf_if_get_output_cost):
+	New function added.  Handle bandwidth parameter for cost
+	calculation.
+
+2000-08-08  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_interface.c (interface_config_write):  Show interface
+	configuration regardless interface is down.
+
+	* ospf_ase.c (ospf_ase_caocluate_route):  Whole rewritten external
+	route calculate function.
+
+2000-08-08  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_routemap.c:  New file added.
+
+	* ospf_asbr.c (ospf_reset_route_map_set_values),
+	(ospf_route_map_set_compare):  New function added.
+
+	* ospf_lsa.c (ospf_external_lsa_body_set):  Set routemap metric
+	with AS-external-LSA.
+
+2000-08-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_ase.c (ospf_ase_calculate_route_add): Pass new->cost to
+	ospf_zebra_add as metric.
+	(ospf_ase_calculate_route_add): Likewise.
+
+	* ospf_route.c (ospf_route_install): Pass or->cost to
+	ospf_zebra_add as metric.
+
+	* ospf_zebra.c (ospf_zebra_add): Add metric arguemnt.
+	(ospf_zebra_delete): Likewise.
+
+2000-08-03  Matthew Grant  <grantma@anathoth.gen.nz>
+
+	* ospf_flood.c (ospf_flood_delayed_lsa_ack):  New function added.
+	Dispatch delayed-ACK with flooding AS-external-LSA across virtual
+	link.
+
+2000-07-31  Matthew Grant  <grantma@anathoth.gen.nz>
+
+	* ospfd.c (show_ip_ospf_area):  Fix lack of VTY_NEWLINE when
+	`show ip ospf'.
+
+	* ospf_interface.c (ospf_if_free):  Fix bug of crash with
+	Point-to-Point interface.
+
+2000-07-27  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_flood.c (ospf_process_self_originated_lsa):
+	Make sure to clear LSA->param (redistributed external information)
+	before refreshment.
+
+2000-07-27  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospfd.c (refresh_group_limit), (refresh_per_slice),
+	(refresh_age_diff):  New defun added.  Refresher related parameter
+	can be configurable.
+
+2000-07-27  Akihiro Mizutani  <mizutani@dml.com>
+
+	* ospf_interface.c (interface_config_write):  Print `description'
+	config directive to work.
+
+2000-07-24  Akihiro Mizutani  <mizutani@dml.com>
+
+	* ospf_interface.c (ospf_if_init): Use install_default for
+	INTERFACE_NODE.
+
+2000-07-24  Gleb Natapov  <gleb@nbase.co.il>
+	
+	* ospf_packet.c (ospf_ls_upd_send_list), (ospf_ls_upd_send_event),
+	(ospf_ls_ack_send_list), (ospf_ls_ack_send_event): New function added.
+	This make sending always as many LS update/Ack combined in one ospf
+	packet.
+
+2000-07-24  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_packet.c (ospf_ls_upd_list_lsa):  Set NULL to lsa->area if 
+	LSA is AS-external-LSA.
+
+	* ospf_nsm.c (nsm_reset_nbr):  Do not cancel Inactivity timer.
+
+2000-07-21  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_zebra.c (ospf_default_originate_timer):  Set timer for
+	`default-information originate'.  Fix some default originate
+	related functions.
+
+2000-07-12  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (stream_put_ospf_metric):  New function added.
+
+2000-07-12  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (show_ip_ospf_database_router),
+	(show_ip_ospf_database_network), (show_ip_ospf_database_summary),
+	(show_ip_ospf_database_summary_asbr), (show_ip_ospf_database_externel),
+	(show_router_lsa), (show_any_lsa), (show_router_lsa_self),
+	(show_any_lsa_self):  Functions removed.
+
+	(show_lsa_prefix_set), (show_lsa_detail_proc), (show_lsa_detail),
+	(show_lsa_detail_adv_router_proc), (show_lsa_detail_adv_router):
+	New functions added.  Replace above functions.
+
+	(show_ip_ospf_database_all), (show_ip_ospf_database_self_originated):
+	Functions removed.
+	(show_ip_ospf_database_summary):  New functions added.  Replace
+	above functions.
+
+	(show_ip_ospf_database_cmd):  DEFUN rearranged.
+	(show_ip_ospf_database_type_id_cmd),
+	(show_ip_ospf_database_type_id_adv_router_cmd),
+	(show_ip_ospf_database_type_is_self_cmd):  New ALIASes added.
+	(show_ip_ospf_database_type_adv_rotuer_cmd):  New DEFUN added.
+	(show_ip_ospf_database_type_self_cmd):  New ALIAS added.
+
+2000-07-11  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_asbr.c (ospf_external_info_new),
+	(ospf_external_info_free):  New functions added.
+
+	* ospf_lsa.h (ospf_lsa):  Add new member `void *param' to set
+	origination parameter for external-LSA.
+	Remove member `redistribute'.
+
+	* ospf_zebra.c (ospf_redistirbute_set):  When `redistribute'
+	command executed, metric and metric-type values are overridden.
+	If one of those is changed refresh AS-external-LSAs for appropriate
+	type.
+
+2000-07-11  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_lsa.c (ospf_summary_lsa_refresh),
+	(ospf_summary_asbr_lsa_refresh):  Make sure to refresh summary-LSAs.
+
+	* ospf_abr.c (set_metric):  New function added.
+
+2000-07-07  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_zebra.c (ospf_default_information_originate_metric_type),
+	(ospf_default_information_originate_type_metric):  New defun added.
+	Metic and Metric type can be set to default route.
+	(ospf_default_information_originate_always_metric_type):
+	(ospf_default_information_originate_always_type_metric):
+	New defun added.  Metric and Metric type can be set to default
+	always route.
+	
+	* ospf_zebra.c (ospf_default_metric), (no_ospf_default_metric):
+	New defun added.
+
+2000-07-06  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_flood.c (ospf_flood_through_area):  Fix bug of considering
+	on the same interface the LSA was received from.
+
+2000-07-06  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospfd.c (ospf_config_write):  Fix bug of printing `area stub'
+	command with `write mem'.
+
+	* ospfd.c (no_router_ospf):  Remove installed routes from zebra.
+
+	* ospf_zebra.c (ospf_interface_delete):  Fix function to handle
+	zebra interface delete event.
+
+2000-07-06  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_zebra.c (ospf_default_information_originate),
+	(ospf_default_information_originate_always):  New DEFUN added.
+
+2000-07-05  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_route.c (ospf_terminate):  Make sure to remove external route
+	when SIGINT received.
+
+2000-07-03  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_flood.c, ospf_ism.c, ospf_lsa,c, ospfd.c:  Make sure to free
+	many structure with `no router ospf'.
+
+2000-06-30  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_neighbor.c (ospf_nbr_new),
+	ospf_nsm.c (nsm_timer_set):  Start LS update timer only
+	when neighbor enters Exchange state.
+
+2000-06-29  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_nsm.c (nsm_timer_set), (nsm_exchange_done),
+	ospf_packet.c (ospf_db_desc_proc):
+	Do not cancel DD retransmit timer when Master.
+
+2000-06-29  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_abr.c (ospf_abr_announce_network_to_area),
+	(ospf_abr_announce_rtr_to_area)
+	ospf_ase.c (ospf_ase_rtrs_register_lsa),
+	ospf_flood.c (ospf_process_self_originated_lsa),
+	(ospf_flood_through_area), (ospf_ls_request_delete),
+	ospf_interface.c (ospf_if_free),
+	ospf_ism.c (ism_change_status),
+	ospf_lsa.c (ospf_router_lsa_update_timer),
+	(ospf_router_lsa_install), (ospf_network_lsa_install),
+	(ospf_lsa_maxage_delete), (ospf_lsa_action),
+	(ospf_schedule_lsa_flood_area),
+	ospf_nsm.c (nsm_change_status),
+	ospf_packet.c (ospf_make_ls_req_func), (ospf_make_ls_ack):
+	Use ospf_lsa_{lock,unlock} for all looking-up of LSA.
+
+	* ospf_flood.c (ospf_ls_request_free):  Function deleted.
+
+	* ospf_lsa.c (ospf_discard_from_db):  New function added.
+
+2000-06-26  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.h (ospf): struct member `external_lsa' name changed to
+	`lsdb'.
+
+2000-06-26  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_lsa_install), (ospf_router_lsa_install),
+	(ospf_network_lsa_install), (ospf_summary_lsa_install),
+	(ospf_summary_asbr_lsa_install), (ospf_external_lsa_install):
+	Functions re-arranged.
+
+	* ospf_lsa.c (IS_LSA_MAXAGE), (IS_LSA_SELF):  Macro added.
+	
+2000-06-20  Michael Rozhavsky <mike@nbase.co.il>
+
+	* ospf_packet.c (ospf_ls_req), (ospf_ls_upd), (ospf_ls_ack):  Add
+	verification of LS type.
+
+2000-06-20  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_ase.c (ospf_ase_calculate_timer):  Add more sanity check
+	whether rn->info is NULL.
+
+2000-06-20  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (show_ip_ospf_interface_sub):  Show Router-ID of both
+	DR and Backup correctly with `show ip ospf interface' command.
+
+2000-06-20  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_lsa_lock), (ospf_lsa_unlock),
+	(ospf_lsa_discard):  These functions are used for avoiding
+	unexpected reference to freed LSAs.
+
+2000-06-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_packet.c (ospf_ls_upd): Initialize lsa by NULL to avoid
+	warning.
+
+2000-06-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_ase.h (ospf_ase_rtrs_register_lsa): Add prototype.
+
+2000-06-12  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_external_lsa_install):  Make sure to register
+	LSA to rtrs_external when replacing AS-external-LSAs in LSDB.
+	Fix core dump.
+
+2000-06-10  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsdb.c (id_to_prefix), (ospf_lsdb_hash_key),
+	(ospf_lsdb_hash_cmp), (ospf_lsdb_new), (ospf_lsdb_iterator),
+	(lsdb_free), (ospf_lsdb_free), (ospf_lsdb_add),	(ospf_lsdb_delete),
+	(find_lsa), (ospf_lsdb_lookup),	(find_by_id),
+	(ospf_lsdb_lookup_by_id), (ospf_lsdb_lookup_by_header):  Functinos
+	removed for migration to new_lsdb.
+
+	* ospf_lsa.c (ospf_summary_lsa_install),
+	(ospf_summary_asbr_lsa_install), (ospf_maxage_lsa_remover),
+	(ospf_lsa_maxage_walker), (ospf_lsa_lookup),
+	(ospf_lsa_lookup_by_id):  Use new_lsdb instead of ospf_lsdb.
+	(count_lsa), (ospf_lsa_count_table), (ospf_lsa_count),
+	(ospf_get_free_id_for_prefix):	Funcitions removed.
+	
+2000-06-09  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_ism.c (ism_interface_down):  Prevent some unneeded DR changes.
+
+	* ospf_packet.c (ospf_db_desc_proc):  Fix memory leak.
+	(ospf_hello):  Always copy router-ID when hello is received.
+
+2000-06-08  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_lsa.h (struct ospf_lsa): Add member of pointer to struct
+	ospf_area.
+
+2000-06-08  Michael Rozhavsky <mike@nbase.co.il>
+
+	* ospf_ase.c (ospf_asbr_route_same):  New function added.
+	This function makes sure external route calculation more 
+	precisely.
+
+2000-06-07  Michael Rozhavsky <mike@nbase.co.il>
+
+	* ospf_ism.c (ism_change_status):  Use ospf_lsa_flush_area for
+	network-LSA deletion instead of using ospf_lsdb_delete.
+	Also cancel network-LSA origination timer.
+
+2000-06-07  Levi Harper  <lharper@kennedytech.com>
+
+	* ospf_interface.c (ospf_if_down): Close read fd when an interface
+	goes down.
+
+2000-06-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_asbr.c (ospf_external_info_lookup): Add explicit brace for
+	avoid ambiguous else.
+
+	* ospf_flood.c (ospf_external_info_check): Likewise.
+
+2000-06-05  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_nsm.c (nsm_adj_ok):  Fix bug of DR election.
+
+2000-06-04  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_zebra.c (ospf_default_information_originate),
+	(no_ospf_default_information_originate):  New DEFUN added.
+
+2000-06-03  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.h, ospf_asbr.h (external_info):  Struct moved from
+	ospf_lsa.h to ospf_asbr.h.
+
+	* ospf_lsa.c, ospf_asbr.c (ospf_external_info_add),
+	(ospf_external_info_delete):  Function moved from ospf_lsa.c
+	to ospf_asbr.c.
+
+2000-06-03  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_flood.c (ospf_external_info_check):  New function added.
+	(ospf_process_self_orignated_lsa):  Make sure to flush
+	self-originated AS-external-LSA, when router reboot and no longer
+	originate those AS-external-LSA.
+
+2000-06-02  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_network.c (ospf_serv_sock):  Remove SO_DONTROUTE
+	socket option.
+
+	* ospf_packet.c (ospf_write):  Set MSG_DONTROUTE flag for
+	unicast destination packets.
+
+2000-06-02  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsdb.c (new_lsdb_delete):  Delete entry from LSDB only when
+	specified LSA matches.
+
+2000-06-02  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_network.c (ospf_serv_sock):  Set SO_DONTROUTE
+	socket option.
+
+2000-06-01  Akihiro Mizutani  <mizutani@dml.com>
+
+	* ospf_dump.c:  Replace string `Debugging functions\n' with DEBUG_STR.
+	Replace string `OSPF information\n' with OSPF_STR.
+
+2000-06-01  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsdb.[ch]:  Use new_lsdb struct for network-LSA instead of
+	ospf_lsdb.
+
+2000-06-01  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_dump.c (config_debug_ospf_packet), (config_debug_ospf_event),
+	(config_debug_ospf_ism), (config_debug_ospf_nsm),
+	(config_debug_ospf_lsa), (config_debug_ospf_zebra),
+	(term_debug_ospf_packet), (term_debug_ospf_event),
+	(term_debug_ospf_ism), (term_debug_ospf_nsm),
+	(term_debug_ospf_lsa), (term_debug_ospf_zebra):  Repalce debug_ospf_*
+	variable to use for debug option flags.
+	
+	(debug_ospf_packet), (debug_ospf_ism), (debug_ospf_nsm),
+	(debug_ospf_lsa), (debug_ospf_zebra):  Set {config,term}_debug_*
+	flags when vty->node is CONFIG_NODE, otherwise set only term_debug_*
+	flags.
+
+	* ospf_dump.h (CONF_DEBUG_PACKET_ON), (CONF_DEBUG_PACKET_OFF),
+	(TERM_DEBUG_PACKET_ON), (TERM_DEBUG_PACKET_OFF),
+	(CONF_DEBUG_ON), (CONF_DEBUG_OFF), (IS_CONF_DEBUG_OSPF_PACKET),
+	(IS_CONF_DEBUG_OSPF):  New Macro added.
+	
+2000-05-31  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (clear_ip_ospf_neighbor):  New DEFUN added.
+	Currently this command is used for only debugging.
+
+	* ospf_nsm.c (nsm_change_status):  Make sure thread cancellation
+	for network-LSA when DR has no full neighbors.
+	
+	* ospf_nsm.c (ospf_db_summary_clear):  New function added.
+
+2000-05-30  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsdb.c (new_lsdb_insert):  LSAs are always freed by
+	maxage_lsa_remover when LSA is replaced.
+
+2000-05-25  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_flood.c (ospf_ls_retransmit_delete_nbr_all):  Add argument
+	`struct ospf_area' to remove LSA from Link State retransmission list
+	of neighbor from only one Area.
+
+2000-05-24  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_lsdb.c (ospf_lsdb_add):  Preserve flags field when
+	overriting old LSA with new LSA.
+
+2000-05-24  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_lsa.c (ospf_router_lsa_body_set):  Fix bug of router-LSA
+	size calculation.
+
+2000-05-22  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_route.c (ospf_intra_add_stub):
+	* ospf_spf.h (struct vertex):  Use u_int32_t for distance (cost)
+	value instead of u_int16_t.
+
+2000-05-22  Axel Gerlach <agerlach@datus.datus.com>
+
+	* ospf_ia.c (ospf_ia_network_route):  Fix bug of Inter-area route
+	equal cost path calculation.
+
+2000-05-21  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_ase.c (ospf_ase_calculate_route_delete):  New function added.
+	Make sure, when rotuer route is deleted, related external routes
+	are also deleted.
+
+2000-05-20  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (ospf_interface_down):  Make sure interface flag is disable
+	and set fd to -1.
+
+2000-05-16  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_asbr.c (ospf_asbr_should_announce), (ospf_asbr_route_remove):
+	Functions removed.
+
+	* ospfd.h (EXTERNAL_INFO):  Macro added.
+	Substitute `ospf_top->external_info[type]' with it.
+
+2000-05-16  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_rtrs_external_remove):  New function added.
+
+2000-05-14  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_flood.c (ospf_ls_retransmit_delete_nbr_all)
+	* ospf_lsdb.c (new_lsdb_insert)
+	* ospf_packet.c (ospf_ls_ack):  Fix database synchonization problem.
+
+2000-05-14  Gleb Natapov <gleb@nbase.co.il>
+
+	* ospf_lsa.h (tv_adjust), (tv_ceil), (tv_floor), (int2tv),
+	(tv_add), (tv_sub), (tv_cmp):  Prototype definition added.
+
+	* ospf_nsm.h (ospf_db_summary_delete_all):  Prototype definition added.
+
+2000-05-13  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.[ch] (ospf_lsa):  struct timestamp type is changed from
+	time_t to struct timeval.
+	(tv_adjust), (tv_ceil), (tv_floor), (int2tv), (tv_add),
+	(tv_sub), (tv_cmp):  timeval utillity functions added.
+
+2000-05-12  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.[ch] (ospf_schedule_update_router_lsas):  Delete function.
+	Change to use macro OSPF_LSA_UPDATE_TIMER instead of using
+	this function.
+	router-LSA refresh timer related stuff is re-organized.
+
+2000-05-10  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_interface.c (ospf_vl_set_params):
+	* ospf_packet.c (ospf_check_network_mask):
+	* ospf_spf.[ch] (ospf_spf_next):
+	Remove field address from `struct vertex', and search for peer
+	address of virtual link in function `ospf_vl_set_params' instead.
+
+2000-05-10  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_packet.c (ospf_ls_upd):  Fix some memory leak related LSA.
+
+2000-05-08  Thomas Molkenbur  <tmo@datus.com>
+
+	* ospf_packet.c (ospf_packet_dup):  Replace ospf_steram_copy()
+	with ospf_stream_dup() to fix memory leak.
+
+2000-05-08  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_flood.c (ospf_flood_through_area):  Fix the problem of
+	LSA update without DROther.
+
+2000-05-04  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_spf.c (ospf_vertex_free):  Fix memory leak of SPF calculation.
+
+2000-05-03  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_neighbor.c (ospf_db_summary_add):  Use new_lsdb struct
+	instead linked-list.
+	(ospf_db_summary_count), (ospf_db_summary_isempty):
+	New function added.
+
+	* ospf_lsa.c (ospf_rotuer_lsa):  Re-arrange and divide functions.
+
+2000-05-02  Gleb Natapov  <gleb@nbase.co.il>
+
+	* ospf_lsdb.c (new_lsdb_cleanup):  Fix memory leak.  When LSDB are
+	not needed any more, then free them.
+
+2000-05-02  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (timers_spf), (no_timers_spf):  New defun added.
+	SPF calculation timers related stuff is rearranged.
+
+	* ospf_spf.c (ospf_spf_calculate_timer_add):  Function removed.
+	SPF timer is scheduled by SPF calculation delay and holdtime
+	configuration variable.
+
+	* ospf_lsa.c (ospf_external_lsa_nexthop_get):  Set AS-external-LSA's
+	forwarding address when nexthop learned by other protocols is
+	in the OSPF domain. 
+
+	* ospf_zebra.c (ospf_redistribute_source_metric_type),
+	(ospf_redistribute_source_type_metric):  Re-arrange DEFUNs and
+	ALIASes.
+
+2000-05-01  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_flood.c (ospf_ls_retransmit_count),
+	(ospf_ls_retransmit_isempty):  New function added.
+
+	(ospf_ls_retransmit_add), (ospf_ls_retransmit_delete),
+	(ospf_ls_retransmit_clear), (ospf_ls_retransmit_lookup),
+	(ospf_ls_retransmit_delete_all), (ospf_ls_retransmit_delete_nbr_all),
+	(ospf_ls_retransmit_add_nbr_all):  Replace these functions to use
+	new_lsdb.
+
+2000-04-29  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (no_network_area):  Add check Area-ID whether specified
+	Area-ID with prefix matches config.
+
+2000-04-27  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_maxage_lsa_remover): Fix problem of
+	remaining withdrawn routes on zebra.
+
+2000-04-25  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_nsm.c (nsm_kill_nbr), (nsm_ll_down), (nsm_change_status),
+	(ospf_nsm_event):  Fix network-LSA re-origination problem.
+
+2000-04-24  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_nsm.c (ospf_db_desc_timer): Fix bug of segmentation fault
+	with DD retransmission.
+
+	* ospf_nsm.c (nsm_kill_nbr): Fix bug of re-origination when
+	a neighbor disappears.
+
+2000-04-23  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_abr.c (ospf_abr_announce_network_to_area):  Fix bug of
+	summary-LSAs reorigination.  Correctly copy OSPF_LSA_APPROVED
+	flag to new LSA. when summary-LSA is reoriginatd.
+
+	* ospf_flood.c (ospf_flood_through_area):  Fix bug of flooding
+	procedure.  Change the condition of interface selection.
+
+2000-04-21  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_refresher_register_lsa): Fix bug of refresh never
+	occurs.
+
+	* ospfd.c (show_ip_ospf_neighbor_id): New defun added.
+	`show ip ospf neighbor' related commands are re-arranged.
+
+2000-04-20  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_dump.c (debug_ospf_zebra): New defun added.
+	Suppress zebra related debug information.
+
+2000-04-19  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_zebra.c (ospf_distribute_list_update_timer),
+	(ospf_distribute_list_update), (ospf_filter_update):
+	New function added.  Re-organize `distribute-list' router ospf
+	command.
+
+2000-04-13  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_packet.c (ospf_make_ls_upd): Add check for MAX_AGE.
+
+2000-04-14  Michael Rozhavsky  <mike@nbase.co.il>
+
+	* ospf_packet.c (ospf_make_ls_upd): Increment LS age by configured 
+	interface transmit_delay.
+
+2000-04-14  Sira Panduranga Rao  <pandu@euler.ece.iisc.ernet.in>
+
+	* ospf_interface.c (ip_ospf_cost), (no_ip_ospf_cost):
+	Add to schedule router_lsa origination when the interface cost changes.
+
+2000-04-12  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_refresher_register_lsa),
+	(ospf_refresher_unregister_lsa): Fix bug of core dumped.
+
+	* ospfd.c (no_router_ospf): Fix bug of core dumped.
+
+2000-03-29  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_nsm.c (nsm_oneway_received): Fix bug of MS flag unset.
+
+2000-03-29  Michael Rozhavsky <mike@nbase.co.il>
+
+	* ospf_lsa.c (ospf_network_lsa):
+	* ospf_nsm.c (ospf_nsm_event): Fix bug of Network-LSA originated
+	in stub network.
+
+2000-03-28  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_nsm.c (nsm_bad_ls_req), (nsm_seq_number_mismatch),
+	(nsm_oneway_received): Fix bug of NSM state flapping between
+	ExStart and Exchange.
+
+2000-03-28  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_packet.h (strcut ospf_header): Fix the size of ospf_header,
+	change u_int8_t to u_char.
+
+2000-03-27  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_lsa.c (ospf_lsa_checksum): Take care of BIGENDIAN architecture.
+
+2000-03-27  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (ospf_interface_run): Make sure Address family matches.
+
+2000-03-26  Love <lha@s3.kth.se>
+
+	* ospf_packet.c (ospf_write): Chack result of sendto().
+
+2000-03-26  Sira Panduranga Rao  <pandu@euler.ece.iisc.ernet.in>
+
+	* ospf_nsm.c (nsm_oneway_received): Fix bug of 1-WayReceived in NSM.
+
+2000-03-23  Libor Pechacek  <farco@clnet.cz>
+
+	* ospf_lsa.c (ospf_network_lsa)
+	* ospf_lsdb.c (new_lsdb_insert): Fix bug of accessing to
+	unallocated memory.
+
+2000-03-23  Toshiaki Takada  <takada@zebra.org>
+
+	* ospfd.c (ospf_config_write): Fix bug of duplicate line for
+	`area A.B.C.D authentication'.
+
+2000-03-22  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_debug.c (debug_ospf_lsa), (no_debug_ospf_lsa): Defun added.
+	Suppress all zlog related to LSAs with this config option.
+
+2000-03-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* ospf_nsm.c (ospf_nsm_event): Add check for NSM_InactivityTimer.
+
+2000-03-21  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_packet.c (ospf_ls_upd_timer), (ospf_ls_req):
+	Fix bug of memory leak about linklist.
+
+	* ospf_flood.c (ospf_flood_through_area): Likewise.
+
+2000-03-18  Sira Panduranga Rao  <pandu@euler.ece.iisc.ernet.in>
+
+	* ospf_flood.c (ospf_ls_retransmit_lookup): Add checksum comparison
+	to identify LSA uniquely.  This fix routes lost.
+
+2000-03-18  Toshiaki Takada  <takada@zebra.org>
+
+	* ospf_ase.c (ospf_find_asbr_route): Add sanity check with router
+	routing table.
+
+2000-03-17  Alex Zinin  <zinin@amt.ru>
+	
+        * ospf_spf.[ch]: Bug fix.
+        The 2nd stage of Dijkstra could consider one vertex
+        more than once if there is more than one link
+        between the routers, thus adding extra CPU overhead
+        and extra next-hops.
+        Fixed.
+
+2000-03-15  Sira Panduranga Rao  <pandu@euler.ece.iisc.ernet.in>
+
+        * ospf_nsm.c (nsm_inactivity_timer): Changed to call nsm_kill_nbr().
+
+2000-03-14  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_route.c (ospf_route_copy_nexthops): Fix bug of memory leak of
+        ospf_path.  Actually ignore merging ospf_route with completely same 
+        paths.
+
+2000-03-12  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (show_as_external_lsa_detail): fix bug of 
+        external route tag byte order.
+
+2000-03-11  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsdb.c (ospf_lsdb_insert): New function added.
+
+2000-03-09  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (ospf_external_lsa_install),
+        (ospf_lsa_lookup), (show_ip_ospf_database_all),
+        (show_ip_ospf_database_self_originate): Use struct new_lsdb for
+        LSDB of AS-external-LSAs instead of ospf_lsdb.
+
+        * ospf_lsa.c (ospf_lsa_unique_id): New function added.
+        Use for assigning Unique Link State ID instead of
+        ospf_get_free_id_for_prefix().
+
+2000-03-09  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ase.c (ospf_ase_calculate_timer): Fix bug of segmentation
+        fault reported by George Bonser <george@siteROCK.com>.
+
+2000-03-07  Libor Pechacek  <farco@clnet.cz>
+
+        * ospfd.c (ospf_interface_down): Fix bug of segmentation fault.
+
+2000-03-06  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_route.c (ospf_route_cmp): Change meaning of return values.
+
+2000-03-02  Alex Zinin <zinin@amt.ru>
+        * ospfd.h, ospf_ia.h
+        New Shortcut ABR code. Now area's flag can be configured
+        with Default, Enable, and Disable values.
+        More info will be in the new ver of I-D soon (see IETF web).
+
+2000-02-25  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (ospf_lsa_header_set), (ospf_external_lsa_body_set),
+        (osfp_external_lsa_originate), (ospf_external_lsa_queue),
+        (ospf_external_lsa_originate_from_queue): New function added.
+        (ospf_external_lsa): Function removed.
+
+        * ospf_zebra.c (ospf_zebra_read_ipv4): Originate AS-external-LSA
+        when listen a route from Zebra, instead creating external route.
+
+        * ospf_asbr.c (ospf_asbr_route_add_flood_lsa),
+        (ospf_asbr_route_add_queue_lsa),
+        (ospf_asbr_route_install_lsa), (ospf_asbr_route_add):
+        Functions removed.
+
+        * ospf_ase.c (process_ase_lsa): Function will not be used.
+        (ospf_ase_calculate), (ospf_ase_calculate_route_add),
+        (ospf_ase_calculate_new_route), (ospf_ase_caluculate_asbr_route):
+        process_ase_lsa () is separated to these functions.
+
+        OSPF AS-external-LSA origination is whole re-organized.
+
+2000-02-18  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_ls_upd): Fix bug of OSPF LSA memory leak.
+
+        * ospf_asbr.c (ospf_asbr_route_add_flood_lsa),
+        (ospf_asbr_route_add_queue_lsa): Fix bug of OSPF external route
+        memory leak.
+
+2000-02-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_asbr.c (ospf_asbr_route_install_lsa): Re-calculate LSA
+        checksum after change Advertised Router field.
+
+2000-02-09  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_asbr.c (ospf_external_route_lookup): Add new function.
+
+2000-02-08  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c (ospf_router_id_get), (ospf_router_id_update),
+        (ospf_router_id_update_timer): Router ID decision algorithm is changed.
+        Router ID is chosen from all of eligible interface addresses even if
+        it is not enable to OSPF.
+
+2000-02-08  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_asbr.c (ospf_asbr_route_add): Function divided to
+        ospf_asbr_route_add_flood_lsa, ospf_asbr_route_add_queue_lsa and
+        ospf_asbr_route_install_lsa.  If Router-ID is not set, then LSA is
+        waited to install to LSDB.
+        `0.0.0.0 adv_router' AS-external-LSA origination bug was fixed.
+
+2000-02-01  Sira Panduranga Rao  <pandu@euler.ece.iisc.ernet.in>
+
+        * ospf_flood.c (ospf_ls_retransmit_lookup): Compare LS seqnum
+        in the ACK before deleting.
+
+        * ospf_packet.c (ospf_hello): Reset the flags after a shutdown
+        and no shutdown of the interface.
+
+2000-01-31  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_ls_req): Send multiple Link State Update
+        packets respond to a Link State Request packet.
+
+        * ospfd.c (show_ip_ospf_neighbor_detail_sub): Show thread state.
+
+        * ospf_interface.c (ospf_vl_new): Crash when backbone area
+        is not configured and set virtual-link to no-backbone area,
+        bug fixed.
+
+2000-01-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_neighbor.h (struct ospf_neighbor): Add pointer to last send
+        LS Request LSA.
+
+        * ospf_packet.c (ospf_ls_upd): Comment out LS request list
+        treatment.  That should be done in OSPF flooding procedure.
+
+        * ospf_flood.c (ospf_flood_through_area): Enclose
+        ospf_check_nbr_loding inside if-else close.
+
+2000-01-31  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_make_ls_upd): Fix bug of #LSAs counting.
+
+2000-01-29  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_make_md5_digest): Fix bug of md5 authentication.
+
+2000-01-28  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c (show_ip_ospf): Show Number of ASE-LSAs.
+
+2000-01-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_packet.c (ospf_make_db_desc): Don't use rm_list for
+        removing LSA from nbr->db_summary.
+
+2000-01-27  Sira Panduranga Rao <pandu@euler.ece.iisc.ernet.in>
+
+        * ospf_packet.c (ospf_ls_upd_send): Set AllSPFRouters to
+        destination when the link is point-to-point.
+        (ospf_ls_ack_send_delayed): Likewise.
+
+2000-01-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_flood.c (ospf_ls_request_delete_all): Fix bug of next
+        pointer lookup after the node is freed.
+
+2000-01-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_asbr.c (ospf_asbr_route_add): Instead of scanning all AS
+        external route, use ospf_top->external_self.
+
+2000-01-27  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (ospf_forward_address_get): New function added.
+
+        * ospf_asbr.c (ospf_asbr_check_lsas): Originate AS-external-LSA
+        only when it should be replaced.
+
+2000-01-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_flood.c (ospf_ls_retransmit_clear): Delete list node.
+
+        * ospf_lsa.c (ospf_lsa_free): Reduce logging message using
+        ospf_zlog value.
+
+        * ospf_ism.c (ism_change_status): Fix bug of DR -> non DR status
+        change.  Self originated LSA is freed but not deleted from lsdb.
+
+2000-01-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_ism.c (ism_interface_down): Don't use router_id for
+        detecting self neighbor structure.  Instead of that compare
+        pointer itself.
+
+        * ospf_neighbor.c (ospf_nbr_free): Cancel all timer when neighbor
+        is deleted.
+        (ospf_nbr_free): Free last send packet.
+
+        * ospf_neighbor.h (struct ospf_neighbor): Remove host strucutre.
+        Instead of that src is introduced.
+
+        * ospf_nsm.h: Enclose macro defenition with do {} while (0).
+
+2000-01-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospfd.c: Change part of passive interface implementation.  For
+        passive interface just disabling sending/receiving Hello on the
+        interface.
+
+2000-01-16  Kai Bankett <kai.bankett@vew-telnet.net>
+
+        * ospf_interface.h (OSPF_IF_PASSIVE): Add passive flag.
+        * ospf_interface.c (ospf_if_lookup_by_name): Add new function.
+        * ospf_lsa.c (ospf_router_lsa): Skip passive interface.
+        * ospfd.c (passive_interface): New command passive-interface is
+        added.
+        (ospf_config_write): Print passive interface.
+
+2000-01-15  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_interface.h (crypt_key): New struct added to store
+        multiple cryptographic autheitication keys.
+        (ospf_interface): struct changed.
+
+        * ospf_interface.c: ospf_crypt_key_new, ospf_crypt_key_add,
+        ospf_crypt_key_lookup, ospf_crypt_key_delete: new functions added.
+
+        * ospf_packet.c (ip_ospf_message_digest_key): Changed to store
+        multiple cryptographic authentication keys.
+
+2000-01-14  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_interface.c: DEFUN (if_ospf_*) commands changed name to
+        ip_ospf_* ().
+        Old notation `ospf *' still remains backward compatibility.
+
+1999-12-29  Alex Zinin  <zinin@amt.ru>
+        * ospf_lsa.c: ospf_lsa_more_recent() bug fix
+        * ospf_nsm.c, ospf_packet.c: remove nbr data struct when
+          int goes down, also check DD flags correctly (bug fix)
+
+1999-12-28  Alex Zinin  <zinin@amt.ru>
+        * "redistribute <source> metric-type (1|2) metric <XXX>" added
+
+1999-12-23  Alex Zinin  <zinin@amt.ru>
+        * added RFC1583Compatibility flag
+        * added dynamic interface up/down functionality
+
+1999-11-19  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_neighbor.h (struct ospf_neighbor): Add member state_change
+        for NSM state change statistics.
+
+1999-11-19  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c (show_ip_ospf_neighbor_detail),
+        (show_ip_ospf_neighbor_int_detail): DEFUN Added.
+
+1999-11-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_asbr.c (ospf_asbr_check_lsas): Add check of
+        lsa->refresh_list.
+
+1999-11-11  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ia.[ch] (OSPF_EXAMINE_SUMMARIES_ALL): Macro added.
+        This macro is expanded to ospf_examine_summaries ()
+        for SUMMARY_LSA and SUMMARY_LSA_ASBR.
+        (OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL): Macro added.
+        This macro is expanded to ospf_examine_transit_summaries ()
+        for SUMMARY_LSA and SUMMARY_LSA_ASBR.
+
+1999-11-11  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.[ch] (ospf_find_self_summary_lsa_by_prefix): Changed to
+        macro OSPF_SUMMARY_LSA_SELF_FIND_BY_PREFIX.
+        (ospf_find_self_summary_asbr_lsa_by_prefix): Changed to
+        macro OSPF_SUMMARY_ASBR_LSA_SELF_FIND_BY_PREFIX.
+        (ospf_find_self_external_lsa_by_prefix): Changed to
+        macro OSPF_EXTERNAL_LSA_SELF_FIND_BY_PREFIX.
+
+1999-11-11  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c (ospf_abr_type): ospf_abr_type_cisco, ospf_abr_type_ibm,
+        ospf_abr_type_shortcut and ospf_abr_type_standard DEFUNs are
+        combined.
+        * ospfd.c (no_ospf_abr_type): no_ospf_abr_type_cisco,
+        no_ospf_abr_type_ibm and no_ospf_abr_type_shortcut DEFUNS are
+        combined.
+
+1999-11-10  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_route.c (ospf_lookup_int_by_prefix): Move function to
+        ospf_interface.c and change name to ospf_if_lookup_by_prefix ().
+
+1999-11-01  Alex Zinin <zinin@amt.ru>
+        * ospf_packet.c 
+        some correction to LSU processing
+
+        * ospf_lsa.c ospfd.h 
+        randomize initial LSA refreshment interval
+        and limit the size of LSA-group to 10
+        to let randomization work more effectively.
+
+1999-10-31  Alex Zinin <zinin@amt.ru>
+        * ospf_interface.c 
+        cancel t_network_lsa_self
+        when freeing int structure
+
+        *  ospf_abr.c ospf_asbr.c ospf_flood.c ospf_lsa.c 
+           ospf_lsa.h ospf_lsdb.h ospfd.c ospfd.h
+
+        Summary and ASE LSA refreshment functions
+        added---LSA refreshment is paced to 70 LSAs
+        per sec to avoid link overflow. Refreshment events
+        are further randomized within a 10 sec interval
+        to avoid syncing.
+        
+        Also the sigfault of memcmp() in ospf_lsa_is_different()
+        is fixed.
+
+1999-10-30  Alex Zinin <zinin@amt.ru>
+        * ospf_nsm.c 
+        Fix the bug where MAX_AGE LSAs
+        are included into the DB summary.
+
+        * ospf_interface.c 
+        allocate 2*MTU input buffer instead of just MTU
+        for the cases when the other router mistakenly
+        sends larger packets thus causing fragmentation, etc.
+
+        * ospf_nsm.c
+        in nsm_reset_nbr() lists should be freed
+        not when they are empty.
+
+1999-10-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_zebra.c (ospf_acl_hook): Move OSPF_IS_ASBR and OSPF_IS_ABR
+        check inside of if (ospf_top).
+
+1999-10-29  Alex Zinin <zinin@amt.ru>
+        * ospf_lsa.c ospf_lsdb.c :
+        add assertion in lsa and lsa->data alloc functions,
+        as well as in lsdb_add for new->data
+
+        * ospf_lsdb.c: free hash table correctly
+
+1999-10-28  John Capo <jc@irbs.com>
+
+        * ospf_packet.h (OSPF_PACKET_MAX): Correct MAX packet length
+        calculation
+
+1999-10-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * OSPF-TRAP-MIB.txt: New file added. Edited version of RFC1850.
+
+        * OSPF-MIB.txt: New file added.  Edited version of RFC1850.
+
+1999-10-27  Alex Zinin  <zinin@amt.ru>
+        * ospfd, ospf_zebra, ospf_abr
+        "area import-list" command is added.
+        This command allows to filter the inter-area routes
+        injected into an area. Access list hook function
+        extended to invalidate area exp/imp lists.
+
+1999-10-25  Yoshinobu Inoue  <shin@nd.net.fujitsu.co.jp>
+
+        * ospfd.c (ospf_interface_run): Enable to detect P2P network
+        on an OSPF interface.
+
+1999-10-19  Jordan Mendelson  <jordy@wserv.com>
+
+        * ospf_lsdb.c (ospf_lsdb_add): Fix bug of crash
+        in ospf_ls_retransmit_lookup ().
+
+1999-10-19  Vladimir B. Grebenschikov <vova@express.ru>
+
+        * ospf_route.c: Workaround about installation of OSPF routes into
+        the zebra daemon.  Add checking of existance routes.  Free
+        ospf_top->old_table if it exists.
+
+1999-10-15  Jordan Mendelson <jordy@wserv.com>
+
+        * Add support for MD5 authentication.
+
+1999-10-12  Alex Zinin  <zinin@amt.ru>
+        * ospfd.c, ospfd.h, ospf_abr.c:
+          a new command "area export-list" was added, it allows
+          the admin. to control which intra-area routes are
+          announced to other areas by the ABR
+
+1999-10-12  Alex Zinin  <zinin@amt.ru>
+        * ospf_asbr.c (ospf_asbr_check_lsas): Fix bug of coredump
+          when "no redistribute" is used after a distribute list
+          denying some networks was used
+
+1999-10-05  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_route.c (ospf_path_dup): New function added.
+
+1999-10-05  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_interface.[ch]: Some of VL related funciton name changed.
+
+1999-09-27  Alex Zinin  <zinin@amt.ru>
+
+        * ospf_zebra.c: Distribute-list functionality added
+
+1999-09-27  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c (show_ip_ospf): Fix bug of segmentation fault when no ospf
+        instance exists.
+
+1999-09-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospfd.c (ospf_interface_down): Fix bug of misusing nextnode()
+        instead of node->next.  Reported by Hiroki Ishibashi
+        <ishibasi@dcd.abk.nec.co.jp>.
+
+        * ospf_route.c (show_ip_ospf_route): Add check for ospf is enabled
+        or not.
+
+1999-09-23  Alex Zinin  <zinin@amt.ru>
+
+        * stub area support added
+
+1999-09-23  Alex Zinin  <zinin@amt.ru>
+
+        * fwd_addr in ASE-LSAs is now set correctly
+        * ASE routing changed to check the fwd_addr
+        and skip the route if the addr points to one
+        of our interfaces to avoid loops.
+
+1999-09-22  Alex Zinin  <zinin@amt.ru>
+
+        * ospf_interface:
+        ospf_vls_in_area() added, it returns 
+        the number of VLs configured through the area
+
+        * ospf_interface.c ospf_lsa.c ospf_lsdb.c ospfd.c 
+        honor correct mem alloc
+
+1999-09-22  Alex Zinin  <zinin@amt.ru>
+
+        * memory.[ch]:
+        Some OSPF mem types added,
+        plus more info in "show mem"
+
+1999-09-21  Alex Zinin  <zinin@amt.ru>
+
+        * ospfd.c:
+        "area range substitute" added.
+        It can be used on NAT-enabled (IP-masquarade)
+        routers to announce private networks
+        from an area as public ones into the outside
+        world (not in the RFC, btw :)
+
+1999-09-21  Alex Zinin  <zinin@amt.ru>
+
+        * ospfd.c:
+        "area range suppress" added.
+        This command allows to instruct the router
+        to be silent about specific ranges, i.e.,
+        it is a method of route filtering on area
+        borders
+
+1999-09-21  Alex Zinin  <zinin@amt.ru>
+
+        * ospfd.c VLs removed when "no network area" executed
+
+1999-09-20  Alex Zinin  <zinin@amt.ru>
+
+        * ospf_ase.c bug fix for not-zero fwd_addr 
+        and directly connected routes.
+
+1999-09-20  Yon Uriarte <yon@plannet.de>
+
+        * ospf_packet.c (ospf_make_ls_req): Introduce delta value for
+        checking the length of OSPF packet exceeds MTU or not.
+
+        * ospf_lsa.c (ospf_lsa_different): Apply ntohs for checking
+        l1->data->length.
+
+1999-09-18  Alex Zinin  <zinin@amt.ru>
+
+        * ospf_lsa.c bug fix for ospf_network_lsa() to
+        include itself into the RID list
+
+1999-09-10  Alex Zinin  <zinin@amt.ru>
+
+        * Alternative ABR behaviors IBM/Cisco/Shortcut
+        implemented
+
+1999-09-10  Alex Zinin  <zinin@amt.ru>
+
+        * router and network-LSA origination
+        changed to honor MinLSInterval
+
+1999-09-08  Alex Zinin  <zinin@amt.ru>
+
+        * modified ABR behavior to honor VLs and transit
+          areas
+
+1999-09-07  Alex Zinin  <zinin@amt.ru>
+
+        * completed VL functionality
+
+1999-09-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_asbr.c: New file.
+        ospf_asbr.h: New file.
+
+        * ospf_zebra.c (ospf_redistribute_connected): Add redistribute
+        related stuff.
+
+1999-09-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospfd.h (OSPF_FLAG_VIRTUAL_LINK): Change OSPF_FLAG_VEND to
+        OSPF_FLAG_VIRTUAL_LINK for comprehensiveness.
+
+1999-09-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_spf.c (ospf_spf_register): Change name from
+        ospf_spf_route_add() to ospf_spf_register().
+        Include "ospfd/ospf_abr.h" for ospf_abr_task() prototype.
+
+1999-09-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_lsa.c (ospf_external_lsa_install): Change to update
+        lsa->data rather than install new one, when same id lsa is already
+        installed.
+
+1999-09-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_lsa.c (ospf_router_lsa_install): Return lsa value.
+        (ospf_network_lsa_install): Likewise.
+        (ospf_summary_lsa_install): Likewise.
+        (ospf_summary_asbr_lsa_install): Likewise.
+        (ospf_external_lsa_install): Likewise.
+
+        * ospf_spf.c (ospf_spf_calculate): Comment out debug function
+        ospf_rtrs_print().
+
+1999-08-31  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_spf.c (ospf_rtrs_free): Add ospf_spf_calculate() for
+        freeing rtrs.
+
+1999-08-31  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (show_ip_ospf_database_summary),
+        (show_ip_ospf_database_summary_asbr),
+        (show_ip_ospf_database_external): New function added.
+        `show ip ospf database summary',
+        `show ip ospf database asbr-summary'
+        `show ip ospf database external' command can be used.
+
+        * ospf_lsa.c (ospf_lsa_count_table): New function added.
+        (show_ip_ospf_database_all): show nothing if a type of LSA
+        does not exist.
+        
+1999-08-31  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_lsa.c (ospf_maxage_lsa_remover): Preserve next pointer when
+        the node is deleted.
+
+1999-08-31  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_flood.c (ospf_ls_retransmit_lookup): change to return
+        struct ospf_lsa *.
+        (ospf_ls_request_new), (ospf_ls_request_free),
+        (ospf_ls_request_add), (ospf_ls_request_delete),
+        (ospf_ls_request_delete_all), (ospf_ls_request_lookup):
+        New function added.
+
+        * ospf_packet.c (ospf_ls_upd_send_lsa): New function added.
+
+        * ospf_lsa.h (LS_AGE): Slightly change macro definition.
+
+        * ospf_lsa.c (ospf_lsa_more_recent), (ospf_lsa_diffrent):
+        Use LS_AGE macro.
+
+1999-08-30  Alex Zinin <zinin@amt.ru>
+        
+        * ospfd.c
+        fix a bug with area range config write
+        added "show ip ospf" command, it will be enhanced later on
+
+1999-08-30  Alex Zinin <zinin@amt.ru>
+
+        * ospf_lsa.c
+        updated ospf_router_lsa() to honor flags (B-bit)
+
+1999-08-30  Alex Zinin <zinin@amt.ru>
+
+        * ospf_abr.c
+        wrote major functions implementing ABR activity
+
+1999-08-30  Alex Zinin <zinin@amt.ru>
+
+        * ospf_ia.c ospf_route.c ospf_route.h 
+        fixed the bug with ospf_route.origin field.
+        Now it holds pointer to lsa_header
+
+1999-08-30  Alex Zinin <zinin@amt.ru>
+
+        * ospf_flood.c ospf_flood.h:
+        transformed ospf_flood_if_select into ospf_flood_through_area()
+        added new ospf_flood_if_select() and ospf_flood_through_as()
+
+1999-08-30  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_flood.[ch]: New file added.
+
+        * ospf_packet.c (ospf_lsa_flooding),
+        (ospf_lsa_flooding_select_if): functions move to ospf_flood.c
+
+        * ospf_neighbor.c (ospf_put_lsa_on_retransm_list),
+        (ospf_remove_lsa_from_retransm_list),
+        (ospf_nbr_remove_all_lsas_from_retransm_list),
+        (ospf_lsa_remove_from_ls_retransmit):
+        (ospf_lsa_retransmit): functions move to
+        ospf_flood.c, and change function's name:
+
+        ospf_put_lsa_on_retransm_list ()
+          -> ospf_ls_retransmit_add ()
+        ospf_remove_lsa_from_retransm_list ()
+          -> ospf_ls_retransmit_delete ()
+        ospf_nbr_remove_all_lsas_from_retransm_list ()
+          -> ospf_ls_retransmit_clear ()
+        ospf_lsa_remove_from_ls_retransmit ()
+          -> ospf_ls_retransmit_delete_nbr_all ()
+        ospf_lsa_retransmit ()
+          -> ospf_ls_retransmit_add_nbr_all ()
+
+        * ospf_lsa.c (ospf_lsa_lookup_from_list): function move to
+        ospf_flood.c, and change name to ospf_ls_retransmit_lookup ().
+
+1999-08-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_neighbor.c (ospf_nbr_lookup_by_addr): Use
+        route_node_lookup() instead of route_node_get().
+
+        * ospf_packet.c (ospf_ls_upd): Temporary comment out (6) check.
+
+1999-08-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_route.c (ospf_lookup_int_by_prefix): Add check of
+        oi->address.
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospf_lsa.c 
+        MaxAge LSA deletion functions added.
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospf_neighbor.c 
+        ospf_nbr_lookup_by_addr(): added route_unlock_node()
+        when function returns NULL if (rn->info == NULL)
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospfd.c
+        added a hack for area range deletion
+        
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospf_lsa.h 
+        included lsdb field into struct ospf_lsa, to find
+        LSDB easier when removing MaxAge LSAs.
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospf_lsa.c ospf_neighbor.c ospf_nsm.c 
+          ospf_packet.c changed to honor new retransmit list
+          management functions
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospf_neighbor.c , .h added new retransmit list functions.
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * Makefile.in
+        added ospf_ase, ospf_abr, ospf_ia
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospf_spf.c:
+        - changed ospf_next_hop_calculation() to include interface
+          and nexthop addr for directly connected routers---more informative
+          and solves problem with route installation into the kernel
+        - changed ospf_nexthop_out_if_addr() to support routers, not only
+          transit networks
+        - added ospf_process_stubs();
+
+1999-08-29  Alex Zinin <zinin@amt.ru>
+        * ospf_lsa.c:
+        - changed ospf_router_lsa() to provide correct links
+          for p-t-p interfaces;
+        - changed ospf_summary_lsa_install() to support table
+          of self-originated summary-LSAs;
+        - added ospf_summary_asbr_lsa_install() and ospf_external_lsa_install()
+        - changed ospf_lsa_install() accordingly
+        - changed show_ip_ospf_database_router_links() to support p-t-p
+
+1999-08-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_packet.c (ospf_make_db_desc): Only master can clear more
+        flag.
+
+1999-08-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_packet.c (ospf_read): Add check of IP src address.
+
+1999-08-28  Alex Zinin <zinin@amt.ru>
+        * ospf_neighbor.h
+        added ospf_nbr_lookup_by_routerid()
+
+1999-08-28  Alex Zinin <zinin@amt.ru>
+        * ospfd.h
+        added ABR/ASBR flag definitions and fields;
+        added iflist field to area structure;
+        summary_lsa_self and summary_lsa_asbr_self are changed
+        to be route tables;
+        added ranges field---configured area ranges;
+        A separate Routers RT added;
+        area range config commands and config write added
+
+
+1999-08-28  Alex Zinin <zinin@amt.ru>
+        * ospf_route.c :
+        ospf_route_free()--added code to free the list of paths;
+        The following functions added:
+                ospf_intra_add_router();
+                ospf_intra_add_transit();
+                ospf_intra_add_stub();
+        the last function uses new ospf_int_lookup_by_prefix();
+        show_ip_ospf_route_cmd()--changed to support new RT structure;
+        added ospf_cmp_routes()--general route comparision function;
+        added ospf_route_copy_nexthops() and ospf_route_copy_nexthops_from_vertex()
+        they are used in ASE and IA routing;
+        added ospf_subst_route() and ospf_add_route();
+
+1999-08-28  Alex Zinin <zinin@amt.ru>
+        * ospf_route.h :
+        changed struct ospf_path to include output interface,
+        changed struct ospf_route to support IA and ASE routing.
+        added prototypes of the function used in IA and ASE modules.
+
+1999-08-28  Alex Zinin <zinin@amt.ru>
+        * ospf_lsa.h ospf_lsa.c :
+        added ospf_my_lsa(), an interface independent version of
+        ospf_lsa_is_self_originated(), it will be used in ASE and IA-routing.
+
+1999-08-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_interface.c (interface_config_write): Add check for
+        oi->nbr_self.
+
+1999-08-25  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (ospf_lsa_dup): New function added.
+
+        * ospf_packet.c (ospf_write), (ospf_read): Print send/recv
+        interface in debug message.
+
+1999-08-25  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_ls_ack_send): The name is changed from
+        `ospf_ls_ack_send'.
+        (ospf_ls_ack_send_delayed) (ospf_ls_ack_timer): New function added.
+        Delayed Link State Acknowledgment is scheduled by timer.
+
+1999-08-25  Alex Zinin  <zinin@amt.ru>
+
+        * ospf_lsa.c (ospf_router_lsa): Incorrectly included link to
+        a stub network instead of link to a transit network into
+        originated router-LSA, bug fixed.
+
+1999-08-24  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c (ospf_update_router_id): New function added.
+
+        * ospf_network.c (ospf_write): Create new socket per transmission.
+        And select outgoing interface whether dst is unicast or multicast.
+
+        * ospf_packet.c: LSA flooding will work.        
+
+1999-08-24  VOP <vop@unity.net>
+
+        * ospf_route.c: Include "sockunion.h"
+
+1999-08-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_network.c (ospf_serv_sock_init): Enclose
+        IPTOS_PREC_INTERNETCONTROL setting with #ifdef for OS which does
+        not have the definition.
+
+1999-08-23  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c: Fix bug of DD processing.
+
+1999-08-18  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (show_ip_ospf_database): Show actual `LS age'.
+
+1999-08-17  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.h (OSPF_MAX_LSA): The value of OSPF_MAX_LSA is
+        corrected.  The bug of `mes_lookup' is fixed.  
+        This had been reported by Poul-Henning Kamp <phk@freebsd.org>.
+
+        * ospf_lsa.c (ospf_router_lsa_install): The name is changed from
+        `ospf_add_router_lsa'.
+        (ospf_network_lsa_install): The name is changed from
+        `ospf_add_network_lsa'.
+
+        * ospf_interface.h (ospf_interface): Add member `nbr_self'.
+
+        * ospf_interface.c (ospf_if_is_enable): New function added.
+
+1999-08-16  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.h (struct lsa_header): The name is changed from
+        `struct ospf_lsa'.
+        (struct ospf_lsa): New struct added to control each LSA's aging
+        and timers.     
+
+        * ospf_lsa.c (ospf_lsa_data_free): The name is change from
+        `ospf_lsa_free'.
+        (ospf_lsa_data_new), (ospf_lsa_new), (ospf_lsa_free),
+        (ospf_lsa_different), (ospf_lsa_install): New function added.
+
+        * ospf_packet.c (ospf_ls_upd_list_lsa): New function added.
+
+1999-08-12  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_nsm.c (nsm_reset_nbr): New function added.
+        KillNbr and LLDown neighbor event call this function.
+        
+1999-08-10  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_ls_retransmit)
+        (ospf_ls_upd_timer): New function added.
+        Set retransmission timer for Link State Update.
+
+1999-07-29  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ism.c (ospf_dr_election): Fix bug of DR election.
+
+1999-07-28  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_network.c (ospf_serv_sock_init): Set IP precedence field
+        with IPTOS_PREC_INTERNET_CONTROL.
+
+        * ospf_nsm.c (nsm_change_status): Schedule NeighborChange event
+        if NSM status change.
+        
+        * ospf_packet.c (ospf_make_hello): Never include a neighbor in
+        Hello packet, when the neighbor goes down.
+
+1999-07-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * Makefile.am (noinst_HEADERS): Add ospf_route.h.
+
+        * ospf_route.c (show_ip_ospf_route): Add `show ip ospf route'
+        command.
+
+1999-07-25  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (ospf_router_lsa): Fix bug of LS sequence number
+        assignement.
+
+1999-07-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_route.c (ospf_route_table_free): New function added.
+
+        * ospf_spf.c (ospf_spf_next): Free vertex w when cw's and w's
+        distance is same.
+
+        * ospfd.h (struct ospf): Add old_table.
+
+        * ospf_main.c (sighup): Call of log_rotate () removed.
+
+        * ospf_lsa.c (ospf_lsa_is_self_originated): Fix bug of checking
+        area->lsa as self LSA.  This should be area->lsa_self.
+
+1999-07-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_zebra.c (ospf_zebra_add): ospf_zebra_add
+        (),ospf_zebra_delete () added.
+
+        * ospf_spf.c (ospf_spf_calculate): Call ospf_intra_route_add ().
+
+1999-07-24  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c: Change LS sequence number treatment.
+        (ospf_lsa_is_self_originated): New function added.
+        (show_ip_ospf_database_self_originated): New DEFUN added.
+        
+1999-07-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_interface.c (ospf_if_lookup_by_addr): Add loopback check.
+
+1999-07-22  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_spf.c (ospf_nexthop_new), (ospf_nexthop_free),
+        (ospf_nexthop_dup): function added.
+        (ospf_nexthop_calculation): function changed.
+
+        * ospf_interface.c (ospf_if_lookup_by_addr): function added.
+        
+1999-07-21  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_spf.c (ospf_spf_closest_vertex): function removed.
+        
+1999-07-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_spf.c (ospf_spf_next): Apply ntohs for fetching metric.
+
+1999-07-21  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_neighbor.c (ospf_nbr_lookup_by_router_id): fundtion removed.
+
+        * ospf_lsa.c (show_ip_ospf_database_router): describe each
+        connected link.
+
+1999-07-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_spf.c (ospf_spf_next): V is router LSA or network LSA so
+        change behavior according to LSA type.
+        (ospf_lsa_has_link): Link check function is added.
+
+1999-07-20  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_spf.c (ospf_spf_calculate_schedule): Add new function for
+        SPF calcultion schedule addtition.
+        (ospf_spf_calculate_timer_add): Rough 30 sec interval SPF calc
+        timer is added.
+        (ospf_spf_next_router): Delete ospf_spf_next_network ().
+
+        * ospf_lsa.c (show_ip_ospf_database_all): Network-LSA display
+        header typo correction.  Display of router LSA's #link added.
+
+1999-07-19  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_check_network_mask): Added new function for
+        receiving Raw IP packet on an appropriate interface.
+
+1999-07-16  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c (ospf_router_id): new DEFUN added.
+
+1999-07-15  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_spf.c (ospf_spf_init), (ospf_spf_free),
+        (ospf_spf_has_vertex), (ospf_vertex_lookup),
+        (ospf_spf_next_router), (ospf_spf_next_network),
+        (ospf_spf_closest_vertex), (ospf_spf_calculate):
+        function added.
+
+1999-07-13  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ism.c: fix bug of DR Election.
+
+        * ospf_nsm.c: fix bug of adjacency forming.
+
+1999-07-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospfd.c (ospf_init): Change to use install_default.
+
+1999-07-01  Rick Payne <rickp@rossfell.co.uk>
+
+        * ospf_zebra.c (zebra_init): Install standard commands to
+        ZEBRA_NODE.
+
+1999-06-30  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_dump.c: Whole debug command is improved.
+        (ISM|NSM) (events|status|timers) debug option added.
+        (show_debugging_ospf): new DEFUN added.
+
+1999-06-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_lsa.c (ospf_lsa_lookup_from_list): Change !IPV4_ADDR_CMP to
+        IPV4_ADDR_SAME.
+
+1999-06-29  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_dump.c (ospf_summary_lsa_dump): Add summary-LSA dump routine.
+        (ospf_as_external_lsa_dump): Add AS-external-LSA dump routine.
+
+        * ospf_nsm.c (nsm_twoway_received): fix condtion of adjacnet.
+
+        * ospf_ism.c (ospf_dr_election): fix DR Election.
+        
+        * ospf_dump.c (ospf_nbr_state_message): fix `show ip ospf neighbor'
+        command's state.
+
+1999-06-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_dump.c (ospf_router_lsa_dump): Add router-LSA dump routine.
+
+1999-06-28  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (show_ip_ospf_database_network): fix bug of
+        `show ip ospf database network' command output.
+
+        * ospf_nsm.c (nsm_inactivity_timer): Clear list of Link State
+        Retransmission, Database Summary and Link State Request.
+
+        * ospf_packet.c (ospf_ls_req_timer): New function added.
+        Set Link State Request retransmission timer.
+
+1999-06-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_main.c (main): Change default output from ZLOG_SYSLOG to
+        ZLOG_STDOUT.
+
+        * ospfd.c (ospf_init): Register show_ip_ospf_interface_cmd and
+        show_ip_ospf_neighbor_cmd to VIEW_NODE.
+
+        * ospf_lsa.c (ospf_lsa_init): Register show_ip_ospf_database_cmd
+        and show_ip_ospf_database_type_cmd to VIEW_NODE.
+
+1999-06-25  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c: fix bug of DD making.
+        fix bug of LS-Update reading.
+        
+1999-06-23  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c: All type of packets are changed to use
+        fifo queue structure.
+        (ospf_fill_header) function added.
+
+1999-06-22  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c (ospf_packet_new): New function added to handle
+        sending ospf packet by fifo queue structure.
+        (ospf_packet_free), (ospf_fifo_new), (ospf_fifo_push),
+        (ospf_fifo_pop), (ospf_fifo_head), (ospf_fifo_flush),
+        (ospf_fifo_free): Likewise.
+
+1999-06-21  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_nsm.c (ospf_db_desc_timer): function added.
+        (nsm_timer_set) function added.
+        * ospf_dump.c (ospf_option_dump): function added.
+        * ospf_packet.c (ospf_ls_req) (ospf_make_ls_req): function added.
+
+1999-06-20  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c (ospf_lsa_more_recent): function added.
+        * ospf_neighbor.h (struct ospf_neighbor): Change member ms_flag
+        to dd_flags.
+        
+1999-06-19  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c: DEFUN (show_ip_ospf_database) Added.
+        * ospf_interface.c (if_ospf_cost), (if_ospf_dead_interval),
+        (if_ospf_hello_interval), (if_ospf_priority),
+        (if_ospf_retransmit_interval), (if_ospf_transmit_delay)
+        argument changed from NUMBER to <range>.
+        DEFUN (if_ospf_network_broadcast),
+        DEFUN (if_ospf_network_non_broadcast),
+        DEFUN (if_ospf_network_point_to_multipoint),
+        DEFUN (if_ospf_network_point_to_point) functions are combined to
+        DEFUN (if_ospf_network).
+        
+1999-06-18  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c: ospf_add_router_lsa (), ospf_add_network_lsa (),
+        ospf_lsa_lookup (), ospf_lsa_count () Added.
+
+1999-06-15  Toshiaki Takada  <takada@zebra.org>
+
+        * DEFUN (ospf_debug_ism), DEFUN (ospf_debug_nsm),
+        DEFUN (no_ospf_debug_ism), DEFUN (no_ospf_debug_nsm) Added.
+        `debug ospf ism' command shows debug message.
+        `debuf ospf nsm' command shows debug message.
+
+1999-06-14  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c: ospf_network_lsa () Added.
+        ospf_lsa_checksum () Added.
+        * DEFUN (ospf_debug_packet), DEFUN (no_ospf_debug_packet) Added.
+        `debug ospf packet' command shows debug message.
+
+1999-06-13  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.h: Remove struct ospf_ls_req {}, ospf_ls_upd {},
+        ospf_ls_ack {}.
+
+1999-06-11  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_dump.c: fix IP packet length treatment.
+
+1999-06-10  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ism.h: Add OSPF_ISM_EVENT_EXECUTE() Macro Added.
+        * ospf_nsm.h: Add OSPF_NSM_EVENT_EXECUTE() Macro Added.
+
+        * ospf_packet.c: ospf_db_desc (), ospf_db_desc_send () Added.
+        ospf_make_hello (), ospf_make_db_desc () Added.
+        ospf_db_desc_proc () Added.n
+
+        * Database Description packet can be processed.
+
+1999-06-08  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.c: New file.
+        
+1999-06-07  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_neighbor.c: ospf_fully_adjacent_count () Added.
+
+1999-06-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_spf.[ch]: New file.
+
+1999-05-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_zebra.c: Changed to use lib/zclient.c routines.
+
+        * ospf_zebra.h (zebra_start): Remove struct zebra.
+
+1999-05-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospfd.c (ospf_config_write): Add cast (unsigned long int) to
+        ntohl for sprintf warning.
+
+1999-05-19  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ism.c (ospf_dr_election): Join AllDRouters Multicast group
+        if interface state changes to DR or BDR.
+
+1999-05-14  Stephen R. van den Berg <srb@cuci.nl>
+
+        * ospf_main.c (signal_init): SIGTERM call sigint.
+        (sigint): Logging more better message.
+
+1999-05-12  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c: Fix bug of `no router ospf' statement, it will work.
+
+1999-05-11  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_neighbor.c: ospf_nbr_free () Added.
+
+1999-05-10  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.h: struct ospf_area { }, struct ospf_network { } Changed.
+        * Fix bug of `no network' statement, it will work.
+
+1999-05-07  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_interface.c, ospf_zebra.c: Fix bug of last interface is not
+        updated by ospf_if_update ().
+
+1999-04-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * Makefile.am (noinst_HEADERS): Add ospf_lsa.h for distribution.
+
+1999-04-25  Toshiaki Takada <takada@zebra.org>
+
+        * ospf_interface.c: DEFUN (no_if_ospf_cost),
+        DEFUN (no_if_ospf_dead_interval),
+        DEFUN (no_if_ospf_hello_interval),
+        DEFUN (no_if_ospf_priority),
+        DEFUN (no_if_ospf_retransmit_interval),
+        DEFUN (no_if_ospf_transmit_delay) Added.
+
+        interface_config_write () suppress showing interface
+        default values.
+
+1999-04-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_dump.c (ospf_timer_dump): If thread is NULL return "inactive".
+
+        * ospfd.c (ospf_if_update): Fix bug of using ospf_area { } instead
+        of ospf_network { }.  So `router ospf' statement in ospfd.conf
+        works again.
+        (ospf_if_update): Call ospf_get_router_id for updating router ID.
+
+1999-04-25  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_interface.c: DEFUN (if_ospf_network) deleted.
+        DEFUN (if_ospf_network_broadcast),
+        DEFUN (if_ospf_network_non_broadcast),
+        DEFUN (if_ospf_network_point_to_multipoint),
+        DEFUN (if_ospf_network_point_to_point),
+        DEFUN (no_if_ospf_network) Added.
+
+1999-04-23  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.h: struct area { } changed to struct ospf_network { }.
+        Add struct ospf_area { }.
+        * ospfd.c: Add ospf_area_lookup_by_area_id (), ospf_network_new (),
+        and ospf_network_free ().
+        DEFUN (area_authentication), DEFUN (no_area_authentication) Added.
+
+1999-04-22  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_lsa.h: New file.
+        * ospf_packet.h: LSA related struct definition are moved to
+        ospf_lsa.h.
+        * ospf_packet.c: ospf_verify_header () Added.
+
+1999-04-21  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ism.c: ospf_elect_dr () and related function is changed.
+        DR Election bug fixed.
+        * ospf_dump.c: ospf_nbr_state_message (), ospf_timer_dump () Added.
+        * ospfd.c: DEFUN (show_ip_ospf_neighbor) Added.
+
+1999-04-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_main.c (main): access_list_init () is added for vty
+        connection filtering.
+
+1999-04-16  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.c: DEFUN (show_ip_ospf_interface) Added.
+        * ospf_neighbor.c: ospf_nbr_count () Added.
+        
+1999-04-15  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.h: struct ospf { } Changed.
+        * ospfd.c: ospf_lookup_by_process_id () Deleted.
+        * ospf_ism.c: ospf_wait_timer () Added. WaitTimer will work.
+
+1999-04-14  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ism.c: ospf_elect_dr () Added.
+        * ospf_network.c: ospf_if_ipmulticast () Added.
+
+1999-04-11  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_interface.c: interface_config_write (),
+        DEFUN (if_ip_ospf_cost),
+        DEFUN (if_ip_ospf_dead_interval),
+        DEFUN (if_ip_ospf_hello_interval),
+        DEFUN (if_ip_ospf_priority),
+        DEFUN (if_ip_ospf_retransmit_interval) and
+        DEFUN (if_ip_ospf_transmit_delay) Added.
+
+1999-04-08  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_dump.c: ospf_packet_db_desc_dump () Added.
+        * ospf_neighbor.c: ospf_nbr_bidirectional () Added.
+        * ospf_nsm.c: nsm_twoway_received () Added.
+
+1999-04-02  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_neighbor.c: New file.
+        * ospf_neighbor.h: New file.
+        * ospf_nsm.c: New file.
+        * ospf_nsm.h: New file.
+        * ospf_packet.c: Add ospf_make_header (), ospf_hello () and
+        ospf_hello_send (). Now OSPFd can receive Hello and send Hello.
+
+1999-03-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_packet.c: Add ospf_recv_packet ().  Now OSPF Hello can receive.
+
+1999-03-19  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_packet.c: New file.
+        * ospf_packet.h: New file.
+        * ospf_network.c: New file.
+        * ospf_network.h: New file.
+        * ospfd.h: move OSPF message structure has moved to ospf_packet.h.
+
+1999-03-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * ospf_zebra.c (ospf_zebra_get_interface): Fix for IPv6 interface
+        address.
+
+        * Makefile.am (install-sysconfDATA): Overwrite install-sysconfDATA
+        for install ospfd.conf.sample as owner read only file.
+
+        * ospf_main.c (usage): Change to use ZEBRA_BUG_ADDRESS.
+
+1999-03-15  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_ism.c: New file.
+        * ospf_ism.h: New file.
+        * ospf_dump.c: New file.
+        * ospf_dump.h: New file.
+
+        * ospfd.h: Add (struct ospf), (struct config_network),
+        (struct message) structure.
+
+        * ospf_interface.c: Add ospf_if_match_network ().
+        * ospf_interface.h (struct ospf_interface): Change struct members.
+
+        * ospfd.c: ospf_lookup_by_process_id (), ospf_network_new (),
+        DEFUN (network_area): Added.
+
+        * ospfd.conf.sample: Change sample configuration.
+
+1999-03-05  Toshiaki Takada  <takada@zebra.org>
+
+        * ospf_interface.c: New file.
+        * ospf_interface.h: New file.
+        * ospf_zebra.h: New file.
+        * ospf_zebra.c: Add interface function for zebra daemon.
+        * ospfd.c: New file.
+
+1999-02-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * Move IPv6 codes and files to ospf6d directory.
+
+1999-02-18  Peter Galbavy  <Peter.Galbavy@knowledge.com>
+
+        * syslog support added
+
+1998-12-22  Toshiaki Takada  <takada@zebra.org>
+
+        * ospfd.h: New file.
+        * ospf_lsa.h: New file.
+
+1998-12-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+        * Makefile.am: New file.
+        * ospf_main.c: New file.
+
diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am
new file mode 100644
index 0000000..1ced11c
--- /dev/null
+++ b/ospfd/Makefile.am
@@ -0,0 +1,44 @@
+## Process this file with automake to produce Makefile.in.
+
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
+DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
+INSTALL_SDATA=@INSTALL@ -m 600
+
+noinst_LIBRARIES = libospf.a
+sbin_PROGRAMS = ospfd
+
+libospf_a_SOURCES = \
+	ospfd.c ospf_zebra.c ospf_interface.c ospf_ism.c ospf_neighbor.c \
+	ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \
+	ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \
+	ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \
+	ospf_opaque.c ospf_te.c ospf_vty.c
+
+noinst_HEADERS = \
+	ospf_dump.h ospf_interface.h ospf_ism.h ospf_neighbor.h \
+	ospf_network.h ospf_nsm.h ospf_packet.h ospf_zebra.h ospfd.h \
+	ospf_lsa.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \
+	ospf_flood.h ospf_lsdb.h ospf_asbr.h ospf_snmp.h ospf_opaque.h \
+	ospf_te.h ospf_vty.h
+
+ospfd_SOURCES = \
+	ospf_main.c $(libospf_a_SOURCES)
+
+ospfd_LDADD = ../lib/libzebra.a
+
+sysconf_DATA = ospfd.conf.sample
+
+EXTRA_DIST = $(sysconf_DATA) OSPF-MIB.txt OSPF-TRAP-MIB.txt
+
+install-sysconfDATA: $(sysconf_DATA)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+	@list='$(sysconf_DATA)'; for p in $$list; do \
+	  if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  else if test -f $$p; then \
+	    echo " $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  fi; fi; \
+	done
diff --git a/ospfd/Makefile.in b/ospfd/Makefile.in
new file mode 100644
index 0000000..8472535
--- /dev/null
+++ b/ospfd/Makefile.in
@@ -0,0 +1,532 @@
+# Makefile.in generated by automake 1.7 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BGPD = @BGPD@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURSES = @CURSES@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+IF_METHOD = @IF_METHOD@
+IF_PROC = @IF_PROC@
+
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPFORWARD = @IPFORWARD@
+KERNEL_METHOD = @KERNEL_METHOD@
+LDFLAGS = @LDFLAGS@
+LIBPAM = @LIBPAM@
+LIBS = @LIBS@
+LIB_IPV6 = @LIB_IPV6@
+LIB_REGEX = @LIB_REGEX@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MULTIPATH_NUM = @MULTIPATH_NUM@
+OBJEXT = @OBJEXT@
+OSPF6D = @OSPF6D@
+OSPFD = @OSPFD@
+OTHER_METHOD = @OTHER_METHOD@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RIPD = @RIPD@
+RIPNGD = @RIPNGD@
+RTREAD_METHOD = @RTREAD_METHOD@
+RT_METHOD = @RT_METHOD@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VTYSH = @VTYSH@
+ZEBRA = @ZEBRA@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+INSTALL_SDATA = @INSTALL@ -m 600
+
+noinst_LIBRARIES = libospf.a
+sbin_PROGRAMS = ospfd
+
+libospf_a_SOURCES = \
+	ospfd.c ospf_zebra.c ospf_interface.c ospf_ism.c ospf_neighbor.c \
+	ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \
+	ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \
+	ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \
+	ospf_opaque.c ospf_te.c ospf_vty.c
+
+
+noinst_HEADERS = \
+	ospf_dump.h ospf_interface.h ospf_ism.h ospf_neighbor.h \
+	ospf_network.h ospf_nsm.h ospf_packet.h ospf_zebra.h ospfd.h \
+	ospf_lsa.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \
+	ospf_flood.h ospf_lsdb.h ospf_asbr.h ospf_snmp.h ospf_opaque.h \
+	ospf_te.h ospf_vty.h
+
+
+ospfd_SOURCES = \
+	ospf_main.c $(libospf_a_SOURCES)
+
+
+ospfd_LDADD = ../lib/libzebra.a
+
+sysconf_DATA = ospfd.conf.sample
+
+EXTRA_DIST = $(sysconf_DATA) OSPF-MIB.txt OSPF-TRAP-MIB.txt
+subdir = ospfd
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+libospf_a_AR = $(AR) cru
+libospf_a_LIBADD =
+am_libospf_a_OBJECTS = ospfd.$(OBJEXT) ospf_zebra.$(OBJEXT) \
+	ospf_interface.$(OBJEXT) ospf_ism.$(OBJEXT) \
+	ospf_neighbor.$(OBJEXT) ospf_nsm.$(OBJEXT) ospf_dump.$(OBJEXT) \
+	ospf_network.$(OBJEXT) ospf_packet.$(OBJEXT) ospf_lsa.$(OBJEXT) \
+	ospf_spf.$(OBJEXT) ospf_route.$(OBJEXT) ospf_ase.$(OBJEXT) \
+	ospf_abr.$(OBJEXT) ospf_ia.$(OBJEXT) ospf_flood.$(OBJEXT) \
+	ospf_lsdb.$(OBJEXT) ospf_asbr.$(OBJEXT) ospf_routemap.$(OBJEXT) \
+	ospf_snmp.$(OBJEXT) ospf_opaque.$(OBJEXT) ospf_te.$(OBJEXT) \
+	ospf_vty.$(OBJEXT)
+libospf_a_OBJECTS = $(am_libospf_a_OBJECTS)
+sbin_PROGRAMS = ospfd$(EXEEXT)
+PROGRAMS = $(sbin_PROGRAMS)
+
+am__objects_1 = ospfd.$(OBJEXT) ospf_zebra.$(OBJEXT) \
+	ospf_interface.$(OBJEXT) ospf_ism.$(OBJEXT) \
+	ospf_neighbor.$(OBJEXT) ospf_nsm.$(OBJEXT) ospf_dump.$(OBJEXT) \
+	ospf_network.$(OBJEXT) ospf_packet.$(OBJEXT) ospf_lsa.$(OBJEXT) \
+	ospf_spf.$(OBJEXT) ospf_route.$(OBJEXT) ospf_ase.$(OBJEXT) \
+	ospf_abr.$(OBJEXT) ospf_ia.$(OBJEXT) ospf_flood.$(OBJEXT) \
+	ospf_lsdb.$(OBJEXT) ospf_asbr.$(OBJEXT) ospf_routemap.$(OBJEXT) \
+	ospf_snmp.$(OBJEXT) ospf_opaque.$(OBJEXT) ospf_te.$(OBJEXT) \
+	ospf_vty.$(OBJEXT)
+am_ospfd_OBJECTS = ospf_main.$(OBJEXT) $(am__objects_1)
+ospfd_OBJECTS = $(am_ospfd_OBJECTS)
+ospfd_DEPENDENCIES = ../lib/libzebra.a
+ospfd_LDFLAGS =
+
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/ospf_abr.Po ./$(DEPDIR)/ospf_asbr.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_ase.Po ./$(DEPDIR)/ospf_dump.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_flood.Po ./$(DEPDIR)/ospf_ia.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_interface.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_ism.Po ./$(DEPDIR)/ospf_lsa.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_lsdb.Po ./$(DEPDIR)/ospf_main.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_neighbor.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_network.Po ./$(DEPDIR)/ospf_nsm.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_opaque.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_packet.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_route.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_routemap.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_snmp.Po ./$(DEPDIR)/ospf_spf.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_te.Po ./$(DEPDIR)/ospf_vty.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/ospf_zebra.Po ./$(DEPDIR)/ospfd.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES = $(libospf_a_SOURCES) $(ospfd_SOURCES)
+DATA = $(sysconf_DATA)
+
+HEADERS = $(noinst_HEADERS)
+
+DIST_COMMON = $(noinst_HEADERS) ChangeLog Makefile.am Makefile.in
+SOURCES = $(libospf_a_SOURCES) $(ospfd_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  ospfd/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libospf.a: $(libospf_a_OBJECTS) $(libospf_a_DEPENDENCIES) 
+	-rm -f libospf.a
+	$(libospf_a_AR) libospf.a $(libospf_a_OBJECTS) $(libospf_a_LIBADD)
+	$(RANLIB) libospf.a
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sbindir)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \
+	   $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \
+	  rm -f $(DESTDIR)$(sbindir)/$$f; \
+	done
+
+clean-sbinPROGRAMS:
+	-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+ospfd$(EXEEXT): $(ospfd_OBJECTS) $(ospfd_DEPENDENCIES) 
+	@rm -f ospfd$(EXEEXT)
+	$(LINK) $(ospfd_LDFLAGS) $(ospfd_OBJECTS) $(ospfd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_abr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_asbr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_ase.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_flood.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_ia.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_interface.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_ism.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_lsa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_lsdb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_neighbor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_network.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_nsm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_opaque.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_packet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_route.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_routemap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_snmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_spf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_te.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_vty.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf_zebra.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospfd.Po@am__quote@
+
+distclean-depend:
+	-rm -rf ./$(DEPDIR)
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@	  -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCC_TRUE@	then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@	fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@	  -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \
+@am__fastdepCC_TRUE@	then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@	fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`
+uninstall-info-am:
+sysconfDATA_INSTALL = $(INSTALL_DATA)
+
+uninstall-sysconfDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sysconf_DATA)'; for p in $$list; do \
+	  f="`echo $$p | sed -e 's|^.*/||'`"; \
+	  echo " rm -f $(DESTDIR)$(sysconfdir)/$$f"; \
+	  rm -f $(DESTDIR)$(sysconfdir)/$$f; \
+	done
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$tags$$unique" \
+	  || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	     $$tags $$unique
+
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS)
+
+installdirs:
+	$(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(sysconfdir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES clean-sbinPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+	distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-sbinPROGRAMS install-sysconfDATA
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS \
+	uninstall-sysconfDATA
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstLIBRARIES clean-sbinPROGRAMS ctags distclean \
+	distclean-compile distclean-depend distclean-generic \
+	distclean-tags distdir dvi dvi-am info info-am install \
+	install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-sbinPROGRAMS install-strip install-sysconfDATA \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-info-am uninstall-sbinPROGRAMS \
+	uninstall-sysconfDATA
+
+
+install-sysconfDATA: $(sysconf_DATA)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+	@list='$(sysconf_DATA)'; for p in $$list; do \
+	  if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  else if test -f $$p; then \
+	    echo " $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  fi; fi; \
+	done
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ospfd/OSPF-MIB.txt b/ospfd/OSPF-MIB.txt
new file mode 100644
index 0000000..de7d03f
--- /dev/null
+++ b/ospfd/OSPF-MIB.txt
@@ -0,0 +1,2723 @@
+OSPF-MIB DEFINITIONS ::= BEGIN
+
+    IMPORTS
+            MODULE-IDENTITY, OBJECT-TYPE, Counter32, Gauge32,
+            Integer32, IpAddress
+                FROM SNMPv2-SMI
+            TEXTUAL-CONVENTION, TruthValue, RowStatus
+                FROM SNMPv2-TC
+            MODULE-COMPLIANCE, OBJECT-GROUP          FROM SNMPv2-CONF
+            mib-2                                    FROM RFC1213-MIB;
+
+--  This MIB module uses the extended OBJECT-TYPE macro as
+--  defined in [9].
+
+ospf MODULE-IDENTITY
+        LAST-UPDATED "9501201225Z" -- Fri Jan 20 12:25:50 PST 1995
+        ORGANIZATION "IETF OSPF Working Group"
+        CONTACT-INFO
+       "       Fred Baker
+       Postal: Cisco Systems
+               519 Lado Drive
+               Santa Barbara, California 93111
+       Tel:    +1 805 681 0115
+       E-Mail: fred@cisco.com
+
+               Rob Coltun
+       Postal: RainbowBridge Communications
+       Tel:    (301) 340-9416
+       E-Mail: rcoltun@rainbow-bridge.com"
+    DESCRIPTION
+       "The MIB module to describe the OSPF Version 2
+       Protocol"
+    ::= { mib-2 14 }
+
+--  The Area ID, in OSPF, has the same format as an IP Address,
+--  but has the function of defining a summarization point for
+--  Link State Advertisements
+
+AreaID ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "An OSPF Area Identifier."
+    SYNTAX      IpAddress
+
+
+--  The Router ID, in OSPF, has the same format as an IP Address,
+--  but identifies the router independent of its IP Address.
+
+RouterID ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "A OSPF Router Identifier."
+    SYNTAX      IpAddress
+
+
+--  The OSPF Metric is defined as an unsigned value in the range
+
+Metric ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "The OSPF Internal Metric."
+    SYNTAX      Integer32 (0..'FFFF'h)
+
+BigMetric ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "The OSPF External Metric."
+    SYNTAX      Integer32 (0..'FFFFFF'h)
+
+--  Status Values
+
+Status ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "The status of an interface: 'enabled' indicates that
+       it is willing to communicate with other OSPF Routers,
+       while 'disabled' indicates that it is not."
+    SYNTAX      INTEGER { enabled (1), disabled (2) }
+
+--  Time Durations measured in seconds
+
+PositiveInteger ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "A positive integer. Values in excess are precluded as
+       unnecessary and prone to interoperability issues."
+    SYNTAX      Integer32 (0..'7FFFFFFF'h)
+
+HelloRange ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "The range of intervals on which hello messages are
+       exchanged."
+    SYNTAX      Integer32 (1..'FFFF'h)
+
+UpToMaxAge ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "The values that one might find or configure for
+       variables bounded by the maximum age of an LSA."
+    SYNTAX      Integer32 (0..3600)
+
+
+--  The range of ifIndex
+
+InterfaceIndex ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "The range of ifIndex."
+    SYNTAX      Integer32
+
+
+--  Potential Priorities for the Designated Router Election
+
+DesignatedRouterPriority ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "The values defined for the priority of a system for
+       becoming the designated router."
+    SYNTAX      Integer32 (0..'FF'h)
+
+TOSType ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+       "Type of Service is defined as a mapping to the IP Type of
+       Service Flags as defined in the IP Forwarding Table MIB
+
+       +-----+-----+-----+-----+-----+-----+-----+-----+
+       |                 |                       |     |
+       |   PRECEDENCE    |    TYPE OF SERVICE    |  0  |
+       |                 |                       |     |
+       +-----+-----+-----+-----+-----+-----+-----+-----+
+
+                IP TOS                IP TOS
+           Field     Policy      Field     Policy
+
+           Contents    Code      Contents    Code
+           0 0 0 0  ==>   0      0 0 0 1  ==>   2
+           0 0 1 0  ==>   4      0 0 1 1  ==>   6
+           0 1 0 0  ==>   8      0 1 0 1  ==>  10
+           0 1 1 0  ==>  12      0 1 1 1  ==>  14
+           1 0 0 0  ==>  16      1 0 0 1  ==>  18
+           1 0 1 0  ==>  20      1 0 1 1  ==>  22
+           1 1 0 0  ==>  24      1 1 0 1  ==>  26
+           1 1 1 0  ==>  28      1 1 1 1  ==>  30
+
+       The remaining values are left for future definition."
+    SYNTAX      Integer32 (0..30)
+
+
+--  OSPF General Variables
+
+--      These parameters apply globally to the Router's
+--      OSPF Process.
+
+ospfGeneralGroup OBJECT IDENTIFIER ::= { ospf 1 }
+
+
+    ospfRouterId OBJECT-TYPE
+        SYNTAX   RouterID
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "A  32-bit  integer  uniquely  identifying  the
+           router in the Autonomous System.
+
+           By  convention,  to  ensure  uniqueness,   this
+           should  default  to  the  value  of  one of the
+           router's IP interface addresses."
+       REFERENCE
+          "OSPF Version 2, C.1 Global parameters"
+      ::= { ospfGeneralGroup 1 }
+
+
+    ospfAdminStat OBJECT-TYPE
+        SYNTAX   Status
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "The  administrative  status  of  OSPF  in  the
+           router.   The  value 'enabled' denotes that the
+           OSPF Process is active on at least  one  inter-
+           face;  'disabled'  disables  it  on  all inter-
+           faces."
+       ::= { ospfGeneralGroup 2 }
+
+    ospfVersionNumber OBJECT-TYPE
+        SYNTAX   INTEGER    { version2 (2) }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The current version number of the OSPF  proto-
+           col is 2."
+       REFERENCE
+          "OSPF Version 2, Title"
+      ::= { ospfGeneralGroup 3 }
+
+
+    ospfAreaBdrRtrStatus OBJECT-TYPE
+        SYNTAX   TruthValue
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "A flag to note whether this router is an  area
+           border router."
+       REFERENCE
+          "OSPF Version 2, Section 3 Splitting the AS into
+          Areas"
+      ::= { ospfGeneralGroup 4 }
+
+
+    ospfASBdrRtrStatus OBJECT-TYPE
+        SYNTAX   TruthValue
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "A flag to note whether this router is  config-
+           ured as an Autonomous System border router."
+       REFERENCE
+          "OSPF Version 2, Section 3.3  Classification  of
+          routers"
+      ::= { ospfGeneralGroup 5 }
+
+    ospfExternLsaCount OBJECT-TYPE
+        SYNTAX   Gauge32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of external (LS type 5)  link-state
+           advertisements in the link-state database."
+       REFERENCE
+          "OSPF Version 2, Appendix A.4.5 AS external link
+          advertisements"
+      ::= { ospfGeneralGroup 6 }
+
+
+    ospfExternLsaCksumSum OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The 32-bit unsigned sum of the LS checksums of
+           the  external  link-state  advertisements  con-
+           tained in the link-state  database.   This  sum
+           can  be  used  to determine if there has been a
+           change in a router's link state  database,  and
+           to  compare  the  link-state  database  of  two
+           routers."
+       ::= { ospfGeneralGroup 7 }
+
+
+    ospfTOSSupport OBJECT-TYPE
+        SYNTAX   TruthValue
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "The router's support for type-of-service rout-
+           ing."
+       REFERENCE
+          "OSPF Version 2,  Appendix  F.1.2  Optional  TOS
+          support"
+      ::= { ospfGeneralGroup 8 }
+
+    ospfOriginateNewLsas OBJECT-TYPE
+        SYNTAX   Counter32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of  new  link-state  advertisements
+           that  have been originated.  This number is in-
+           cremented each time the router originates a new
+           LSA."
+       ::= { ospfGeneralGroup 9 }
+
+
+    ospfRxNewLsas OBJECT-TYPE
+        SYNTAX   Counter32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of  link-state  advertisements  re-
+           ceived  determined  to  be  new instantiations.
+           This number does not include  newer  instantia-
+           tions  of self-originated link-state advertise-
+           ments."
+       ::= { ospfGeneralGroup 10 }
+
+    ospfExtLsdbLimit OBJECT-TYPE
+        SYNTAX   Integer32 (-1..'7FFFFFFF'h)
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "The  maximum   number   of   non-default   AS-
+           external-LSAs entries that can be stored in the
+           link-state database.  If the value is -1,  then
+           there is no limit.
+
+           When the number of non-default AS-external-LSAs
+           in   a  router's  link-state  database  reaches
+           ospfExtLsdbLimit, the router  enters  Overflow-
+           State.   The   router  never  holds  more  than
+           ospfExtLsdbLimit  non-default  AS-external-LSAs
+           in  its  database. OspfExtLsdbLimit MUST be set
+           identically in all routers attached to the OSPF
+           backbone  and/or  any regular OSPF area. (i.e.,
+           OSPF stub areas and NSSAs are excluded)."
+       DEFVAL { -1 }
+       ::= { ospfGeneralGroup 11 }
+
+    ospfMulticastExtensions OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "A Bit Mask indicating whether  the  router  is
+           forwarding  IP  multicast  (Class  D) datagrams
+           based on the algorithms defined in  the  Multi-
+           cast Extensions to OSPF.
+
+           Bit 0, if set, indicates that  the  router  can
+           forward  IP multicast datagrams in the router's
+           directly attached areas (called intra-area mul-
+           ticast routing).
+
+           Bit 1, if set, indicates that  the  router  can
+           forward  IP  multicast  datagrams  between OSPF
+           areas (called inter-area multicast routing).
+
+           Bit 2, if set, indicates that  the  router  can
+           forward  IP  multicast  datagrams between Auto-
+           nomous Systems (called inter-AS multicast rout-
+           ing).
+
+           Only certain combinations of bit  settings  are
+           allowed,  namely: 0 (no multicast forwarding is
+           enabled), 1 (intra-area multicasting  only),  3
+           (intra-area  and  inter-area  multicasting),  5
+           (intra-area and inter-AS  multicasting)  and  7
+           (multicasting  everywhere). By default, no mul-
+           ticast forwarding is enabled."
+       DEFVAL { 0 }
+       ::= { ospfGeneralGroup 12 }
+
+    ospfExitOverflowInterval OBJECT-TYPE
+        SYNTAX   PositiveInteger
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "The number of  seconds  that,  after  entering
+           OverflowState,  a  router will attempt to leave
+           OverflowState. This allows the router to  again
+           originate  non-default  AS-external-LSAs.  When
+           set to 0, the router will not  leave  Overflow-
+           State until restarted."
+       DEFVAL { 0 }
+       ::= { ospfGeneralGroup 13 }
+
+
+    ospfDemandExtensions OBJECT-TYPE
+        SYNTAX   TruthValue
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "The router's support for demand routing."
+       REFERENCE
+          "OSPF Version 2, Appendix on Demand Routing"
+      ::= { ospfGeneralGroup 14 }
+
+
+--      The OSPF Area Data Structure contains information
+--      regarding the various areas. The interfaces and
+--      virtual links are configured as part of these areas.
+--      Area 0.0.0.0, by definition, is the Backbone Area
+
+
+    ospfAreaTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfAreaEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "Information describing the configured  parame-
+           ters  and cumulative statistics of the router's
+           attached areas."
+       REFERENCE
+          "OSPF Version 2, Section 6  The Area Data Struc-
+          ture"
+      ::= { ospf 2 }
+
+
+    ospfAreaEntry OBJECT-TYPE
+        SYNTAX   OspfAreaEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "Information describing the configured  parame-
+           ters  and  cumulative  statistics of one of the
+           router's attached areas."
+       INDEX { ospfAreaId }
+       ::= { ospfAreaTable 1 }
+
+OspfAreaEntry ::=
+    SEQUENCE {
+        ospfAreaId
+            AreaID,
+        ospfAuthType
+            Integer32,
+        ospfImportAsExtern
+            INTEGER,
+        ospfSpfRuns
+            Counter32,
+        ospfAreaBdrRtrCount
+            Gauge32,
+        ospfAsBdrRtrCount
+            Gauge32,
+        ospfAreaLsaCount
+            Gauge32,
+        ospfAreaLsaCksumSum
+            Integer32,
+        ospfAreaSummary
+            INTEGER,
+        ospfAreaStatus
+            RowStatus
+              }
+
+    ospfAreaId OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "A 32-bit integer uniquely identifying an area.
+           Area ID 0.0.0.0 is used for the OSPF backbone."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfAreaEntry 1 }
+
+
+    ospfAuthType OBJECT-TYPE
+        SYNTAX   Integer32
+                    -- none (0),
+                    -- simplePassword (1)
+                    -- md5 (2)
+                    -- reserved for specification by IANA (> 2)
+        MAX-ACCESS   read-create
+        STATUS   obsolete
+        DESCRIPTION
+           "The authentication type specified for an area.
+           Additional authentication types may be assigned
+           locally on a per Area basis."
+       REFERENCE
+          "OSPF Version 2, Appendix E Authentication"
+      DEFVAL { 0 }        -- no authentication, by default
+      ::= { ospfAreaEntry 2 }
+
+    ospfImportAsExtern OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    importExternal (1),
+                    importNoExternal (2),
+                    importNssa (3)
+                  }
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The area's support for importing  AS  external
+           link- state advertisements."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      DEFVAL { importExternal }
+      ::= { ospfAreaEntry 3 }
+
+
+    ospfSpfRuns OBJECT-TYPE
+        SYNTAX   Counter32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of times that the intra-area  route
+           table  has  been  calculated  using this area's
+           link-state database.  This  is  typically  done
+           using Dijkstra's algorithm."
+       ::= { ospfAreaEntry 4 }
+
+
+    ospfAreaBdrRtrCount OBJECT-TYPE
+        SYNTAX   Gauge32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The total number of area border routers reach-
+           able within this area.  This is initially zero,
+           and is calculated in each SPF Pass."
+       ::= { ospfAreaEntry 5 }
+
+    ospfAsBdrRtrCount OBJECT-TYPE
+        SYNTAX   Gauge32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The total number of Autonomous  System  border
+           routers  reachable  within  this area.  This is
+           initially zero, and is calculated in  each  SPF
+           Pass."
+       ::= { ospfAreaEntry 6 }
+
+
+    ospfAreaLsaCount OBJECT-TYPE
+        SYNTAX   Gauge32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The total number of link-state  advertisements
+           in  this  area's link-state database, excluding
+           AS External LSA's."
+       ::= { ospfAreaEntry 7 }
+
+
+    ospfAreaLsaCksumSum OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The 32-bit unsigned sum of the link-state  ad-
+           vertisements'  LS  checksums  contained in this
+           area's link-state database.  This sum  excludes
+           external (LS type 5) link-state advertisements.
+           The sum can be used to determine if  there  has
+           been  a  change  in a router's link state data-
+           base, and to compare the link-state database of
+           two routers."
+       DEFVAL   { 0 }
+       ::= { ospfAreaEntry 8 }
+
+    ospfAreaSummary OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    noAreaSummary (1),
+                    sendAreaSummary (2)
+                  }
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The variable ospfAreaSummary controls the  im-
+           port  of  summary LSAs into stub areas.  It has
+           no effect on other areas.
+
+           If it is noAreaSummary, the router will neither
+           originate  nor  propagate summary LSAs into the
+           stub area.  It will rely entirely  on  its  de-
+           fault route.
+
+           If it is sendAreaSummary, the router will  both
+           summarize and propagate summary LSAs."
+       DEFVAL   { noAreaSummary }
+       ::= { ospfAreaEntry 9 }
+
+
+    ospfAreaStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfAreaEntry 10 }
+
+
+--  OSPF Area Default Metric Table
+
+--      The OSPF Area Default Metric Table describes the metrics
+--      that a default Area Border Router will advertise into a
+--      Stub area.
+
+
+    ospfStubAreaTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfStubAreaEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The set of metrics that will be advertised  by
+           a default Area Border Router into a stub area."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2, Area Parameters"
+      ::= { ospf 3 }
+
+
+    ospfStubAreaEntry OBJECT-TYPE
+        SYNTAX   OspfStubAreaEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The metric for a given Type  of  Service  that
+           will  be  advertised  by  a default Area Border
+           Router into a stub area."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2, Area Parameters"
+      INDEX { ospfStubAreaId, ospfStubTOS }
+      ::= { ospfStubAreaTable 1 }
+
+OspfStubAreaEntry ::=
+    SEQUENCE {
+        ospfStubAreaId
+            AreaID,
+        ospfStubTOS
+            TOSType,
+        ospfStubMetric
+            BigMetric,
+        ospfStubStatus
+            RowStatus,
+        ospfStubMetricType
+            INTEGER
+              }
+
+    ospfStubAreaId OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The 32 bit identifier for the Stub  Area.   On
+           creation,  this  can  be  derived  from the in-
+           stance."
+       ::= { ospfStubAreaEntry 1 }
+
+
+    ospfStubTOS OBJECT-TYPE
+        SYNTAX   TOSType
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The  Type  of  Service  associated  with   the
+           metric.   On creation, this can be derived from
+           the instance."
+       ::= { ospfStubAreaEntry 2 }
+
+
+    ospfStubMetric OBJECT-TYPE
+        SYNTAX   BigMetric
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The metric value applied at the indicated type
+           of  service.  By default, this equals the least
+           metric at the type of service among the  inter-
+           faces to other areas."
+       ::= { ospfStubAreaEntry 3 }
+
+
+    ospfStubStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfStubAreaEntry 4 }
+
+    ospfStubMetricType OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    ospfMetric (1),                -- OSPF Metric
+                    comparableCost (2),        -- external type 1
+                    nonComparable  (3)        -- external type 2
+                  }
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the type of metric  ad-
+           vertised as a default route."
+       DEFVAL   { ospfMetric }
+       ::= { ospfStubAreaEntry 5 }
+
+--  OSPF Link State Database
+
+--      The Link State Database contains the Link State
+--      Advertisements from throughout the areas that the
+--      device is attached to.
+
+
+    ospfLsdbTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfLsdbEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The OSPF Process's Link State Database."
+       REFERENCE
+          "OSPF Version 2, Section 12  Link  State  Adver-
+          tisements"
+      ::= { ospf 4 }
+
+
+    ospfLsdbEntry OBJECT-TYPE
+        SYNTAX   OspfLsdbEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A single Link State Advertisement."
+       INDEX { ospfLsdbAreaId, ospfLsdbType,
+               ospfLsdbLsid, ospfLsdbRouterId }
+       ::= { ospfLsdbTable 1 }
+
+OspfLsdbEntry ::=
+    SEQUENCE {
+        ospfLsdbAreaId
+            AreaID,
+        ospfLsdbType
+            INTEGER,
+        ospfLsdbLsid
+            IpAddress,
+        ospfLsdbRouterId
+            RouterID,
+        ospfLsdbSequence
+            Integer32,
+        ospfLsdbAge
+            Integer32,
+        ospfLsdbChecksum
+            Integer32,
+        ospfLsdbAdvertisement
+            OCTET STRING
+              }
+    ospfLsdbAreaId OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The 32 bit identifier of the Area  from  which
+           the LSA was received."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfLsdbEntry 1 }
+
+-- External Link State Advertisements are permitted
+-- for backward compatibility, but should be displayed in
+-- the ospfExtLsdbTable rather than here.
+
+    ospfLsdbType OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    routerLink (1),
+                    networkLink (2),
+                    summaryLink (3),
+                    asSummaryLink (4),
+                    asExternalLink (5), -- but see ospfExtLsdbTable
+                    multicastLink (6),
+                    nssaExternalLink (7)
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The type  of  the  link  state  advertisement.
+           Each  link state type has a separate advertise-
+           ment format."
+       REFERENCE
+          "OSPF Version 2, Appendix A.4.1 The  Link  State
+          Advertisement header"
+      ::= { ospfLsdbEntry 2 }
+
+    ospfLsdbLsid OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Link State ID is an LS Type Specific field
+           containing either a Router ID or an IP Address;
+           it identifies the piece of the  routing  domain
+           that is being described by the advertisement."
+       REFERENCE
+          "OSPF Version 2, Section 12.1.4 Link State ID"
+      ::= { ospfLsdbEntry 3 }
+    ospfLsdbRouterId OBJECT-TYPE
+        SYNTAX   RouterID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The 32 bit number that uniquely identifies the
+           originating router in the Autonomous System."
+       REFERENCE
+          "OSPF Version 2, Appendix C.1 Global parameters"
+      ::= { ospfLsdbEntry 4 }
+
+--  Note that the OSPF Sequence Number is a 32 bit signed
+--  integer.  It starts with the value '80000001'h,
+--  or -'7FFFFFFF'h, and increments until '7FFFFFFF'h
+--  Thus, a typical sequence number will be very negative.
+
+    ospfLsdbSequence OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The sequence number field is a  signed  32-bit
+           integer.   It  is used to detect old and dupli-
+           cate link state advertisements.  The  space  of
+           sequence  numbers  is  linearly  ordered.   The
+           larger the sequence number the more recent  the
+           advertisement."
+       REFERENCE
+          "OSPF Version  2,  Section  12.1.6  LS  sequence
+          number"
+      ::= { ospfLsdbEntry 5 }
+
+
+    ospfLsdbAge OBJECT-TYPE
+        SYNTAX   Integer32    -- Should be 0..MaxAge
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "This field is the age of the link state adver-
+           tisement in seconds."
+       REFERENCE
+          "OSPF Version 2, Section 12.1.1 LS age"
+      ::= { ospfLsdbEntry 6 }
+
+    ospfLsdbChecksum OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "This field is the  checksum  of  the  complete
+           contents  of  the  advertisement, excepting the
+           age field.  The age field is excepted  so  that
+           an   advertisement's  age  can  be  incremented
+           without updating the  checksum.   The  checksum
+           used  is  the same that is used for ISO connec-
+           tionless datagrams; it is commonly referred  to
+           as the Fletcher checksum."
+       REFERENCE
+          "OSPF Version 2, Section 12.1.7 LS checksum"
+      ::= { ospfLsdbEntry 7 }
+
+
+    ospfLsdbAdvertisement OBJECT-TYPE
+        SYNTAX   OCTET STRING (SIZE (1..65535))
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The entire Link State Advertisement, including
+           its header."
+       REFERENCE
+          "OSPF Version 2, Section 12  Link  State  Adver-
+          tisements"
+      ::= { ospfLsdbEntry 8 }
+
+
+--  Address Range Table
+
+--      The Address Range Table acts as an adjunct to the Area
+--      Table; It describes those Address Range Summaries that
+--      are configured to be propagated from an Area to reduce
+--      the amount of information about it which is known beyond
+--      its borders.
+
+    ospfAreaRangeTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfAreaRangeEntry
+        MAX-ACCESS   not-accessible
+        STATUS   obsolete
+        DESCRIPTION
+           "A range if IP addresses  specified  by  an  IP
+           address/IP  network  mask  pair.   For example,
+           class B address range of X.X.X.X with a network
+           mask  of  255.255.0.0 includes all IP addresses
+           from X.X.0.0 to X.X.255.255"
+       REFERENCE
+          "OSPF Version 2, Appendix C.2  Area parameters"
+      ::= { ospf 5 }
+    ospfAreaRangeEntry OBJECT-TYPE
+        SYNTAX   OspfAreaRangeEntry
+        MAX-ACCESS   not-accessible
+        STATUS   obsolete
+        DESCRIPTION
+           "A range if IP addresses  specified  by  an  IP
+           address/IP  network  mask  pair.   For example,
+           class B address range of X.X.X.X with a network
+           mask  of  255.255.0.0 includes all IP addresses
+           from X.X.0.0 to X.X.255.255"
+       REFERENCE
+          "OSPF Version 2, Appendix C.2  Area parameters"
+      INDEX { ospfAreaRangeAreaId, ospfAreaRangeNet }
+      ::= { ospfAreaRangeTable 1 }
+
+OspfAreaRangeEntry ::=
+    SEQUENCE {
+        ospfAreaRangeAreaId
+            AreaID,
+        ospfAreaRangeNet
+            IpAddress,
+        ospfAreaRangeMask
+            IpAddress,
+        ospfAreaRangeStatus
+            RowStatus,
+        ospfAreaRangeEffect
+            INTEGER
+              }
+
+    ospfAreaRangeAreaId OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   obsolete
+        DESCRIPTION
+           "The Area the Address  Range  is  to  be  found
+           within."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfAreaRangeEntry 1 }
+
+
+    ospfAreaRangeNet OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   obsolete
+        DESCRIPTION
+           "The IP Address of the Net or Subnet  indicated
+           by the range."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfAreaRangeEntry 2 }
+
+
+    ospfAreaRangeMask OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-create
+        STATUS   obsolete
+        DESCRIPTION
+           "The Subnet Mask that pertains to  the  Net  or
+           Subnet."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfAreaRangeEntry 3 }
+
+    ospfAreaRangeStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   obsolete
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfAreaRangeEntry 4 }
+
+
+    ospfAreaRangeEffect OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    advertiseMatching (1),
+                    doNotAdvertiseMatching (2)
+                  }
+        MAX-ACCESS   read-create
+        STATUS   obsolete
+        DESCRIPTION
+           "Subnets subsumed by ranges either trigger  the
+           advertisement  of the indicated summary (adver-
+           tiseMatching), or result in  the  subnet's  not
+           being advertised at all outside the area."
+       DEFVAL   { advertiseMatching }
+       ::= { ospfAreaRangeEntry 5 }
+
+
+
+--  OSPF Host Table
+
+--      The Host/Metric Table indicates what hosts are directly
+--      attached to the Router, and what metrics and types of
+--      service should be advertised for them.
+
+    ospfHostTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfHostEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The list of Hosts, and their metrics, that the
+           router will advertise as host routes."
+       REFERENCE
+          "OSPF Version 2, Appendix C.6  Host route param-
+          eters"
+      ::= { ospf 6 }
+
+
+    ospfHostEntry OBJECT-TYPE
+        SYNTAX   OspfHostEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A metric to be advertised, for a given type of
+           service, when a given host is reachable."
+       INDEX { ospfHostIpAddress, ospfHostTOS }
+       ::= { ospfHostTable 1 }
+
+OspfHostEntry ::=
+    SEQUENCE {
+        ospfHostIpAddress
+            IpAddress,
+        ospfHostTOS
+            TOSType,
+        ospfHostMetric
+            Metric,
+        ospfHostStatus
+            RowStatus,
+        ospfHostAreaID
+            AreaID
+              }
+
+    ospfHostIpAddress OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP Address of the Host."
+       REFERENCE
+          "OSPF Version 2, Appendix C.6 Host route parame-
+          ters"
+      ::= { ospfHostEntry 1 }
+
+
+    ospfHostTOS OBJECT-TYPE
+        SYNTAX   TOSType
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Type of Service of the route being config-
+           ured."
+       REFERENCE
+          "OSPF Version 2, Appendix C.6 Host route parame-
+          ters"
+      ::= { ospfHostEntry 2 }
+
+
+    ospfHostMetric OBJECT-TYPE
+        SYNTAX   Metric
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The Metric to be advertised."
+       REFERENCE
+          "OSPF Version 2, Appendix C.6 Host route parame-
+          ters"
+      ::= { ospfHostEntry 3 }
+
+    ospfHostStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfHostEntry 4 }
+
+
+    ospfHostAreaID OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Area the Host Entry is to be found within.
+           By  default, the area that a subsuming OSPF in-
+           terface is in, or 0.0.0.0"
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfHostEntry 5 }
+
+
+--  OSPF Interface Table
+
+--      The OSPF Interface Table augments the ipAddrTable
+--             with OSPF specific information.
+
+    ospfIfTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfIfEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The OSPF Interface Table describes the  inter-
+           faces from the viewpoint of OSPF."
+       REFERENCE
+          "OSPF Version 2, Appendix C.3  Router  interface
+          parameters"
+      ::= { ospf 7 }
+
+
+    ospfIfEntry OBJECT-TYPE
+        SYNTAX   OspfIfEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The OSPF Interface Entry describes one  inter-
+           face from the viewpoint of OSPF."
+       INDEX { ospfIfIpAddress, ospfAddressLessIf }
+       ::= { ospfIfTable 1 }
+
+OspfIfEntry ::=
+    SEQUENCE {
+        ospfIfIpAddress
+            IpAddress,
+        ospfAddressLessIf
+            Integer32,
+        ospfIfAreaId
+            AreaID,
+        ospfIfType
+            INTEGER,
+        ospfIfAdminStat
+            Status,
+        ospfIfRtrPriority
+            DesignatedRouterPriority,
+        ospfIfTransitDelay
+            UpToMaxAge,
+        ospfIfRetransInterval
+            UpToMaxAge,
+        ospfIfHelloInterval
+            HelloRange,
+        ospfIfRtrDeadInterval
+            PositiveInteger,
+        ospfIfPollInterval
+            PositiveInteger,
+        ospfIfState
+            INTEGER,
+        ospfIfDesignatedRouter
+            IpAddress,
+        ospfIfBackupDesignatedRouter
+            IpAddress,
+        ospfIfEvents
+            Counter32,
+        ospfIfAuthType
+            INTEGER,
+        ospfIfAuthKey
+            OCTET STRING,
+        ospfIfStatus
+            RowStatus,
+        ospfIfMulticastForwarding
+            INTEGER,
+        ospfIfDemand
+            TruthValue
+              }
+
+    ospfIfIpAddress OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP address of this OSPF interface."
+       ::= { ospfIfEntry 1 }
+
+    ospfAddressLessIf OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "For the purpose of easing  the  instancing  of
+           addressed   and  addressless  interfaces;  This
+           variable takes the value 0 on  interfaces  with
+           IP  Addresses,  and  the corresponding value of
+           ifIndex for interfaces having no IP Address."
+       ::= { ospfIfEntry 2 }
+    ospfIfAreaId OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "A 32-bit integer uniquely identifying the area
+           to  which  the  interface  connects.   Area  ID
+           0.0.0.0 is used for the OSPF backbone."
+       DEFVAL   { '00000000'H }    -- 0.0.0.0
+       ::= { ospfIfEntry 3 }
+
+    ospfIfType OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    broadcast (1),
+                    nbma (2),
+                    pointToPoint (3),
+                    pointToMultipoint (5)
+                  }
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The OSPF interface type.
+
+           By way of a default, this field may be intuited
+           from the corresponding value of ifType.  Broad-
+           cast LANs, such as  Ethernet  and  IEEE  802.5,
+           take  the  value  'broadcast', X.25 and similar
+           technologies take the value 'nbma',  and  links
+           that  are  definitively point to point take the
+           value 'pointToPoint'."
+       ::= { ospfIfEntry 4 }
+
+
+    ospfIfAdminStat OBJECT-TYPE
+        SYNTAX   Status
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The OSPF  interface's  administrative  status.
+           The  value formed on the interface, and the in-
+           terface will be advertised as an internal route
+           to  some  area.   The  value 'disabled' denotes
+           that the interface is external to OSPF."
+       DEFVAL { enabled }
+       ::= { ospfIfEntry 5 }
+
+    ospfIfRtrPriority OBJECT-TYPE
+        SYNTAX   DesignatedRouterPriority
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The  priority  of  this  interface.   Used  in
+           multi-access  networks,  this  field is used in
+           the designated router election algorithm.   The
+           value 0 signifies that the router is not eligi-
+           ble to become the  designated  router  on  this
+           particular  network.   In the event of a tie in
+           this value, routers will use their Router ID as
+           a tie breaker."
+       DEFVAL { 1 }
+       ::= { ospfIfEntry 6 }
+
+
+    ospfIfTransitDelay OBJECT-TYPE
+        SYNTAX   UpToMaxAge
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The estimated number of seconds  it  takes  to
+           transmit  a  link state update packet over this
+           interface."
+       DEFVAL { 1 }
+       ::= { ospfIfEntry 7 }
+
+
+    ospfIfRetransInterval OBJECT-TYPE
+        SYNTAX   UpToMaxAge
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The number of seconds between  link-state  ad-
+           vertisement  retransmissions,  for  adjacencies
+           belonging to this  interface.   This  value  is
+           also used when retransmitting database descrip-
+           tion and link-state request packets."
+       DEFVAL { 5 }
+       ::= { ospfIfEntry 8 }
+
+
+    ospfIfHelloInterval OBJECT-TYPE
+        SYNTAX   HelloRange
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The length of time, in  seconds,  between  the
+           Hello  packets that the router sends on the in-
+           terface.  This value must be the same  for  all
+           routers attached to a common network."
+       DEFVAL { 10 }
+       ::= { ospfIfEntry 9 }
+
+
+    ospfIfRtrDeadInterval OBJECT-TYPE
+        SYNTAX   PositiveInteger
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The number of seconds that  a  router's  Hello
+           packets  have  not been seen before it's neigh-
+           bors declare the router down.  This  should  be
+           some  multiple  of  the  Hello  interval.  This
+           value must be the same for all routers attached
+           to a common network."
+       DEFVAL { 40 }
+       ::= { ospfIfEntry 10 }
+
+
+    ospfIfPollInterval OBJECT-TYPE
+        SYNTAX   PositiveInteger
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The larger time interval, in seconds,  between
+           the  Hello  packets  sent  to  an inactive non-
+           broadcast multi- access neighbor."
+       DEFVAL { 120 }
+       ::= { ospfIfEntry 11 }
+
+
+    ospfIfState OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    down (1),
+                    loopback (2),
+                    waiting (3),
+                    pointToPoint (4),
+                    designatedRouter (5),
+                    backupDesignatedRouter (6),
+                    otherDesignatedRouter (7)
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The OSPF Interface State."
+       DEFVAL { down }
+       ::= { ospfIfEntry 12 }
+
+
+    ospfIfDesignatedRouter OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP Address of the Designated Router."
+       DEFVAL   { '00000000'H }    -- 0.0.0.0
+       ::= { ospfIfEntry 13 }
+
+
+    ospfIfBackupDesignatedRouter OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The  IP  Address  of  the  Backup   Designated
+           Router."
+       DEFVAL   { '00000000'H }    -- 0.0.0.0
+       ::= { ospfIfEntry 14 }
+
+    ospfIfEvents OBJECT-TYPE
+        SYNTAX   Counter32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of times this  OSPF  interface  has
+           changed its state, or an error has occurred."
+       ::= { ospfIfEntry 15 }
+
+
+    ospfIfAuthKey OBJECT-TYPE
+        SYNTAX   OCTET STRING (SIZE (0..256))
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The Authentication Key.  If the Area's Author-
+           ization  Type  is  simplePassword,  and the key
+           length is shorter than 8 octets, the agent will
+           left adjust and zero fill to 8 octets.
+
+           Note that unauthenticated  interfaces  need  no
+           authentication key, and simple password authen-
+           tication cannot use a key of more  than  8  oc-
+           tets.  Larger keys are useful only with authen-
+           tication mechanisms not specified in this docu-
+           ment.
+
+           When read, ospfIfAuthKey always returns an  Oc-
+           tet String of length zero."
+       REFERENCE
+          "OSPF Version 2, Section 9  The  Interface  Data
+          Structure"
+      DEFVAL   { '0000000000000000'H }    -- 0.0.0.0.0.0.0.0
+      ::= { ospfIfEntry 16 }
+
+    ospfIfStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfIfEntry 17 }
+
+
+    ospfIfMulticastForwarding OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                            blocked (1),        -- no multicast forwarding
+                            multicast (2),        -- using multicast address
+                            unicast (3)        -- to each OSPF neighbor
+                  }
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The way multicasts should  forwarded  on  this
+           interface;  not  forwarded,  forwarded  as data
+           link multicasts, or forwarded as data link uni-
+           casts.   Data link multicasting is not meaning-
+           ful on point to point and NBMA interfaces,  and
+           setting ospfMulticastForwarding to 0 effective-
+           ly disables all multicast forwarding."
+       DEFVAL { blocked }
+       ::= { ospfIfEntry 18 }
+
+
+    ospfIfDemand OBJECT-TYPE
+        SYNTAX   TruthValue
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "Indicates whether Demand OSPF procedures (hel-
+           lo supression to FULL neighbors and setting the
+           DoNotAge flag on proogated LSAs) should be per-
+           formed on this interface."
+       DEFVAL { false }
+       ::= { ospfIfEntry 19 }
+
+
+    ospfIfAuthType OBJECT-TYPE
+        SYNTAX   INTEGER (0..255)
+                    -- none (0),
+                    -- simplePassword (1)
+                    -- md5 (2)
+                    -- reserved for specification by IANA (> 2)
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The authentication type specified for  an  in-
+           terface.   Additional  authentication types may
+           be assigned locally."
+       REFERENCE
+          "OSPF Version 2, Appendix E Authentication"
+      DEFVAL { 0 }        -- no authentication, by default
+      ::= { ospfIfEntry 20 }
+
+
+--  OSPF Interface Metric Table
+
+--      The Metric Table describes the metrics to be advertised
+--      for a specified interface at the various types of service.
+--      As such, this table is an adjunct of the OSPF Interface
+--      Table.
+
+-- Types of service, as defined by RFC 791, have the ability
+-- to request low delay, high bandwidth, or reliable linkage.
+
+-- For the purposes of this specification, the measure of
+-- bandwidth
+
+--      Metric = 10^8 / ifSpeed
+
+-- is the default value.  For multiple link interfaces, note
+-- that ifSpeed is the sum of the individual link speeds.
+-- This yields a number having the following typical values:
+
+--      Network Type/bit rate   Metric
+
+--      >= 100 MBPS                 1
+--      Ethernet/802.3             10
+--      E1                         48
+--      T1 (ESF)                   65
+--       64 KBPS                 1562
+--       56 KBPS                 1785
+--       19.2 KBPS               5208
+--        9.6 KBPS              10416
+
+-- Routes that are not specified use the default (TOS 0) metric
+
+    ospfIfMetricTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfIfMetricEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The TOS metrics for  a  non-virtual  interface
+           identified by the interface index."
+       REFERENCE
+          "OSPF Version 2, Appendix C.3  Router  interface
+          parameters"
+      ::= { ospf 8 }
+
+    ospfIfMetricEntry OBJECT-TYPE
+        SYNTAX   OspfIfMetricEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A particular TOS metric for a non-virtual  in-
+           terface identified by the interface index."
+       REFERENCE
+          "OSPF Version 2, Appendix C.3  Router  interface
+          parameters"
+      INDEX { ospfIfMetricIpAddress,
+  ospfIfMetricAddressLessIf,
+  ospfIfMetricTOS }
+      ::= { ospfIfMetricTable 1 }
+
+OspfIfMetricEntry ::=
+    SEQUENCE {
+        ospfIfMetricIpAddress
+            IpAddress,
+        ospfIfMetricAddressLessIf
+            Integer32,
+        ospfIfMetricTOS
+            TOSType,
+        ospfIfMetricValue
+            Metric,
+        ospfIfMetricStatus
+            RowStatus
+              }
+
+    ospfIfMetricIpAddress OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP address of this OSPF interface.  On row
+           creation,  this  can  be  derived  from the in-
+           stance."
+       ::= { ospfIfMetricEntry 1 }
+
+    ospfIfMetricAddressLessIf OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "For the purpose of easing  the  instancing  of
+           addressed   and  addressless  interfaces;  This
+           variable takes the value 0 on  interfaces  with
+           IP  Addresses, and the value of ifIndex for in-
+           terfaces having no IP Address.   On  row  crea-
+           tion, this can be derived from the instance."
+       ::= { ospfIfMetricEntry 2 }
+
+
+    ospfIfMetricTOS OBJECT-TYPE
+        SYNTAX   TOSType
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The type of service metric  being  referenced.
+           On  row  creation, this can be derived from the
+           instance."
+       ::= { ospfIfMetricEntry 3 }
+
+
+    ospfIfMetricValue OBJECT-TYPE
+        SYNTAX   Metric
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The metric of using this type  of  service  on
+           this interface.  The default value of the TOS 0
+           Metric is 10^8 / ifSpeed."
+       ::= { ospfIfMetricEntry 4 }
+
+    ospfIfMetricStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfIfMetricEntry 5 }
+
+
+--  OSPF Virtual Interface Table
+
+--      The Virtual Interface Table describes the virtual
+--      links that the OSPF Process is configured to
+--      carry on.
+
+    ospfVirtIfTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfVirtIfEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "Information about this router's virtual inter-
+           faces."
+       REFERENCE
+          "OSPF Version  2,  Appendix  C.4   Virtual  link
+          parameters"
+      ::= { ospf 9 }
+
+
+    ospfVirtIfEntry OBJECT-TYPE
+        SYNTAX   OspfVirtIfEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "Information about a single Virtual Interface."
+       INDEX { ospfVirtIfAreaId, ospfVirtIfNeighbor }
+       ::= { ospfVirtIfTable 1 }
+
+OspfVirtIfEntry ::=
+    SEQUENCE {
+        ospfVirtIfAreaId
+            AreaID,
+        ospfVirtIfNeighbor
+            RouterID,
+        ospfVirtIfTransitDelay
+            UpToMaxAge,
+        ospfVirtIfRetransInterval
+            UpToMaxAge,
+        ospfVirtIfHelloInterval
+            HelloRange,
+        ospfVirtIfRtrDeadInterval
+            PositiveInteger,
+        ospfVirtIfState
+            INTEGER,
+        ospfVirtIfEvents
+            Counter32,
+        ospfVirtIfAuthType
+            INTEGER,
+        ospfVirtIfAuthKey
+            OCTET STRING,
+        ospfVirtIfStatus
+            RowStatus
+              }
+
+    ospfVirtIfAreaId OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The  Transit  Area  that  the   Virtual   Link
+           traverses.  By definition, this is not 0.0.0.0"
+       ::= { ospfVirtIfEntry 1 }
+
+
+    ospfVirtIfNeighbor OBJECT-TYPE
+        SYNTAX   RouterID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Router ID of the Virtual Neighbor."
+       ::= { ospfVirtIfEntry 2 }
+
+
+    ospfVirtIfTransitDelay OBJECT-TYPE
+        SYNTAX   UpToMaxAge
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The estimated number of seconds  it  takes  to
+           transmit  a link- state update packet over this
+           interface."
+       DEFVAL { 1 }
+       ::= { ospfVirtIfEntry 3 }
+
+
+    ospfVirtIfRetransInterval OBJECT-TYPE
+        SYNTAX   UpToMaxAge
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The number of seconds between  link-state  ad-
+           vertisement  retransmissions,  for  adjacencies
+           belonging to this  interface.   This  value  is
+           also used when retransmitting database descrip-
+           tion  and  link-state  request  packets.   This
+           value  should  be well over the expected round-
+           trip time."
+       DEFVAL { 5 }
+       ::= { ospfVirtIfEntry 4 }
+
+
+    ospfVirtIfHelloInterval OBJECT-TYPE
+        SYNTAX   HelloRange
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The length of time, in  seconds,  between  the
+           Hello  packets that the router sends on the in-
+           terface.  This value must be the same  for  the
+           virtual neighbor."
+       DEFVAL { 10 }
+       ::= { ospfVirtIfEntry 5 }
+
+
+    ospfVirtIfRtrDeadInterval OBJECT-TYPE
+        SYNTAX   PositiveInteger
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The number of seconds that  a  router's  Hello
+           packets  have  not been seen before it's neigh-
+           bors declare the router down.  This  should  be
+           some  multiple  of  the  Hello  interval.  This
+           value must be the same for the  virtual  neigh-
+           bor."
+       DEFVAL { 60 }
+       ::= { ospfVirtIfEntry 6 }
+
+
+    ospfVirtIfState OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    down (1),            -- these use the same encoding
+                    pointToPoint (4)     -- as the ospfIfTable
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "OSPF virtual interface states."
+       DEFVAL   { down }
+       ::= { ospfVirtIfEntry 7 }
+
+
+    ospfVirtIfEvents OBJECT-TYPE
+        SYNTAX   Counter32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of state changes or error events on
+           this Virtual Link"
+       ::= { ospfVirtIfEntry 8 }
+
+
+    ospfVirtIfAuthKey OBJECT-TYPE
+        SYNTAX   OCTET STRING (SIZE(0..256))
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "If Authentication Type is simplePassword,  the
+           device  will left adjust and zero fill to 8 oc-
+           tets.
+
+           Note that unauthenticated  interfaces  need  no
+           authentication key, and simple password authen-
+           tication cannot use a key of more  than  8  oc-
+           tets.  Larger keys are useful only with authen-
+           tication mechanisms not specified in this docu-
+           ment.
+
+           When  read,  ospfVifAuthKey  always  returns  a
+           string of length zero."
+       REFERENCE
+          "OSPF Version 2, Section 9  The  Interface  Data
+          Structure"
+      DEFVAL   { '0000000000000000'H }    -- 0.0.0.0.0.0.0.0
+      ::= { ospfVirtIfEntry 9 }
+
+
+    ospfVirtIfStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfVirtIfEntry 10 }
+
+
+    ospfVirtIfAuthType OBJECT-TYPE
+        SYNTAX   INTEGER (0..255)
+                    -- none (0),
+                    -- simplePassword (1)
+                    -- md5 (2)
+                    -- reserved for specification by IANA (> 2)
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The authentication type specified for a virtu-
+           al  interface.  Additional authentication types
+           may be assigned locally."
+       REFERENCE
+          "OSPF Version 2, Appendix E Authentication"
+      DEFVAL { 0 }        -- no authentication, by default
+      ::= { ospfVirtIfEntry 11 }
+
+
+--  OSPF Neighbor Table
+
+--      The OSPF Neighbor Table describes all neighbors in
+--      the locality of the subject router.
+
+    ospfNbrTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfNbrEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A table of non-virtual neighbor information."
+       REFERENCE
+          "OSPF Version 2, Section 10  The  Neighbor  Data
+          Structure"
+      ::= { ospf 10 }
+
+
+    ospfNbrEntry OBJECT-TYPE
+        SYNTAX   OspfNbrEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The information regarding a single neighbor."
+       REFERENCE
+          "OSPF Version 2, Section 10  The  Neighbor  Data
+          Structure"
+      INDEX { ospfNbrIpAddr, ospfNbrAddressLessIndex }
+      ::= { ospfNbrTable 1 }
+
+OspfNbrEntry ::=
+    SEQUENCE {
+        ospfNbrIpAddr
+            IpAddress,
+        ospfNbrAddressLessIndex
+            InterfaceIndex,
+        ospfNbrRtrId
+            RouterID,
+        ospfNbrOptions
+            Integer32,
+        ospfNbrPriority
+            DesignatedRouterPriority,
+        ospfNbrState
+            INTEGER,
+        ospfNbrEvents
+            Counter32,
+        ospfNbrLsRetransQLen
+            Gauge32,
+        ospfNbmaNbrStatus
+            RowStatus,
+        ospfNbmaNbrPermanence
+            INTEGER,
+        ospfNbrHelloSuppressed
+            TruthValue
+              }
+
+    ospfNbrIpAddr OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP address this neighbor is using  in  its
+           IP  Source  Address.  Note that, on addressless
+           links, this will not be 0.0.0.0,  but  the  ad-
+           dress of another of the neighbor's interfaces."
+       ::= { ospfNbrEntry 1 }
+
+
+    ospfNbrAddressLessIndex OBJECT-TYPE
+        SYNTAX   InterfaceIndex
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "On an interface having an  IP  Address,  zero.
+           On  addressless  interfaces,  the corresponding
+           value of ifIndex in the Internet Standard  MIB.
+           On  row  creation, this can be derived from the
+           instance."
+       ::= { ospfNbrEntry 2 }
+
+
+    ospfNbrRtrId OBJECT-TYPE
+        SYNTAX   RouterID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "A 32-bit integer (represented as a type  IpAd-
+           dress)  uniquely  identifying  the  neighboring
+           router in the Autonomous System."
+       DEFVAL   { '00000000'H }    -- 0.0.0.0
+       ::= { ospfNbrEntry 3 }
+
+
+    ospfNbrOptions OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "A Bit Mask corresponding to the neighbor's op-
+           tions field.
+
+           Bit 0, if set, indicates that the  system  will
+           operate  on  Type of Service metrics other than
+           TOS 0.  If zero, the neighbor will  ignore  all
+           metrics except the TOS 0 metric.
+
+           Bit 1, if set, indicates  that  the  associated
+           area  accepts and operates on external informa-
+           tion; if zero, it is a stub area.
+
+           Bit 2, if set, indicates that the system is ca-
+           pable  of routing IP Multicast datagrams; i.e.,
+           that it implements the Multicast Extensions  to
+           OSPF.
+
+           Bit 3, if set, indicates  that  the  associated
+           area  is  an  NSSA.  These areas are capable of
+           carrying type 7 external advertisements,  which
+           are  translated into type 5 external advertise-
+           ments at NSSA borders."
+       REFERENCE
+          "OSPF Version 2, Section 12.1.2 Options"
+      DEFVAL { 0 }
+      ::= { ospfNbrEntry 4 }
+
+
+    ospfNbrPriority OBJECT-TYPE
+        SYNTAX   DesignatedRouterPriority
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "The priority of this neighbor in the designat-
+           ed router election algorithm.  The value 0 sig-
+           nifies that the neighbor is not eligible to be-
+           come  the  designated router on this particular
+           network."
+       DEFVAL { 1 }
+       ::= { ospfNbrEntry 5 }
+
+
+    ospfNbrState OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    down (1),
+                    attempt (2),
+                    init (3),
+                    twoWay (4),
+                    exchangeStart (5),
+                    exchange (6),
+                    loading (7),
+                    full (8)
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The State of the relationship with this Neigh-
+           bor."
+       REFERENCE
+          "OSPF Version 2, Section 10.1 Neighbor States"
+      DEFVAL   { down }
+      ::= { ospfNbrEntry 6 }
+
+
+    ospfNbrEvents OBJECT-TYPE
+        SYNTAX   Counter32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of times this neighbor relationship
+           has changed state, or an error has occurred."
+       ::= { ospfNbrEntry 7 }
+
+
+    ospfNbrLsRetransQLen OBJECT-TYPE
+        SYNTAX   Gauge32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The  current  length  of  the   retransmission
+           queue."
+       ::= { ospfNbrEntry 8 }
+
+
+    ospfNbmaNbrStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfNbrEntry 9 }
+
+
+    ospfNbmaNbrPermanence OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    dynamic (1),        -- learned through protocol
+                    permanent (2)       -- configured address
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.   'dynamic'  and  'permanent' refer to how
+           the neighbor became known."
+       DEFVAL { permanent }
+       ::= { ospfNbrEntry 10 }
+
+
+    ospfNbrHelloSuppressed OBJECT-TYPE
+        SYNTAX   TruthValue
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "Indicates whether Hellos are being  suppressed
+           to the neighbor"
+       ::= { ospfNbrEntry 11 }
+
+
+--  OSPF Virtual Neighbor Table
+
+--      This table describes all virtual neighbors.
+--      Since Virtual Links are configured in the
+--      virtual interface table, this table is read-only.
+
+    ospfVirtNbrTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfVirtNbrEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A table of virtual neighbor information."
+       REFERENCE
+          "OSPF Version 2, Section 15  Virtual Links"
+      ::= { ospf 11 }
+
+
+    ospfVirtNbrEntry OBJECT-TYPE
+        SYNTAX   OspfVirtNbrEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "Virtual neighbor information."
+       INDEX { ospfVirtNbrArea, ospfVirtNbrRtrId }
+       ::= { ospfVirtNbrTable 1 }
+
+OspfVirtNbrEntry ::=
+    SEQUENCE {
+        ospfVirtNbrArea
+            AreaID,
+        ospfVirtNbrRtrId
+            RouterID,
+        ospfVirtNbrIpAddr
+            IpAddress,
+        ospfVirtNbrOptions
+            Integer32,
+        ospfVirtNbrState
+            INTEGER,
+        ospfVirtNbrEvents
+            Counter32,
+        ospfVirtNbrLsRetransQLen
+            Gauge32,
+        ospfVirtNbrHelloSuppressed
+                TruthValue
+              }
+
+    ospfVirtNbrArea OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Transit Area Identifier."
+       ::= { ospfVirtNbrEntry 1 }
+
+
+    ospfVirtNbrRtrId OBJECT-TYPE
+        SYNTAX   RouterID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "A  32-bit  integer  uniquely  identifying  the
+           neighboring router in the Autonomous System."
+       ::= { ospfVirtNbrEntry 2 }
+
+
+    ospfVirtNbrIpAddr OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP address this Virtual  Neighbor  is  us-
+           ing."
+       ::= { ospfVirtNbrEntry 3 }
+
+
+    ospfVirtNbrOptions OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "A Bit Mask corresponding to the neighbor's op-
+           tions field.
+
+           Bit 1, if set, indicates that the  system  will
+           operate  on  Type of Service metrics other than
+           TOS 0.  If zero, the neighbor will  ignore  all
+           metrics except the TOS 0 metric.
+
+           Bit 2, if set, indicates  that  the  system  is
+           Network  Multicast  capable; ie, that it imple-
+           ments OSPF Multicast Routing."
+       ::= { ospfVirtNbrEntry 4 }
+    ospfVirtNbrState OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    down (1),
+                    attempt (2),
+                    init (3),
+                    twoWay (4),
+                    exchangeStart (5),
+                    exchange (6),
+                    loading (7),
+                    full (8)
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The state of the  Virtual  Neighbor  Relation-
+           ship."
+       ::= { ospfVirtNbrEntry 5 }
+
+
+    ospfVirtNbrEvents OBJECT-TYPE
+        SYNTAX   Counter32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The number of  times  this  virtual  link  has
+           changed its state, or an error has occurred."
+       ::= { ospfVirtNbrEntry 6 }
+
+
+    ospfVirtNbrLsRetransQLen OBJECT-TYPE
+        SYNTAX   Gauge32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The  current  length  of  the   retransmission
+           queue."
+       ::= { ospfVirtNbrEntry 7 }
+
+
+    ospfVirtNbrHelloSuppressed OBJECT-TYPE
+        SYNTAX   TruthValue
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "Indicates whether Hellos are being  suppressed
+           to the neighbor"
+       ::= { ospfVirtNbrEntry 8 }
+
+--  OSPF Link State Database, External
+
+--      The Link State Database contains the Link State
+--      Advertisements from throughout the areas that the
+--      device is attached to.
+
+--             This table is identical to the OSPF LSDB Table in
+--      format, but contains only External Link State
+--             Advertisements.  The purpose is to allow external
+--      LSAs to be displayed once for the router rather
+--      than once in each non-stub area.
+
+    ospfExtLsdbTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfExtLsdbEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "The OSPF Process's Links State Database."
+       REFERENCE
+          "OSPF Version 2, Section 12  Link  State  Adver-
+          tisements"
+      ::= { ospf 12 }
+
+
+    ospfExtLsdbEntry OBJECT-TYPE
+        SYNTAX   OspfExtLsdbEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A single Link State Advertisement."
+       INDEX { ospfExtLsdbType, ospfExtLsdbLsid, ospfExtLsdbRouterId }
+       ::= { ospfExtLsdbTable 1 }
+
+OspfExtLsdbEntry ::=
+    SEQUENCE {
+        ospfExtLsdbType
+            INTEGER,
+        ospfExtLsdbLsid
+            IpAddress,
+        ospfExtLsdbRouterId
+            RouterID,
+        ospfExtLsdbSequence
+            Integer32,
+        ospfExtLsdbAge
+            Integer32,
+        ospfExtLsdbChecksum
+            Integer32,
+        ospfExtLsdbAdvertisement
+            OCTET STRING
+              }
+
+    ospfExtLsdbType OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    asExternalLink (5)
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The type  of  the  link  state  advertisement.
+           Each  link state type has a separate advertise-
+           ment format."
+       REFERENCE
+          "OSPF Version 2, Appendix A.4.1 The  Link  State
+          Advertisement header"
+      ::= { ospfExtLsdbEntry 1 }
+
+
+    ospfExtLsdbLsid OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Link State ID is an LS Type Specific field
+           containing either a Router ID or an IP Address;
+           it identifies the piece of the  routing  domain
+           that is being described by the advertisement."
+       REFERENCE
+          "OSPF Version 2, Section 12.1.4 Link State ID"
+      ::= { ospfExtLsdbEntry 2 }
+
+
+    ospfExtLsdbRouterId OBJECT-TYPE
+        SYNTAX   RouterID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The 32 bit number that uniquely identifies the
+           originating router in the Autonomous System."
+       REFERENCE
+          "OSPF Version 2, Appendix C.1 Global parameters"
+      ::= { ospfExtLsdbEntry 3 }
+
+--  Note that the OSPF Sequence Number is a 32 bit signed
+--  integer.  It starts with the value '80000001'h,
+--  or -'7FFFFFFF'h, and increments until '7FFFFFFF'h
+--  Thus, a typical sequence number will be very negative.
+    ospfExtLsdbSequence OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The sequence number field is a  signed  32-bit
+           integer.   It  is used to detect old and dupli-
+           cate link state advertisements.  The  space  of
+           sequence  numbers  is  linearly  ordered.   The
+           larger the sequence number the more recent  the
+           advertisement."
+       REFERENCE
+          "OSPF Version  2,  Section  12.1.6  LS  sequence
+          number"
+      ::= { ospfExtLsdbEntry 4 }
+
+
+    ospfExtLsdbAge OBJECT-TYPE
+        SYNTAX   Integer32    -- Should be 0..MaxAge
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "This field is the age of the link state adver-
+           tisement in seconds."
+       REFERENCE
+          "OSPF Version 2, Section 12.1.1 LS age"
+      ::= { ospfExtLsdbEntry 5 }
+
+
+    ospfExtLsdbChecksum OBJECT-TYPE
+        SYNTAX   Integer32
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "This field is the  checksum  of  the  complete
+           contents  of  the  advertisement, excepting the
+           age field.  The age field is excepted  so  that
+           an   advertisement's  age  can  be  incremented
+           without updating the  checksum.   The  checksum
+           used  is  the same that is used for ISO connec-
+           tionless datagrams; it is commonly referred  to
+           as the Fletcher checksum."
+       REFERENCE
+          "OSPF Version 2, Section 12.1.7 LS checksum"
+      ::= { ospfExtLsdbEntry 6 }
+
+
+    ospfExtLsdbAdvertisement OBJECT-TYPE
+        SYNTAX   OCTET STRING (SIZE(36))
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The entire Link State Advertisement, including
+           its header."
+       REFERENCE
+          "OSPF Version 2, Section 12  Link  State  Adver-
+          tisements"
+      ::= { ospfExtLsdbEntry 7 }
+
+
+--  OSPF Use of the CIDR Route Table
+
+ospfRouteGroup           OBJECT IDENTIFIER ::= { ospf 13 }
+
+-- The IP Forwarding Table defines a number of objects for use by
+-- the routing protocol to externalize its information.  Most of
+-- the variables (ipForwardDest, ipForwardMask, ipForwardPolicy,
+-- ipForwardNextHop, ipForwardIfIndex, ipForwardType,
+-- ipForwardProto, ipForwardAge, and ipForwardNextHopAS) are
+-- defined there.
+
+-- Those that leave some discretion are defined here.
+
+-- ipCidrRouteProto is, of course, ospf (13).
+
+-- ipCidrRouteAge is the time since the route was first calculated,
+-- as opposed to the time since the last SPF run.
+
+-- ipCidrRouteInfo is an OBJECT IDENTIFIER for use by the routing
+-- protocol.  The following values shall be found there depending
+-- on the way the route was calculated.
+
+ospfIntraArea      OBJECT IDENTIFIER ::= { ospfRouteGroup 1 }
+ospfInterArea      OBJECT IDENTIFIER ::= { ospfRouteGroup 2 }
+ospfExternalType1  OBJECT IDENTIFIER ::= { ospfRouteGroup 3 }
+ospfExternalType2  OBJECT IDENTIFIER ::= { ospfRouteGroup 4 }
+
+-- ipCidrRouteMetric1 is, by definition, the primary routing
+-- metric.  Therefore, it should be the metric that route
+-- selection is based on.  For intra-area and inter-area routes,
+-- it is an OSPF metric.  For External Type 1 (comparable value)
+-- routes, it is an OSPF metric plus the External Metric.  For
+-- external Type 2 (non-comparable value) routes, it is the
+-- external metric.
+
+-- ipCidrRouteMetric2 is, by definition, a secondary routing
+-- metric.  Therefore, it should be the metric that breaks a tie
+-- among routes having equal metric1 values and the same
+-- calculation rule.  For intra-area, inter-area routes, and
+-- External Type 1 (comparable value) routes, it is unused.  For
+-- external Type 2 (non-comparable value) routes, it is the metric
+-- to the AS border router.
+
+-- ipCidrRouteMetric3, ipCidrRouteMetric4, and ipCidrRouteMetric5 are
+-- unused.
+
+--
+--      The OSPF Area Aggregate Table
+--
+--      This table replaces the OSPF Area Summary Table, being an
+--      extension of that for CIDR routers.
+
+    ospfAreaAggregateTable OBJECT-TYPE
+        SYNTAX   SEQUENCE OF OspfAreaAggregateEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A range of IP addresses  specified  by  an  IP
+           address/IP  network  mask  pair.   For example,
+           class B address range of X.X.X.X with a network
+           mask  of  255.255.0.0 includes all IP addresses
+           from X.X.0.0  to  X.X.255.255.   Note  that  if
+           ranges  are configured such that one range sub-
+           sumes  another  range  (e.g.,   10.0.0.0   mask
+           255.0.0.0  and  10.1.0.0 mask 255.255.0.0), the
+           most specific match is the preferred one."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2  Area parameters"
+      ::= { ospf 14 }
+
+
+    ospfAreaAggregateEntry OBJECT-TYPE
+        SYNTAX   OspfAreaAggregateEntry
+        MAX-ACCESS   not-accessible
+        STATUS   current
+        DESCRIPTION
+           "A range of IP addresses  specified  by  an  IP
+           address/IP  network  mask  pair.   For example,
+           class B address range of X.X.X.X with a network
+           mask  of  255.255.0.0 includes all IP addresses
+           from X.X.0.0  to  X.X.255.255.   Note  that  if
+           ranges are range configured such that one range
+           subsumes another  range  (e.g.,  10.0.0.0  mask
+           255.0.0.0  and  10.1.0.0 mask 255.255.0.0), the
+           most specific match is the preferred one."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2  Area parameters"
+      INDEX { ospfAreaAggregateAreaID, ospfAreaAggregateLsdbType,
+              ospfAreaAggregateNet, ospfAreaAggregateMask }
+      ::= { ospfAreaAggregateTable 1 }
+
+
+OspfAreaAggregateEntry ::=
+    SEQUENCE {
+        ospfAreaAggregateAreaID
+            AreaID,
+        ospfAreaAggregateLsdbType
+            INTEGER,
+        ospfAreaAggregateNet
+            IpAddress,
+        ospfAreaAggregateMask
+            IpAddress,
+        ospfAreaAggregateStatus
+            RowStatus,
+        ospfAreaAggregateEffect
+            INTEGER
+              }
+
+    ospfAreaAggregateAreaID OBJECT-TYPE
+        SYNTAX   AreaID
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Area the Address Aggregate is to be  found
+           within."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfAreaAggregateEntry 1 }
+
+
+    ospfAreaAggregateLsdbType OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    summaryLink (3),
+                    nssaExternalLink (7)
+                  }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The type of the Address Aggregate.  This field
+           specifies  the  Lsdb type that this Address Ag-
+           gregate applies to."
+       REFERENCE
+          "OSPF Version 2, Appendix A.4.1 The  Link  State
+          Advertisement header"
+      ::= { ospfAreaAggregateEntry 2 }
+
+
+    ospfAreaAggregateNet OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP Address of the Net or Subnet  indicated
+           by the range."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfAreaAggregateEntry 3 }
+
+
+    ospfAreaAggregateMask OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The Subnet Mask that pertains to  the  Net  or
+           Subnet."
+       REFERENCE
+          "OSPF Version 2, Appendix C.2 Area parameters"
+      ::= { ospfAreaAggregateEntry 4 }
+
+
+    ospfAreaAggregateStatus OBJECT-TYPE
+        SYNTAX   RowStatus
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "This variable displays the status of  the  en-
+           try.  Setting it to 'invalid' has the effect of
+           rendering it inoperative.  The internal  effect
+           (row removal) is implementation dependent."
+       ::= { ospfAreaAggregateEntry 5 }
+
+
+    ospfAreaAggregateEffect OBJECT-TYPE
+        SYNTAX   INTEGER    {
+                    advertiseMatching (1),
+                    doNotAdvertiseMatching (2)
+                  }
+        MAX-ACCESS   read-create
+        STATUS   current
+        DESCRIPTION
+           "Subnets subsumed by ranges either trigger  the
+           advertisement  of  the indicated aggregate (ad-
+           vertiseMatching), or result in the subnet's not
+           being advertised at all outside the area."
+       DEFVAL   { advertiseMatching }
+       ::= { ospfAreaAggregateEntry 6 }
+
+
+-- conformance information
+
+ospfConformance OBJECT IDENTIFIER ::= { ospf 15 }
+
+ospfGroups      OBJECT IDENTIFIER ::= { ospfConformance 1 }
+ospfCompliances OBJECT IDENTIFIER ::= { ospfConformance 2 }
+
+-- compliance statements
+
+    ospfCompliance MODULE-COMPLIANCE
+        STATUS  current
+        DESCRIPTION
+           "The compliance statement "
+       MODULE  -- this module
+       MANDATORY-GROUPS {
+                    ospfBasicGroup,
+                    ospfAreaGroup,
+                    ospfStubAreaGroup,
+                    ospfIfGroup,
+                    ospfIfMetricGroup,
+                    ospfVirtIfGroup,
+                    ospfNbrGroup,
+                    ospfVirtNbrGroup,
+                    ospfAreaAggregateGroup
+           }
+       ::= { ospfCompliances 1 }
+
+
+-- units of conformance
+
+    ospfBasicGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfRouterId,
+                    ospfAdminStat,
+                    ospfVersionNumber,
+                    ospfAreaBdrRtrStatus,
+                    ospfASBdrRtrStatus,
+                    ospfExternLsaCount,
+                    ospfExternLsaCksumSum,
+                    ospfTOSSupport,
+                    ospfOriginateNewLsas,
+                    ospfRxNewLsas,
+                    ospfExtLsdbLimit,
+                    ospfMulticastExtensions,
+                    ospfExitOverflowInterval,
+                    ospfDemandExtensions
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required for OSPF systems."
+       ::= { ospfGroups 1 }
+
+
+    ospfAreaGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfAreaId,
+                    ospfImportAsExtern,
+                    ospfSpfRuns,
+                    ospfAreaBdrRtrCount,
+                    ospfAsBdrRtrCount,
+                    ospfAreaLsaCount,
+                    ospfAreaLsaCksumSum,
+                    ospfAreaSummary,
+                    ospfAreaStatus
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required  for  OSPF  systems
+           supporting areas."
+       ::= { ospfGroups 2 }
+
+
+    ospfStubAreaGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfStubAreaId,
+                    ospfStubTOS,
+                    ospfStubMetric,
+                    ospfStubStatus,
+                    ospfStubMetricType
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required  for  OSPF  systems
+           supporting stub areas."
+       ::= { ospfGroups 3 }
+
+
+    ospfLsdbGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfLsdbAreaId,
+                    ospfLsdbType,
+                    ospfLsdbLsid,
+                    ospfLsdbRouterId,
+                    ospfLsdbSequence,
+                    ospfLsdbAge,
+                    ospfLsdbChecksum,
+                    ospfLsdbAdvertisement
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required  for  OSPF  systems
+           that display their link state database."
+       ::= { ospfGroups 4 }
+
+
+    ospfAreaRangeGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfAreaRangeAreaId,
+                    ospfAreaRangeNet,
+                    ospfAreaRangeMask,
+                    ospfAreaRangeStatus,
+                    ospfAreaRangeEffect
+        }
+        STATUS  obsolete
+        DESCRIPTION
+           "These objects are required for  non-CIDR  OSPF
+           systems that support multiple areas."
+       ::= { ospfGroups 5 }
+
+
+    ospfHostGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfHostIpAddress,
+                    ospfHostTOS,
+                    ospfHostMetric,
+                    ospfHostStatus,
+                    ospfHostAreaID
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required  for  OSPF  systems
+           that support attached hosts."
+       ::= { ospfGroups 6 }
+
+
+    ospfIfGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfIfIpAddress,
+                    ospfAddressLessIf,
+                    ospfIfAreaId,
+                    ospfIfType,
+                    ospfIfAdminStat,
+                    ospfIfRtrPriority,
+                    ospfIfTransitDelay,
+                    ospfIfRetransInterval,
+                    ospfIfHelloInterval,
+                    ospfIfRtrDeadInterval,
+                    ospfIfPollInterval,
+                    ospfIfState,
+                    ospfIfDesignatedRouter,
+                    ospfIfBackupDesignatedRouter,
+                    ospfIfEvents,
+                    ospfIfAuthType,
+                    ospfIfAuthKey,
+                    ospfIfStatus,
+                    ospfIfMulticastForwarding,
+                    ospfIfDemand
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required for OSPF systems."
+       ::= { ospfGroups 7 }
+
+
+    ospfIfMetricGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfIfMetricIpAddress,
+                    ospfIfMetricAddressLessIf,
+                    ospfIfMetricTOS,
+                    ospfIfMetricValue,
+                    ospfIfMetricStatus
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required for OSPF systems."
+       ::= { ospfGroups 8 }
+
+
+    ospfVirtIfGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfVirtIfAreaId,
+                    ospfVirtIfNeighbor,
+                    ospfVirtIfTransitDelay,
+                    ospfVirtIfRetransInterval,
+                    ospfVirtIfHelloInterval,
+                    ospfVirtIfRtrDeadInterval,
+                    ospfVirtIfState,
+                    ospfVirtIfEvents,
+                    ospfVirtIfAuthType,
+                    ospfVirtIfAuthKey,
+                    ospfVirtIfStatus
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required for OSPF systems."
+       ::= { ospfGroups 9 }
+
+
+    ospfNbrGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfNbrIpAddr,
+                    ospfNbrAddressLessIndex,
+                    ospfNbrRtrId,
+                    ospfNbrOptions,
+                    ospfNbrPriority,
+                    ospfNbrState,
+                    ospfNbrEvents,
+                    ospfNbrLsRetransQLen,
+                    ospfNbmaNbrStatus,
+                    ospfNbmaNbrPermanence,
+                    ospfNbrHelloSuppressed
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required for OSPF systems."
+       ::= { ospfGroups 10 }
+
+
+    ospfVirtNbrGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfVirtNbrArea,
+                    ospfVirtNbrRtrId,
+                    ospfVirtNbrIpAddr,
+                    ospfVirtNbrOptions,
+                    ospfVirtNbrState,
+                    ospfVirtNbrEvents,
+                    ospfVirtNbrLsRetransQLen,
+                    ospfVirtNbrHelloSuppressed
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required for OSPF systems."
+       ::= { ospfGroups 11 }
+
+
+    ospfExtLsdbGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfExtLsdbType,
+                    ospfExtLsdbLsid,
+                    ospfExtLsdbRouterId,
+                    ospfExtLsdbSequence,
+                    ospfExtLsdbAge,
+                    ospfExtLsdbChecksum,
+                    ospfExtLsdbAdvertisement
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required  for  OSPF  systems
+           that display their link state database."
+       ::= { ospfGroups 12 }
+
+
+    ospfAreaAggregateGroup    OBJECT-GROUP
+        OBJECTS {
+                    ospfAreaAggregateAreaID,
+                    ospfAreaAggregateLsdbType,
+                    ospfAreaAggregateNet,
+                    ospfAreaAggregateMask,
+                    ospfAreaAggregateStatus,
+                    ospfAreaAggregateEffect
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required for OSPF systems."
+       ::= { ospfGroups 13 }
+
+END
diff --git a/ospfd/OSPF-TRAP-MIB.txt b/ospfd/OSPF-TRAP-MIB.txt
new file mode 100644
index 0000000..8a3ab99
--- /dev/null
+++ b/ospfd/OSPF-TRAP-MIB.txt
@@ -0,0 +1,443 @@
+OSPF-TRAP-MIB DEFINITIONS ::= BEGIN
+
+    IMPORTS
+            MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, IpAddress
+                FROM SNMPv2-SMI
+            MODULE-COMPLIANCE, OBJECT-GROUP
+                FROM SNMPv2-CONF
+            ospfRouterId, ospfIfIpAddress, ospfAddressLessIf, ospfIfState,
+            ospfVirtIfAreaId, ospfVirtIfNeighbor, ospfVirtIfState,
+            ospfNbrIpAddr, ospfNbrAddressLessIndex, ospfNbrRtrId,
+            ospfNbrState, ospfVirtNbrArea, ospfVirtNbrRtrId, ospfVirtNbrState,
+            ospfLsdbType, ospfLsdbLsid, ospfLsdbRouterId, ospfLsdbAreaId,
+            ospfExtLsdbLimit, ospf
+                FROM OSPF-MIB;
+
+    ospfTrap MODULE-IDENTITY
+           LAST-UPDATED "9501201225Z" -- Fri Jan 20 12:25:50 PST 1995
+           ORGANIZATION "IETF OSPF Working Group"
+           CONTACT-INFO
+           "                      Fred Baker
+           Postal:                Cisco Systems
+                                  519 Lado Drive
+                                  Santa Barbara, California 93111
+           Tel:                   +1 805 681 0115
+           E-Mail:                fred@cisco.com
+
+                                  Rob Coltun
+           Postal:                RainbowBridge Communications
+           Tel:                   (301) 340-9416
+           E-Mail:                rcoltun@rainbow-bridge.com"
+       DESCRIPTION
+          "The MIB module to describe traps for  the  OSPF
+          Version 2 Protocol."
+      ::= { ospf 16 }
+
+-- Trap Support Objects
+
+--         The following are support objects for the OSPF traps.
+
+ospfTrapControl OBJECT IDENTIFIER ::= { ospfTrap 1 }
+ospfTraps OBJECT IDENTIFIER ::= { ospfTrap 2 }
+
+    ospfSetTrap OBJECT-TYPE
+        SYNTAX   OCTET STRING (SIZE(4))
+        MAX-ACCESS   read-write
+        STATUS   current
+        DESCRIPTION
+           "A four-octet string serving as a bit  map  for
+           the trap events defined by the OSPF traps. This
+           object is used to enable and  disable  specific
+           OSPF   traps   where  a  1  in  the  bit  field
+           represents enabled.  The right-most bit  (least
+           significant) represents trap 0."
+       ::= { ospfTrapControl 1 }
+
+
+    ospfConfigErrorType OBJECT-TYPE
+        SYNTAX   INTEGER   {
+                    badVersion (1),
+                    areaMismatch (2),
+                    unknownNbmaNbr (3), -- Router is Dr eligible
+                    unknownVirtualNbr (4),
+                    authTypeMismatch(5),
+                    authFailure (6),
+                    netMaskMismatch (7),
+                    helloIntervalMismatch (8),
+                    deadIntervalMismatch (9),
+                    optionMismatch (10) }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "Potential types  of  configuration  conflicts.
+           Used  by the ospfConfigError and ospfConfigVir-
+           tError traps."
+   ::= { ospfTrapControl 2 }
+
+
+    ospfPacketType OBJECT-TYPE
+        SYNTAX   INTEGER   {
+                    hello (1),
+                    dbDescript (2),
+                    lsReq (3),
+                    lsUpdate (4),
+                    lsAck (5) }
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "OSPF packet types."
+   ::= { ospfTrapControl 3 }
+
+
+    ospfPacketSrc OBJECT-TYPE
+        SYNTAX   IpAddress
+        MAX-ACCESS   read-only
+        STATUS   current
+        DESCRIPTION
+           "The IP address of an inbound packet that  can-
+           not be identified by a neighbor instance."
+       ::= { ospfTrapControl 4 }
+
+
+-- Traps
+
+
+    ospfIfStateChange NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfIfIpAddress,
+                    ospfAddressLessIf,
+                    ospfIfState   -- The new state
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfIfStateChange trap signifies that there
+           has been a change in the state of a non-virtual
+           OSPF interface. This trap should  be  generated
+           when  the interface state regresses (e.g., goes
+           from Dr to Down) or progresses  to  a  terminal
+           state  (i.e.,  Point-to-Point, DR Other, Dr, or
+           Backup)."
+   ::= { ospfTraps 16 }
+
+
+    ospfVirtIfStateChange NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfVirtIfAreaId,
+                    ospfVirtIfNeighbor,
+                    ospfVirtIfState  -- The new state
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfIfStateChange trap signifies that there
+           has  been a change in the state of an OSPF vir-
+           tual interface.
+           This trap should be generated when  the  inter-
+           face  state  regresses  (e.g., goes from Point-
+           to-Point to Down) or progresses to  a  terminal
+           state (i.e., Point-to-Point)."
+   ::= { ospfTraps 1 }
+
+
+    ospfNbrStateChange NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfNbrIpAddr,
+                    ospfNbrAddressLessIndex,
+                    ospfNbrRtrId,
+                    ospfNbrState  -- The new state
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An  ospfNbrStateChange  trap  signifies   that
+           there  has been a change in the state of a non-
+           virtual OSPF neighbor.   This  trap  should  be
+           generated  when  the  neighbor  state regresses
+           (e.g., goes from Attempt or Full  to  1-Way  or
+           Down)  or progresses to a terminal state (e.g.,
+           2-Way or Full).  When an  neighbor  transitions
+           from  or  to Full on non-broadcast multi-access
+           and broadcast networks, the trap should be gen-
+           erated  by the designated router.  A designated
+           router transitioning to Down will be  noted  by
+           ospfIfStateChange."
+   ::= { ospfTraps 2 }
+
+
+    ospfVirtNbrStateChange NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfVirtNbrArea,
+                    ospfVirtNbrRtrId,
+                    ospfVirtNbrState  -- The new state
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfIfStateChange trap signifies that there
+           has  been a change in the state of an OSPF vir-
+           tual neighbor.  This trap should  be  generated
+           when  the  neighbor state regresses (e.g., goes
+           from Attempt or  Full  to  1-Way  or  Down)  or
+           progresses to a terminal state (e.g., Full)."
+   ::= { ospfTraps 3 }
+    ospfIfConfigError NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfIfIpAddress,
+                    ospfAddressLessIf,
+                    ospfPacketSrc,  -- The source IP address
+                    ospfConfigErrorType, -- Type of error
+                    ospfPacketType
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfIfConfigError  trap  signifies  that  a
+           packet  has  been received on a non-virtual in-
+           terface  from  a  router  whose   configuration
+           parameters  conflict  with this router's confi-
+           guration parameters.  Note that the  event  op-
+           tionMismatch  should  cause  a  trap only if it
+           prevents an adjacency from forming."
+                  ::= { ospfTraps 4 }
+
+
+    ospfVirtIfConfigError NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfVirtIfAreaId,
+                    ospfVirtIfNeighbor,
+                    ospfConfigErrorType, -- Type of error
+                    ospfPacketType
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfConfigError trap signifies that a pack-
+           et  has  been  received  on a virtual interface
+           from a router  whose  configuration  parameters
+           conflict   with   this  router's  configuration
+           parameters.  Note that the event optionMismatch
+           should  cause a trap only if it prevents an ad-
+           jacency from forming."
+   ::= { ospfTraps 5 }
+
+
+    ospfIfAuthFailure NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfIfIpAddress,
+                    ospfAddressLessIf,
+                    ospfPacketSrc,  -- The source IP address
+                    ospfConfigErrorType, -- authTypeMismatch or
+                                         -- authFailure
+                    ospfPacketType
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfIfAuthFailure  trap  signifies  that  a
+           packet  has  been received on a non-virtual in-
+           terface from a router whose authentication  key
+           or  authentication  type  conflicts  with  this
+           router's authentication key  or  authentication
+           type."
+   ::= { ospfTraps 6 }
+
+
+    ospfVirtIfAuthFailure NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfVirtIfAreaId,
+                    ospfVirtIfNeighbor,
+                    ospfConfigErrorType, -- authTypeMismatch or
+                                         -- authFailure
+                    ospfPacketType
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfVirtIfAuthFailure trap signifies that a
+           packet has been received on a virtual interface
+           from a router whose authentication key  or  au-
+           thentication  type conflicts with this router's
+           authentication key or authentication type."
+   ::= { ospfTraps 7 }
+
+
+    ospfIfRxBadPacket NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfIfIpAddress,
+                    ospfAddressLessIf,
+                    ospfPacketSrc,  -- The source IP address
+                    ospfPacketType
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfIfRxBadPacket trap  signifies  that  an
+           OSPF  packet has been received on a non-virtual
+           interface that cannot be parsed."
+   ::= { ospfTraps 8 }
+
+    ospfVirtIfRxBadPacket NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfVirtIfAreaId,
+                    ospfVirtIfNeighbor,
+                    ospfPacketType
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfRxBadPacket trap signifies that an OSPF
+           packet has been received on a virtual interface
+           that cannot be parsed."
+   ::= { ospfTraps 9 }
+
+
+    ospfTxRetransmit NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfIfIpAddress,
+                    ospfAddressLessIf,
+                    ospfNbrRtrId, -- Destination
+                    ospfPacketType,
+                    ospfLsdbType,
+                    ospfLsdbLsid,
+                    ospfLsdbRouterId
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfTxRetransmit  trap  signifies  than  an
+           OSPF  packet  has  been retransmitted on a non-
+           virtual interface.  All packets that may be re-
+           transmitted  are associated with an LSDB entry.
+           The LS type, LS ID, and Router ID are  used  to
+           identify the LSDB entry."
+   ::= { ospfTraps 10 }
+
+
+    ospfVirtIfTxRetransmit NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfVirtIfAreaId,
+                    ospfVirtIfNeighbor,
+                    ospfPacketType,
+                    ospfLsdbType,
+                    ospfLsdbLsid,
+                    ospfLsdbRouterId
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfTxRetransmit  trap  signifies  than  an
+           OSPF packet has been retransmitted on a virtual
+           interface.  All packets that may be retransmit-
+           ted  are  associated with an LSDB entry. The LS
+           type, LS ID, and Router ID are used to identify
+           the LSDB entry."
+   ::= { ospfTraps 11 }
+
+
+    ospfOriginateLsa NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfLsdbAreaId,  -- 0.0.0.0 for AS Externals
+                    ospfLsdbType,
+                    ospfLsdbLsid,
+                    ospfLsdbRouterId
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfOriginateLsa trap signifies that a  new
+           LSA  has  been originated by this router.  This
+           trap should not be invoked for simple refreshes
+           of  LSAs  (which happesn every 30 minutes), but
+           instead will only be invoked  when  an  LSA  is
+           (re)originated due to a topology change.  Addi-
+           tionally, this trap does not include LSAs  that
+           are  being  flushed  because  they have reached
+           MaxAge."
+   ::= { ospfTraps 12 }
+
+
+    ospfMaxAgeLsa NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfLsdbAreaId,  -- 0.0.0.0 for AS Externals
+                    ospfLsdbType,
+                    ospfLsdbLsid,
+                    ospfLsdbRouterId
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfMaxAgeLsa trap signifies  that  one  of
+           the LSA in the router's link-state database has
+           aged to MaxAge."
+   ::= { ospfTraps 13 }
+
+
+    ospfLsdbOverflow NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfExtLsdbLimit
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfLsdbOverflow trap  signifies  that  the
+           number of LSAs in the router's link-state data-
+           base has exceeded ospfExtLsdbLimit."
+   ::= { ospfTraps 14 }
+
+
+    ospfLsdbApproachingOverflow NOTIFICATION-TYPE
+        OBJECTS {
+                    ospfRouterId, -- The originator of the trap
+                    ospfExtLsdbLimit
+                  }
+        STATUS             current
+        DESCRIPTION
+           "An ospfLsdbApproachingOverflow trap  signifies
+           that  the  number of LSAs in the router's link-
+           state database has exceeded ninety  percent  of
+           ospfExtLsdbLimit."
+   ::= { ospfTraps 15 }
+
+
+-- conformance information
+
+ospfTrapConformance OBJECT IDENTIFIER ::= { ospfTrap 3 }
+
+ospfTrapGroups      OBJECT IDENTIFIER ::= { ospfTrapConformance 1 }
+ospfTrapCompliances OBJECT IDENTIFIER ::= { ospfTrapConformance 2 }
+
+-- compliance statements
+
+    ospfTrapCompliance MODULE-COMPLIANCE
+        STATUS  current
+        DESCRIPTION
+           "The compliance statement "
+       MODULE  -- this module
+       MANDATORY-GROUPS { ospfTrapControlGroup }
+
+
+        GROUP       ospfTrapControlGroup
+        DESCRIPTION
+           "This group is optional but recommended for all
+           OSPF systems"
+       ::= { ospfTrapCompliances 1 }
+
+
+-- units of conformance
+
+    ospfTrapControlGroup    OBJECT-GROUP
+        OBJECTS {
+                           ospfSetTrap,
+                           ospfConfigErrorType,
+                           ospfPacketType,
+                           ospfPacketSrc
+        }
+        STATUS  current
+        DESCRIPTION
+           "These objects are required  to  control  traps
+           from OSPF systems."
+       ::= { ospfTrapGroups 1 }
+
+
+END
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
new file mode 100644
index 0000000..ec3b153
--- /dev/null
+++ b/ospfd/ospf_abr.c
@@ -0,0 +1,1741 @@
+/*
+ * OSPF ABR functions.
+ * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "vty.h"
+#include "filter.h"
+#include "plist.h"
+#include "log.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ia.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_ase.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_dump.h"
+
+
+struct ospf_area_range *
+ospf_area_range_new (struct prefix_ipv4 *p)
+{
+  struct ospf_area_range *range;
+
+  range = XCALLOC (MTYPE_OSPF_AREA_RANGE, sizeof (struct ospf_area_range));
+  range->addr = p->prefix;
+  range->masklen = p->prefixlen;
+  range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC;
+
+  return range;
+}
+
+void
+ospf_area_range_free (struct ospf_area_range *range)
+{
+  XFREE (MTYPE_OSPF_AREA_RANGE, range);
+}
+
+void
+ospf_area_range_add (struct ospf_area *area, struct ospf_area_range *range)
+{
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+
+  p.family = AF_INET;
+  p.prefixlen = range->masklen;
+  p.prefix = range->addr;
+
+  rn = route_node_get (area->ranges, (struct prefix *)&p);
+  if (rn->info)
+    route_unlock_node (rn);
+  else
+    rn->info = range;
+}
+
+void
+ospf_area_range_delete (struct ospf_area *area, struct ospf_area_range *range)
+{
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+
+  p.family = AF_INET;
+  p.prefixlen = range->masklen;
+  p.prefix = range->addr;
+
+  rn = route_node_lookup (area->ranges, (struct prefix *)&p);
+  if (rn)
+    {
+      ospf_area_range_free (rn->info);
+      rn->info = NULL;
+      route_unlock_node (rn);
+      route_unlock_node (rn);
+    }
+}
+
+struct ospf_area_range *
+ospf_area_range_lookup (struct ospf_area *area, struct prefix_ipv4 *p)
+{
+  struct route_node *rn;
+
+  rn = route_node_lookup (area->ranges, (struct prefix *)p);
+  if (rn)
+    {
+      route_unlock_node (rn);
+      return rn->info;
+    }
+  return NULL;
+}
+
+struct ospf_area_range *
+ospf_area_range_lookup_next (struct ospf_area *area, struct in_addr *range_net,
+			     int first)
+{
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+  struct ospf_area_range *find;
+
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+  p.prefix = *range_net;
+
+  if (first)
+    rn = route_top (area->ranges);
+  else
+    {
+      rn = route_node_get (area->ranges, (struct prefix *) &p);
+      rn = route_next (rn);
+    }
+
+  for (; rn; rn = route_next (rn))
+    if (rn->info)
+      break;
+
+  if (rn && rn->info)
+    {
+      find = rn->info;
+      *range_net = rn->p.u.prefix4;
+      route_unlock_node (rn);
+      return find;
+    }
+  return NULL;
+}
+
+struct ospf_area_range *
+ospf_area_range_match (struct ospf_area *area, struct prefix_ipv4 *p)
+{
+  struct route_node *node;
+
+  node = route_node_match (area->ranges, (struct prefix *) p);
+  if (node)
+    {
+      route_unlock_node (node);
+      return node->info;
+    }
+  return NULL;
+}
+
+struct ospf_area_range *
+ospf_area_range_match_any (struct ospf *ospf, struct prefix_ipv4 *p)
+{
+  struct ospf_area_range *range;
+  listnode node;
+
+  for (node = listhead (ospf->areas); node; nextnode (node))
+    if ((range = ospf_area_range_match (node->data, p)))
+      return range;
+
+  return NULL;
+}
+
+int
+ospf_area_range_active (struct ospf_area_range *range)
+{
+  return range->specifics;
+}
+
+int
+ospf_area_actively_attached (struct ospf_area *area)
+{
+  return area->act_ints;
+}
+
+int
+ospf_area_range_set (struct ospf *ospf, struct in_addr area_id,
+		     struct prefix_ipv4 *p, int advertise)
+{
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+  int ret = OSPF_AREA_ID_FORMAT_DECIMAL;
+
+  area = ospf_area_get (area_id, ret);
+  if (area == NULL)
+    return 0;
+
+  range = ospf_area_range_lookup (area, p);
+  if (range != NULL)
+    {
+      if ((CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)
+	   && !CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE))
+	  || (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)
+	      && CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE)))
+	ospf_schedule_abr_task ();
+    }
+  else
+    {
+      range = ospf_area_range_new (p);
+      ospf_area_range_add (area, range);
+      ospf_schedule_abr_task ();
+    }
+
+  if (CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE))
+    SET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE);
+  else
+    UNSET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE);
+
+  return 1;
+}
+
+int
+ospf_area_range_cost_set (struct ospf *ospf, struct in_addr area_id,
+			  struct prefix_ipv4 *p, u_int32_t cost)
+{
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+  int ret = OSPF_AREA_ID_FORMAT_DECIMAL;
+
+  area = ospf_area_get (area_id, ret);
+  if (area == NULL)
+    return 0;
+
+  range = ospf_area_range_new (p);
+  if (range == NULL)
+    return 0;
+
+  if (range->cost_config != cost)
+    {
+      range->cost_config = cost;
+      if (ospf_area_range_active (range))
+	ospf_schedule_abr_task ();
+    }
+
+  return 1;
+}
+
+int
+ospf_area_range_unset (struct ospf *ospf, struct in_addr area_id,
+		       struct prefix_ipv4 *p)
+{
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return 0;
+
+  range = ospf_area_range_lookup (area, p);
+  if (range == NULL)
+    return 0;
+
+  if (ospf_area_range_active (range))
+    ospf_schedule_abr_task ();
+
+  ospf_area_range_delete (area, range);
+
+  return 1;
+}
+
+int
+ospf_area_range_substitute_set (struct ospf *ospf, struct in_addr area_id,
+				struct prefix_ipv4 *p, struct prefix_ipv4 *s)
+{
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+  int ret = OSPF_AREA_ID_FORMAT_DECIMAL;
+
+  area = ospf_area_get (area_id, ret);
+  range = ospf_area_range_lookup (area, p);
+
+  if (range != NULL)
+    {
+      if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE) ||
+	  !CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))
+	ospf_schedule_abr_task ();
+    }
+  else
+    {
+      range = ospf_area_range_new (p);
+      ospf_area_range_add (area, range);
+      ospf_schedule_abr_task ();
+    }
+
+  SET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE);
+  SET_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE);
+  range->subst_addr = s->prefix;
+  range->subst_masklen = s->prefixlen;
+
+  return 1;
+}
+
+int
+ospf_area_range_substitute_unset (struct ospf *ospf, struct in_addr area_id,
+				  struct prefix_ipv4 *p)
+{
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return 0;
+
+  range = ospf_area_range_lookup (area, p);
+  if (range == NULL)
+    return 0;
+
+  if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))
+    if (ospf_area_range_active (range))
+      ospf_schedule_abr_task ();
+
+  UNSET_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE);
+  range->subst_addr.s_addr = 0;
+  range->subst_masklen = 0;
+
+  return 1;
+}
+
+int
+ospf_act_bb_connection ()
+{
+  if (ospf_top->backbone == NULL)
+    return 0;
+
+  return ospf_top->backbone->full_nbrs;
+}
+
+/* Check area border router status. */
+void
+ospf_check_abr_status ()
+{
+  struct ospf_area *area;
+  listnode node;
+  int bb_configured = 0;
+  int bb_act_attached = 0;
+  int areas_configured = 0;
+  int areas_act_attached = 0;
+
+  u_char new_flags = ospf_top->flags;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_check_abr_status(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (listcount (area->oiflist)) 
+	{
+	  areas_configured++;
+	  
+	  if (OSPF_IS_AREA_BACKBONE (area))
+ 	    bb_configured = 1;
+	}
+
+      if (ospf_area_actively_attached (area))
+	{
+	  areas_act_attached++;
+	  
+	  if (OSPF_IS_AREA_BACKBONE (area))
+            bb_act_attached = 1;
+	}
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    {
+      zlog_info ("ospf_check_abr_status(): looked through areas");
+      zlog_info ("ospf_check_abr_status(): bb_configured: %d", bb_configured);
+      zlog_info ("ospf_check_abr_status(): bb_act_attached: %d",
+		 bb_act_attached);
+      zlog_info ("ospf_check_abr_status(): areas_configured: %d",
+		 areas_configured);
+      zlog_info ("ospf_check_abr_status(): areas_act_attached: %d",
+		 areas_act_attached);
+    }
+
+  switch (ospf_top->abr_type)
+    {
+    case OSPF_ABR_SHORTCUT:
+    case OSPF_ABR_STAND:
+      if (areas_act_attached > 1)
+	SET_FLAG (new_flags, OSPF_FLAG_ABR);
+      else
+	UNSET_FLAG (new_flags, OSPF_FLAG_ABR);
+      break;
+
+    case OSPF_ABR_IBM:
+      if ((areas_act_attached > 1) && bb_configured)
+	SET_FLAG (new_flags, OSPF_FLAG_ABR);
+      else
+	UNSET_FLAG (new_flags, OSPF_FLAG_ABR);
+      break;
+
+    case OSPF_ABR_CISCO:
+      if ((areas_configured > 1) && bb_act_attached)
+	SET_FLAG (new_flags, OSPF_FLAG_ABR);
+      else
+	UNSET_FLAG (new_flags, OSPF_FLAG_ABR);
+      break;
+    default:
+      break;
+    }
+
+  if (new_flags != ospf_top->flags)
+    {
+      ospf_spf_calculate_schedule ();
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_check_abr_status(): new router flags: %x",new_flags);
+      ospf_top->flags = new_flags;
+      OSPF_TIMER_ON (ospf_top->t_router_lsa_update,
+		     ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
+    }
+}
+
+void
+ospf_abr_update_aggregate (struct ospf_area_range *range,
+			   struct ospf_route *or)
+{
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_update_aggregate(): Start");
+
+  if (range->cost_config != -1)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_update_aggregate(): use configured cost %d",
+		   range->cost_config);
+
+      range->cost = range->cost_config;
+    }
+  else
+    {
+      if (range->specifics == 0)
+	range->cost = or->cost; /* 1st time get 1st cost */
+
+      if (or->cost < range->cost)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_update_aggregate(): lowest cost, update");
+
+	  range->cost = or->cost;
+	}
+    }
+
+  range->specifics++;
+}
+
+static void
+set_metric (struct ospf_lsa *lsa, u_int32_t metric)
+{
+  struct summary_lsa *header;
+  u_char *mp;
+  metric = htonl (metric);
+  mp = (char *) &metric;
+  mp++;
+  header = (struct summary_lsa *) lsa->data;
+  memcpy(header->metric, mp, 3);
+}
+
+#ifdef HAVE_NSSA
+int
+ospf_abr_check_nssa_range (struct prefix_ipv4 *p, u_int32_t cost,
+				   struct ospf_area *area)
+{
+  /* The Type-7 is tested against the aggregated prefix and forwarded
+       for lsa installation and flooding */
+  return 0;
+}
+
+/* ospf_abr_translate_nssa */
+int
+ospf_abr_translate_nssa (struct ospf_lsa *lsa, void *p_arg, int int_arg)
+{
+  /* Incoming Type-7 or later aggregated Type-7 
+
+     LSA is skipped if P-bit is off.
+     LSA is aggregated if within range.
+
+     The Type-7 is translated, Installed/Approved as a Type-5 into
+     global LSDB, then Flooded through AS
+
+     Later, any Unapproved Translated Type-5's are flushed/discarded */
+
+  struct ospf_lsa *dup;
+
+  if (! CHECK_FLAG (lsa->data->options, OSPF_OPTION_NP))
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_abr_nssa(): P-bit off, NO Translation");
+      return 0; 
+    }
+
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa(): TRANSLATING 7 to 5");
+
+  /* No more P-bit. */
+  /* UNSET_FLAG (lsa->data->options, OSPF_OPTION_NP); */
+
+  /* Area where Aggregate testing will be inserted, just like summary
+     advertisements */
+  /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */
+
+  /* Follow thru here means no aggregation */
+  dup = ospf_lsa_dup (lsa);	/* keep LSDB intact, lock = 1 */
+
+  SET_FLAG (dup->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7  */
+  SET_FLAG (dup->flags, OSPF_LSA_APPROVED); /* So, do not remove it */
+
+  dup->data->type = OSPF_AS_EXTERNAL_LSA;  /* make Type-5 */
+
+  ospf_lsa_checksum (dup->data);
+
+  ospf_lsa_install (NULL, dup); /* Install this Type-5 into LSDB, Lock = 2. */
+
+  ospf_flood_through_as (NULL, dup); /* flood non-NSSA/STUB areas */
+  
+  /* This translated Type-5 will go to all non-NSSA areas connected to
+     this ABR; The Type-5 could come from any of the NSSA's connected
+     to this ABR.  */
+
+  return 0;
+}
+
+void
+ospf_abr_translate_nssa_range (struct prefix_ipv4 *p, u_int32_t cost)
+{
+  /* The Type-7 is created from the aggregated prefix and forwarded
+     for lsa installation and flooding... to be added... */
+}
+#endif /* HAVE_NSSA */
+
+void
+ospf_abr_announce_network_to_area (struct prefix_ipv4 *p, u_int32_t cost,
+				   struct ospf_area *area)
+{
+  struct ospf_lsa *lsa, *old = NULL;
+  struct summary_lsa *sl = NULL;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_network_to_area(): Start");
+
+  old = OSPF_SUMMARY_LSA_SELF_FIND_BY_PREFIX (area, p);
+
+  if (old)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_network_to_area(): old summary found");
+      sl = (struct summary_lsa *) old->data;
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_network_to_area(): "
+		   "old metric: %d, new metric: %d",
+		   GET_METRIC (sl->metric), cost);
+    }
+
+  if (old && (GET_METRIC (sl->metric) == cost))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_network_to_area(): "
+		   "old summary approved"); 
+      SET_FLAG (old->flags, OSPF_LSA_APPROVED);
+    }
+  else
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_network_to_area(): "
+		   "creating new summary");
+      if (old)
+	{
+
+	  set_metric (old, cost);
+	  lsa = ospf_summary_lsa_refresh (old);
+	  /* This will flood through area. */
+	}
+      else
+	{
+	  lsa = ospf_summary_lsa_originate (p, cost, area);
+	  /* This will flood through area. */
+	}
+      
+
+      SET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_network_to_area(): "
+		   "flooding new version of summary");
+
+#ifndef HAVE_NSSA      
+      ospf_flood_through_area (area, NULL, lsa);
+#endif /* ! HAVE_NSSA */
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_network_to_area(): Stop");
+}
+
+int
+ospf_abr_nexthops_belong_to_area (struct ospf_route *or,
+				  struct ospf_area *area)
+{
+  listnode node;
+
+  for (node = listhead (or->path); node; nextnode (node))
+    {
+      struct ospf_path *path = node->data;
+      struct ospf_interface *oi = path->oi;
+
+      if (oi != NULL)
+	if (oi->area == area)
+	  return 1;
+    }
+
+  return 0;
+}
+
+int
+ospf_abr_should_accept (struct prefix *p, struct ospf_area *area)
+{
+  if (IMPORT_NAME (area))
+    {
+      if (IMPORT_LIST (area) == NULL)
+	IMPORT_LIST (area) = access_list_lookup (AFI_IP, IMPORT_NAME (area));
+
+      if (IMPORT_LIST (area))
+        if (access_list_apply (IMPORT_LIST (area), p) == FILTER_DENY)
+           return 0;
+    }
+
+ return 1;
+}
+
+int
+ospf_abr_plist_in_check (struct ospf_area *area, struct ospf_route *or,
+			 struct prefix *p)
+{
+  if (PREFIX_NAME_IN (area))
+    {
+      if (PREFIX_LIST_IN (area) == NULL)
+	PREFIX_LIST_IN (area) = prefix_list_lookup (AFI_IP,
+						    PREFIX_NAME_IN (area));
+      if (PREFIX_LIST_IN (area))
+	if (prefix_list_apply (PREFIX_LIST_IN (area), p) != PREFIX_PERMIT)
+	  return 0;
+    }
+  return 1;
+}
+
+int
+ospf_abr_plist_out_check (struct ospf_area *area, struct ospf_route *or,
+			  struct prefix *p)
+{
+  if (PREFIX_NAME_OUT (area))
+    {
+      if (PREFIX_LIST_OUT (area) == NULL)
+	PREFIX_LIST_OUT (area) = prefix_list_lookup (AFI_IP,
+						     PREFIX_NAME_OUT (area));
+      if (PREFIX_LIST_OUT (area))
+	if (prefix_list_apply (PREFIX_LIST_OUT (area), p) != PREFIX_PERMIT)
+	  return 0;
+    }
+  return 1;
+}
+
+void
+ospf_abr_announce_network (struct route_node *n, struct ospf_route *or)
+{
+  listnode node;
+  struct ospf_area_range *range;
+  struct prefix_ipv4 *p;
+  struct ospf_area *area, *or_area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_network(): Start");
+  p = (struct prefix_ipv4 *) &n->p;
+
+  or_area = ospf_area_lookup_by_area_id (or->u.std.area_id); 
+  assert (or_area);
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_network(): looking at area %s",
+		   inet_ntoa (area->area_id));
+
+      if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id))
+	continue;
+
+      if (ospf_abr_nexthops_belong_to_area (or, area))
+	continue;
+
+      if (!ospf_abr_should_accept (&n->p, area))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_network(): "
+		       "prefix %s/%d was denied by import-list",
+		       inet_ntoa (p->prefix), p->prefixlen);
+	  continue; 
+	}
+
+      if (!ospf_abr_plist_in_check (area, or, &n->p))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_network(): "
+		       "prefix %s/%d was denied by prefix-list",
+		       inet_ntoa (p->prefix), p->prefixlen);
+	  continue; 
+	}
+
+      if (area->external_routing != OSPF_AREA_DEFAULT && area->no_summary)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_network(): "
+		       "area %s is stub and no_summary",
+		       inet_ntoa (area->area_id));
+          continue;
+	}
+
+      if (or->path_type == OSPF_PATH_INTER_AREA)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_network(): this is "
+		       "inter-area route to %s/%d",
+		       inet_ntoa (p->prefix), p->prefixlen);
+
+          if (!OSPF_IS_AREA_BACKBONE (area))
+	    ospf_abr_announce_network_to_area (p, or->cost, area);
+	}
+
+      if (or->path_type == OSPF_PATH_INTRA_AREA)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_network(): "
+		       "this is intra-area route to %s/%d",
+		       inet_ntoa (p->prefix), p->prefixlen);
+	  if ((range = ospf_area_range_match (or_area, p)) &&
+              !ospf_area_is_transit (area))
+	    ospf_abr_update_aggregate (range, or);
+	  else
+	    ospf_abr_announce_network_to_area (p, or->cost, area);
+	}
+    }
+}
+
+int
+ospf_abr_should_announce (struct prefix *p, struct ospf_route *or)
+{
+  struct ospf_area *area = ospf_area_lookup_by_area_id (or->u.std.area_id);
+
+  assert (area);
+  
+  if (EXPORT_NAME (area))
+    {
+      if (EXPORT_LIST (area) == NULL)
+	EXPORT_LIST (area) = access_list_lookup (AFI_IP, EXPORT_NAME (area));
+
+      if (EXPORT_LIST (area))
+        if (access_list_apply (EXPORT_LIST (area), p) == FILTER_DENY)
+           return 0;
+    }
+
+  return 1;
+}
+
+#ifdef HAVE_NSSA
+void
+ospf_abr_process_nssa_translates ()
+{
+  /* Scan through all NSSA_LSDB records for all areas;
+
+     If P-bit is on, translate all Type-7's to 5's and aggregate or
+     flood install as approved in Type-5 LSDB with XLATE Flag on
+     later, do same for all aggregates...  At end, DISCARD all
+     remaining UNAPPROVED Type-5's (Aggregate is for future ) */
+  listnode node;
+  struct ospf_area *area;
+
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_process_nssa_translates(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (! area->NSSATranslator)
+	continue; /* skip if not translator */
+      
+      if (area->external_routing != OSPF_AREA_NSSA)
+	continue;  /* skip if not Nssa Area */
+
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_abr_process_nssa_translates(): "
+		   "looking at area %s", inet_ntoa (area->area_id));
+      
+      foreach_lsa (NSSA_LSDB (area), area, 0, ospf_abr_translate_nssa);
+    }
+ 
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_process_nssa_translates(): Stop");
+
+}
+#endif /* HAVE_NSSA */
+
+void
+ospf_abr_process_network_rt (struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct ospf_area *area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_process_network_rt(): Start");
+
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    {
+      if ((or = rn->info) == NULL)
+	continue;
+
+      if (!(area = ospf_area_lookup_by_area_id (or->u.std.area_id)))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_process_network_rt(): area %s no longer exists",
+		       inet_ntoa (or->u.std.area_id));
+	  continue;
+	}
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_process_network_rt(): this is a route to %s/%d",
+		   inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
+      if (or->path_type >= OSPF_PATH_TYPE1_EXTERNAL)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_process_network_rt(): "
+		       "this is an External router, skipping");
+	  continue;
+	}
+
+      if (or->cost >= OSPF_LS_INFINITY)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_process_network_rt():"
+		       " this route's cost is infinity, skipping");
+	  continue;
+	}
+
+      if (or->type == OSPF_DESTINATION_DISCARD)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_process_network_rt():"
+		       " this is a discard entry, skipping");
+	  continue;
+	}
+
+      if (or->path_type == OSPF_PATH_INTRA_AREA &&
+	  !ospf_abr_should_announce (&rn->p, or))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info("ospf_abr_process_network_rt(): denied by export-list");
+	  continue;
+	}
+
+      if (or->path_type == OSPF_PATH_INTRA_AREA &&
+	  !ospf_abr_plist_out_check (area, or, &rn->p))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info("ospf_abr_process_network_rt(): denied by prefix-list");
+	  continue;
+	}
+
+      if ((or->path_type == OSPF_PATH_INTER_AREA) &&
+          !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_process_network_rt():"
+		       " this is route is not backbone one, skipping");
+	  continue;
+	}
+
+
+      if ((ospf_top->abr_type == OSPF_ABR_CISCO) ||
+          (ospf_top->abr_type == OSPF_ABR_IBM))
+
+          if (!ospf_act_bb_connection () &&
+              or->path_type != OSPF_PATH_INTRA_AREA)
+	     {
+	       if (IS_DEBUG_OSPF_EVENT)
+		 zlog_info ("ospf_abr_process_network_rt(): ALT ABR: "
+			    "No BB connection, skip not intra-area routes");
+	       continue;
+	     }
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_process_network_rt(): announcing");
+      ospf_abr_announce_network (rn, or);
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_process_network_rt(): Stop");
+}
+
+void
+ospf_abr_announce_rtr_to_area (struct prefix_ipv4 *p, u_int32_t cost,
+			       struct ospf_area *area)
+{
+  struct ospf_lsa *lsa, *old = NULL;
+  struct summary_lsa *slsa = NULL;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_rtr_to_area(): Start");
+
+  old = OSPF_SUMMARY_ASBR_LSA_SELF_FIND_BY_PREFIX (area, p);
+  /* old = ospf_find_self_summary_asbr_lsa_by_prefix (area, p); */
+
+  if (old)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_rtr_to_area(): old summary found");
+      slsa = (struct summary_lsa *) old->data;
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_network_to_area(): "
+		   "old metric: %d, new metric: %d",
+		   GET_METRIC (slsa->metric), cost);
+    }
+
+  if (old && (GET_METRIC (slsa->metric) == cost))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_rtr_to_area(): old summary approved");
+      SET_FLAG (old->flags, OSPF_LSA_APPROVED);
+    }
+  else
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_rtr_to_area(): 2.2");
+       
+      if (old) 
+	{ 
+	  set_metric (old, cost);
+	  lsa = ospf_summary_asbr_lsa_refresh (old);
+	}
+      else
+	lsa = ospf_summary_asbr_lsa_originate (p, cost, area);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_rtr_to_area(): "
+		   "flooding new version of summary");
+      /*
+      zlog_info ("ospf_abr_announce_rtr_to_area(): creating new summary");
+      lsa = ospf_summary_asbr_lsa (p, cost, area, old); */
+
+      SET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+      /* ospf_flood_through_area (area, NULL, lsa);*/
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_rtr_to_area(): Stop");
+}
+
+
+void
+ospf_abr_announce_rtr (struct prefix_ipv4 *p, struct ospf_route *or)
+{
+  listnode node;
+  struct ospf_area *area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_rtr(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_rtr(): looking at area %s",
+		   inet_ntoa (area->area_id));
+
+      if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id))
+	continue;
+
+      if (ospf_abr_nexthops_belong_to_area (or, area))
+	continue;
+
+      if (area->external_routing != OSPF_AREA_DEFAULT)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_network(): "
+		       "area %s doesn't support external routing",
+		       inet_ntoa(area->area_id));
+          continue;
+	}
+
+      if (or->path_type == OSPF_PATH_INTER_AREA)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_rtr(): "
+		       "this is inter-area route to %s", inet_ntoa (p->prefix));
+          if (!OSPF_IS_AREA_BACKBONE (area))
+	    ospf_abr_announce_rtr_to_area (p, or->cost, area);
+	}
+
+      if (or->path_type == OSPF_PATH_INTRA_AREA)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_abr_announce_rtr(): "
+		       "this is intra-area route to %s", inet_ntoa (p->prefix));
+          ospf_abr_announce_rtr_to_area (p, or->cost, area);
+	}
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_rtr(): Stop");
+}
+
+void
+ospf_abr_process_router_rt (struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct list *l;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_process_router_rt(): Start");
+
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    {
+      listnode node;
+      char flag = 0;
+      struct ospf_route *best = NULL;
+
+      if (rn->info == NULL)
+	continue;
+
+      l = rn->info;
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_process_router_rt(): this is a route to %s",
+		   inet_ntoa (rn->p.u.prefix4));
+
+      for (node = listhead (l); node; nextnode (node))
+	{
+	  or = getdata (node);
+	  if (or == NULL)
+	    continue;
+
+	  if (!ospf_area_lookup_by_area_id (or->u.std.area_id))
+	    {
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("ospf_abr_process_router_rt(): area %s no longer exists",
+			 inet_ntoa (or->u.std.area_id));
+	      continue;
+	    }
+
+
+	  if (!CHECK_FLAG (or->u.std.flags, ROUTER_LSA_EXTERNAL))
+	    {
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("ospf_abr_process_router_rt(): "
+			   "This is not an ASBR, skipping");
+	      continue;
+	    }
+
+	  if (!flag)
+	    {
+	      best = ospf_find_asbr_route (rt, (struct prefix_ipv4 *) &rn->p);
+	      flag = 1;
+	    }
+	  
+        if (best == NULL)
+	  continue;
+	
+        if (or != best)
+	  {
+	    if (IS_DEBUG_OSPF_EVENT)
+	      zlog_info ("ospf_abr_process_router_rt(): "
+			 "This route is not the best among possible, skipping");
+	    continue;
+	  }
+	
+        if (or->path_type == OSPF_PATH_INTER_AREA &&
+            !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id))
+	  {
+	    if (IS_DEBUG_OSPF_EVENT)
+	      zlog_info ("ospf_abr_process_router_rt(): "
+			 "This route is not a backbone one, skipping");
+	    continue;
+	  }
+
+        if (or->cost >= OSPF_LS_INFINITY)
+	  {
+	    if (IS_DEBUG_OSPF_EVENT)
+	      zlog_info ("ospf_abr_process_router_rt(): "
+			 "This route has LS_INFINITY metric, skipping");
+	    continue;
+	  }
+
+        if (ospf_top->abr_type == OSPF_ABR_CISCO ||
+            ospf_top->abr_type == OSPF_ABR_IBM)
+	  if (!ospf_act_bb_connection () &&
+	      or->path_type != OSPF_PATH_INTRA_AREA)
+	    {
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info("ospf_abr_process_network_rt(): ALT ABR: "
+			  "No BB connection, skip not intra-area routes");
+	      continue;
+	    }
+
+        ospf_abr_announce_rtr ((struct prefix_ipv4 *) &rn->p, or);
+
+	}
+
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_process_router_rt(): Stop");
+}
+
+#ifdef HAVE_NSSA
+int
+ospf_abr_unapprove_translates_apply (struct ospf_lsa *lsa, void *p_arg,
+				    int int_arg)
+{
+  /* Could be a mix of Normal Type-5's, self-originated, or Type-7s
+      that are Locally ABR Translated */
+
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+    UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+  
+  return 0;
+}
+
+void
+ospf_abr_unapprove_translates () /* For NSSA Translations */
+{
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_unapprove_translates(): Start");
+
+  /* NSSA Translator is not checked, because it may have gone away,
+    and we would want to flush any residuals anyway */
+
+  foreach_lsa (EXTERNAL_LSDB (ospf_top), NULL, 0,
+	       ospf_abr_unapprove_translates_apply);
+
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_unapprove_translates(): Stop");
+}
+#endif /* HAVE_NSSA */
+
+int
+ospf_abr_unapprove_summaries_apply (struct ospf_lsa *lsa, void *p_arg,
+				    int int_arg)
+{
+  if (ospf_lsa_is_self_originated (lsa))
+    UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+
+  return 0;
+}
+
+void
+ospf_abr_unapprove_summaries ()
+{
+  listnode node;
+  struct ospf_area *area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_unapprove_summaries(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+      foreach_lsa (SUMMARY_LSDB (area), NULL, 0,
+		   ospf_abr_unapprove_summaries_apply);
+      foreach_lsa (ASBR_SUMMARY_LSDB (area), NULL, 0,
+		   ospf_abr_unapprove_summaries_apply);
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_unapprove_summaries(): Stop");
+}
+
+void
+ospf_abr_prepare_aggregates ()
+{
+  listnode node;
+  struct route_node *rn;
+  struct ospf_area_range *range;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_prepare_aggregates(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      struct ospf_area *area = getdata (node);
+
+      for (rn = route_top (area->ranges); rn; rn = route_next (rn))
+	if ((range = rn->info) != NULL)
+	  {
+	    range->cost = 0;
+	    range->specifics = 0;
+	  }
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_prepare_aggregates(): Stop");
+}
+
+void
+ospf_abr_announce_aggregates ()
+{
+  struct ospf_area *area, *ar;
+  struct ospf_area_range *range;
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+  listnode node, n;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_aggregates(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_aggregates(): looking at area %s",
+		   inet_ntoa (area->area_id));
+
+      for (rn = route_top (area->ranges); rn; rn = route_next (rn))
+	if ((range =  rn->info))
+	  {
+	    if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE))
+	      {
+		if (IS_DEBUG_OSPF_EVENT)
+		  zlog_info ("ospf_abr_announce_aggregates():"
+			     " discarding suppress-ranges");
+		continue;
+	      }
+
+	    p.family = AF_INET;
+	    p.prefix = range->addr;
+	    p.prefixlen = range->masklen;
+
+	    if (IS_DEBUG_OSPF_EVENT)
+	      zlog_info ("ospf_abr_announce_aggregates():"
+			 " this is range: %s/%d",
+			 inet_ntoa (p.prefix), p.prefixlen);
+
+	    if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))
+	      {
+		p.family = AF_INET;
+		p.prefix = range->subst_addr;
+		p.prefixlen = range->subst_masklen;
+	      }
+
+	    if (range->specifics)
+	      {
+		if (IS_DEBUG_OSPF_EVENT)
+		  zlog_info ("ospf_abr_announce_aggregates(): active range");
+
+		for (n = listhead (ospf_top->areas); n; nextnode (n))
+		  {
+		    ar = getdata (n);
+		    if (ar == area)
+		      continue;
+
+		    /* We do not check nexthops here, because
+		       intra-area routes can be associated with
+		       one area only */
+
+		    /* backbone routes are not summarized
+		       when announced into transit areas */
+
+		    if (ospf_area_is_transit (ar) &&
+			OSPF_IS_AREA_BACKBONE (area))
+		      {
+			if (IS_DEBUG_OSPF_EVENT)
+			  zlog_info ("ospf_abr_announce_aggregates(): Skipping "
+				     "announcement of BB aggregate into"
+				     " a transit area");
+			continue; 
+		      }
+		    ospf_abr_announce_network_to_area (&p, range->cost, ar);
+		  }
+	      }
+	  }
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_aggregates(): Stop");
+}
+
+#ifdef HAVE_NSSA
+void
+ospf_abr_send_nssa_aggregates () /* temporarily turned off */
+{
+  listnode node; /*, n; */
+  struct ospf_area *area; /*, *ar; */
+  struct route_node *rn;
+  struct ospf_area_range *range;
+  struct prefix_ipv4 p;
+
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_send_nssa_aggregates(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (! area->NSSATranslator)
+	continue;
+
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_abr_send_nssa_aggregates(): looking at area %s",
+		   inet_ntoa (area->area_id));
+
+      for (rn = route_top (area->ranges); rn; rn = route_next (rn))
+	{
+          if (rn->info == NULL)
+	    continue;
+
+	  range = rn->info;
+
+          if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE))
+	    {
+	      if (IS_DEBUG_OSPF_NSSA)
+		zlog_info ("ospf_abr_send_nssa_aggregates():"
+			   " discarding suppress-ranges");
+	      continue;
+	    }
+
+          p.family = AF_INET;
+          p.prefix = range->addr;
+          p.prefixlen = range->masklen;
+
+	  if (IS_DEBUG_OSPF_NSSA)
+	    zlog_info ("ospf_abr_send_nssa_aggregates():"
+		       " this is range: %s/%d",
+		       inet_ntoa (p.prefix), p.prefixlen);
+
+          if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))
+	    {
+	      p.family = AF_INET;
+	      p.prefix = range->subst_addr;
+	      p.prefixlen = range->subst_masklen;
+	    }
+
+          if (range->specifics)
+	    {
+	      if (IS_DEBUG_OSPF_NSSA)
+		zlog_info ("ospf_abr_send_nssa_aggregates(): active range");
+
+	      /* Fetch LSA-Type-7 from aggregate prefix, and then
+                 translate, Install (as Type-5), Approve, and Flood */
+		ospf_abr_translate_nssa_range (&p, range->cost);
+	    } /* if (range->specifics)*/
+	} /* all area ranges*/
+    } /* all areas */
+
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_send_nssa_aggregates(): Stop");
+}
+
+void
+ospf_abr_announce_nssa_defaults () /* By ABR-Translator */
+{
+  listnode node;
+  struct ospf_area *area;
+  struct prefix_ipv4 p;
+
+  if (! OSPF_IS_ABR)
+    return;
+
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_announce_stub_defaults(): Start");
+
+  p.family = AF_INET;
+  p.prefix.s_addr = OSPF_DEFAULT_DESTINATION;
+  p.prefixlen = 0;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_abr_announce_nssa_defaults(): looking at area %s",
+		   inet_ntoa (area->area_id));
+
+      if (area->external_routing != OSPF_AREA_NSSA)
+	continue;
+
+      if (OSPF_IS_AREA_BACKBONE (area))
+	continue; /* Sanity Check */
+
+      /* if (!TranslatorRole continue V 1.0 look for "always" conf */
+      if (area->NSSATranslator)
+	{
+	  if (IS_DEBUG_OSPF_NSSA)
+	    zlog_info ("ospf_abr_announce_nssa_defaults(): "
+		       "announcing 0.0.0.0/0 to this nssa");
+	  /* ospf_abr_announce_nssa_asbr_to_as (&p, area->default_cost, area); */
+	}
+    }
+}
+#endif /* HAVE_NSSA */
+
+void
+ospf_abr_announce_stub_defaults ()
+{
+  listnode node;
+  struct ospf_area *area;
+  struct prefix_ipv4 p;
+
+  if (! OSPF_IS_ABR)
+    return;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_stub_defaults(): Start");
+
+  p.family = AF_INET;
+  p.prefix.s_addr = OSPF_DEFAULT_DESTINATION;
+  p.prefixlen = 0;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_stub_defaults(): looking at area %s",
+		   inet_ntoa (area->area_id));
+
+#ifdef HAVE_NSSA
+      if (area->external_routing != OSPF_AREA_STUB)
+#else /* ! HAVE_NSSA */
+      if (area->external_routing == OSPF_AREA_DEFAULT)
+#endif /* HAVE_NSSA */
+	continue;
+
+      if (OSPF_IS_AREA_BACKBONE (area))
+	continue; /* Sanity Check */
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_announce_stub_defaults(): "
+		   "announcing 0.0.0.0/0 to this area");
+      ospf_abr_announce_network_to_area (&p, area->default_cost, area);
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_announce_stub_defaults(): Stop");
+}
+
+#ifdef HAVE_NSSA
+int
+ospf_abr_remove_unapproved_translates_apply (struct ospf_lsa *lsa, void *p_arg,
+					     int int_arg)
+{
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)
+      && ! CHECK_FLAG (lsa->flags, OSPF_LSA_APPROVED))
+    {
+      zlog_info ("ospf_abr_remove_unapproved_translates(): "
+		 "removing unapproved translates, ID: %s",
+		 inet_ntoa (lsa->data->id));
+
+      /* FLUSH THROUGHOUT AS */
+      ospf_lsa_flush_as (lsa);
+
+      /* DISCARD from LSDB  */
+    }
+  return 0;
+}
+
+void
+ospf_abr_remove_unapproved_translates () /* For NSSA Translations */
+{
+  /* All AREA PROCESS should have APPROVED necessary LSAs */
+  /* Remove any left over and not APPROVED */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_remove_unapproved_translates(): Start");
+
+  foreach_lsa (EXTERNAL_LSDB (ospf_top), NULL, 0,
+	       ospf_abr_remove_unapproved_translates_apply);
+ 
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_remove_unapproved_translates(): Stop");
+}
+#endif /* HAVE_NSSA */
+
+int
+ospf_abr_remove_unapproved_summaries_apply (struct ospf_lsa *lsa, void *p_arg,
+					    int int_arg)
+{
+  struct ospf_area *area;
+
+  area = (struct ospf_area *) p_arg;
+
+  if (ospf_lsa_is_self_originated (lsa) &&
+      !CHECK_FLAG (lsa->flags, OSPF_LSA_APPROVED))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_remove_unapproved_summaries(): "
+		   "removing unapproved summary, ID: %s",
+		   inet_ntoa (lsa->data->id));
+      ospf_lsa_flush_area (lsa, area);
+    }
+  return 0;
+}
+
+void
+ospf_abr_remove_unapproved_summaries ()
+{
+  listnode node;
+  struct ospf_area *area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_remove_unapproved_summaries(): Start");
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_remove_unapproved_summaries(): "
+		   "looking at area %s", inet_ntoa (area->area_id));
+
+      foreach_lsa (SUMMARY_LSDB (area), area, 0,
+		   ospf_abr_remove_unapproved_summaries_apply);
+      foreach_lsa (ASBR_SUMMARY_LSDB (area), area, 0,
+		   ospf_abr_remove_unapproved_summaries_apply);
+    }
+ 
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_remove_unapproved_summaries(): Stop");
+}
+
+void
+ospf_abr_manage_discard_routes ()
+{
+  listnode node;
+  struct route_node *rn;
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    if ((area = node->data) != NULL)
+      for (rn = route_top (area->ranges); rn; rn = route_next (rn))
+	if ((range = rn->info) != NULL)
+	  if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE))
+	    {
+	      if (range->specifics)
+		ospf_add_discard_route (ospf_top->new_table, area,
+					(struct prefix_ipv4 *) &rn->p);
+	      else
+		ospf_delete_discard_route ((struct prefix_ipv4 *) &rn->p);
+	    }
+}
+
+#ifdef HAVE_NSSA
+/* This is the function taking care about ABR NSSA, i.e.  NSSA
+   Translator, -LSA aggregation and flooding. For all NSSAs
+
+   Any SELF-AS-LSA is in the Type-5 LSDB and Type-7 LSDB.  These LSA's
+   are refreshed from the Type-5 LSDB, installed into the Type-7 LSDB
+   with the P-bit set.
+
+   Any received Type-5s are legal for an ABR, else illegal for IR.
+   Received Type-7s are installed, by area, with incoming P-bit.  They
+   are flooded; if the Elected NSSA Translator, then P-bit off.
+
+   Additionally, this ABR will place "translated type-7's" into the
+   Type-5 LSDB in order to keep track of APPROVAL or not.
+
+   It will scan through every area, looking for Type-7 LSAs with P-Bit
+   SET. The Type-7's are either AS-FLOODED & 5-INSTALLED or
+   AGGREGATED.  Later, the AGGREGATED LSAs are AS-FLOODED &
+   5-INSTALLED.
+
+   5-INSTALLED is into the Type-5 LSDB; Any UNAPPROVED Type-5 LSAs
+   left over are FLUSHED and DISCARDED.
+
+   For External Calculations, any NSSA areas use the Type-7 AREA-LSDB,
+   any ABR-non-NSSA areas use the Type-5 GLOBAL-LSDB. */
+
+void
+ospf_abr_nssa_task () /* called only if any_nssa */
+{
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("Check for NSSA-ABR Tasks():");
+
+  if (! OSPF_IS_ABR)
+    return;
+
+  if (! ospf_top->anyNSSA)
+    return;
+
+  /* Each area must confirm TranslatorRole */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa_task(): Start");
+
+  /* For all Global Entries flagged "local-translate", unset APPROVED */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa_task(): unapprove translates");
+
+  ospf_abr_unapprove_translates ();
+
+  /* RESET all Ranges in every Area, same as summaries */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa_task(): NSSA initialize aggregates");
+
+  /*    ospf_abr_prepare_aggregates ();  TURNED OFF just for now */
+
+  /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
+     Aggregate as Type-7 */
+  /* Install or Approve in Type-5 Global LSDB */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa_task(): process translates");
+
+  ospf_abr_process_nssa_translates (ospf_top->new_table);
+
+  /* Translate/Send any "ranged" aggregates, and also 5-Install and
+     Approve */
+  /* Scan Type-7's for aggregates, translate to Type-5's,
+     Install/Flood/Approve */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info("ospf_abr_nssa_task(): send NSSA aggregates");
+  /*       ospf_abr_send_nssa_aggregates ();  TURNED OFF FOR NOW */
+
+  /* Send any NSSA defaults as Type-5 */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa_task(): announce nssa defaults");
+  ospf_abr_announce_nssa_defaults ();
+   
+  /* Flush any unapproved previous translates from Global Data Base */
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa_task(): remove unapproved translates");
+  ospf_abr_remove_unapproved_translates ();
+
+  ospf_abr_manage_discard_routes (); /* same as normal...discard */
+
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_abr_nssa_task(): Stop");
+}
+#endif /* HAVE_NSSA */
+
+/* This is the function taking care about ABR stuff, i.e.
+   summary-LSA origination and flooding. */
+void
+ospf_abr_task ()
+{
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_task(): Start");
+
+  if (ospf_top->new_table == NULL || ospf_top->new_rtrs == NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_task(): Routing tables are not yet ready");
+      return;
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_task(): unapprove summaries");
+  ospf_abr_unapprove_summaries ();
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_task(): prepare aggregates");
+  ospf_abr_prepare_aggregates ();
+
+  if (OSPF_IS_ABR)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_task(): process network RT");
+      ospf_abr_process_network_rt (ospf_top->new_table);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_task(): process router RT");
+      ospf_abr_process_router_rt (ospf_top->new_rtrs);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_task(): announce aggregates");
+      ospf_abr_announce_aggregates ();
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_abr_task(): announce stub defaults");
+      ospf_abr_announce_stub_defaults ();
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_task(): remove unapproved summaries");
+  ospf_abr_remove_unapproved_summaries ();
+
+  ospf_abr_manage_discard_routes ();
+
+#ifdef HAVE_NSSA
+  ospf_abr_nssa_task(); /* if nssa-abr, then scan Type-7 LSDB */
+#endif /* HAVE_NSSA */
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_abr_task(): Stop");
+}
+
+
+int
+ospf_abr_task_timer (struct thread *t)
+{
+  ospf_top->t_abr_task = 0;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Running ABR task on timer");
+
+  ospf_check_abr_status ();
+
+  ospf_abr_task ();
+
+ return 0;
+}
+
+void
+ospf_schedule_abr_task ()
+{
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Scheduling ABR task");
+  if (! ospf_top->t_abr_task)
+    ospf_top->t_abr_task = thread_add_timer (master, ospf_abr_task_timer,
+					     0, OSPF_ABR_TASK_DELAY);
+}
diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h
new file mode 100644
index 0000000..3b385c3
--- /dev/null
+++ b/ospfd/ospf_abr.h
@@ -0,0 +1,84 @@
+/*
+ * OSPF ABR functions.
+ * Copyright (C) 1999 Alex Zinin
+ *
+ * This file is part of GNU Zebra.
+ * 
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_ABR_H
+#define _ZEBRA_OSPF_ABR_H
+
+#define OSPF_ABR_TASK_DELAY 	7
+
+#define OSPF_AREA_RANGE_ADVERTISE	(1 << 0)
+#define OSPF_AREA_RANGE_SUBSTITUTE	(1 << 1)
+
+/* Area range. */
+struct ospf_area_range
+{
+  /* Area range address. */
+  struct in_addr addr;
+
+  /* Area range masklen. */
+  u_char masklen;
+
+  /* Flags. */
+  u_char flags;
+
+  /* Number of more specific prefixes. */
+  int specifics;
+
+  /* Addr and masklen to substitute. */
+  struct in_addr subst_addr;
+  u_char subst_masklen;
+
+  /* Range cost. */
+  u_int32_t cost;
+
+  /* Configured range cost. */
+  u_int32_t cost_config;
+#define OSPF_AREA_RANGE_COST_UNSPEC	-1
+};
+
+/* Prototypes. */
+struct ospf_area_range *ospf_area_range_lookup (struct ospf_area *,
+						struct prefix_ipv4 *);
+struct ospf_area_range *ospf_some_area_range_match (struct prefix_ipv4 *);
+struct ospf_area_range *ospf_area_range_lookup_next (struct ospf_area *,
+						     struct in_addr *, int);
+int ospf_area_range_set (struct ospf *, struct in_addr, struct prefix_ipv4 *,
+			 int);
+int ospf_area_range_cost_set (struct ospf *, struct in_addr,
+			      struct prefix_ipv4 *, u_int32_t);
+int ospf_area_range_unset (struct ospf *, struct in_addr,
+			   struct prefix_ipv4 *);
+int ospf_area_range_substitute_set (struct ospf *, struct in_addr,
+				    struct prefix_ipv4 *,
+				    struct prefix_ipv4 *);
+int ospf_area_range_substitute_unset (struct ospf *, struct in_addr,
+				      struct prefix_ipv4 *);
+struct ospf_area_range *ospf_area_range_match_any (struct ospf *,
+						   struct prefix_ipv4 *);
+int ospf_area_range_active (struct ospf_area_range *);
+int ospf_act_bb_connection ();
+
+void ospf_check_abr_status ();
+void ospf_abr_task ();
+void ospf_schedule_abr_task ();
+
+#endif /* _ZEBRA_OSPF_ABR_H */
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
new file mode 100644
index 0000000..d13bbc4
--- /dev/null
+++ b/ospfd/ospf_asbr.c
@@ -0,0 +1,287 @@
+/*
+ * OSPF AS Boundary Router functions.
+ * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "vty.h"
+#include "filter.h"
+#include "log.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_dump.h"
+
+/* Remove external route. */
+void
+ospf_external_route_remove (struct prefix_ipv4 *p)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+
+  rn = route_node_lookup (ospf_top->old_external_route, (struct prefix *) p);
+  if (rn)
+    if ((or = rn->info))
+      {
+	zlog_info ("Route[%s/%d]: external path deleted",
+		   inet_ntoa (p->prefix), p->prefixlen);
+
+	/* Remove route from zebra. */
+        if (or->type == OSPF_DESTINATION_NETWORK)
+	  ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
+
+	ospf_route_free (or);
+	rn->info = NULL;
+
+	route_unlock_node (rn);
+	route_unlock_node (rn);
+	return;
+      }
+
+  zlog_info ("Route[%s/%d]: no such external path",
+	     inet_ntoa (p->prefix), p->prefixlen);
+}
+
+/* Lookup external route. */
+struct ospf_route *
+ospf_external_route_lookup (struct prefix_ipv4 *p)
+{
+  struct route_node *rn;
+
+  rn = route_node_lookup (ospf_top->old_external_route, (struct prefix *) p);
+  if (rn)
+    {
+      route_unlock_node (rn);
+      if (rn->info)
+	return rn->info;
+    }
+
+  zlog_warn ("Route[%s/%d]: lookup, no such prefix",
+	     inet_ntoa (p->prefix), p->prefixlen);
+
+  return NULL;
+}
+
+
+/* Add an External info for AS-external-LSA. */
+struct external_info *
+ospf_external_info_new (u_char type)
+{
+  struct external_info *new;
+
+  new = (struct external_info *)
+    XMALLOC (MTYPE_OSPF_EXTERNAL_INFO, sizeof (struct external_info));
+  memset (new, 0, sizeof (struct external_info));
+  new->type = type;
+
+  ospf_reset_route_map_set_values (&new->route_map_set);
+  return new;
+}
+
+void
+ospf_external_info_free (struct external_info *ei)
+{
+  XFREE (MTYPE_OSPF_EXTERNAL_INFO, ei);
+}
+
+void
+ospf_reset_route_map_set_values (struct route_map_set_values *values)
+{
+  values->metric = -1;
+  values->metric_type = -1;
+}
+
+int
+ospf_route_map_set_compare (struct route_map_set_values *values1,
+			    struct route_map_set_values *values2)
+{
+  return values1->metric == values2->metric &&
+    values1->metric_type == values2->metric_type;
+}
+
+/* Add an External info for AS-external-LSA. */
+struct external_info *
+ospf_external_info_add (u_char type, struct prefix_ipv4 p,
+			unsigned int ifindex, struct in_addr nexthop)
+{
+  struct external_info *new;
+  struct route_node *rn;
+
+  /* Initialize route table. */
+  if (EXTERNAL_INFO (type) == NULL)
+    EXTERNAL_INFO (type) = route_table_init ();
+
+  rn = route_node_get (EXTERNAL_INFO (type), (struct prefix *) &p);
+  /* If old info exists, -- discard new one or overwrite with new one? */
+  if (rn)
+    if (rn->info)
+      {
+	route_unlock_node (rn);
+	zlog_warn ("Redistribute[%s]: %s/%d already exists, discard.",
+		   LOOKUP (ospf_redistributed_proto, type),
+		   inet_ntoa (p.prefix), p.prefixlen);
+	/* XFREE (MTYPE_OSPF_TMP, rn->info); */
+	return rn->info;
+      }
+
+  /* Create new External info instance. */
+  new = ospf_external_info_new (type);
+  new->p = p;
+  new->ifindex = ifindex;
+  new->nexthop = nexthop;
+  new->tag = 0;
+
+  rn->info = new;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("Redistribute[%s]: %s/%d external info created.",
+	       LOOKUP (ospf_redistributed_proto, type),
+	       inet_ntoa (p.prefix), p.prefixlen);
+  return new;
+}
+
+void
+ospf_external_info_delete (u_char type, struct prefix_ipv4 p)
+{
+  struct route_node *rn;
+
+  rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p);
+  if (rn)
+    {
+      ospf_external_info_free (rn->info);
+      rn->info = NULL;
+      route_unlock_node (rn);
+      route_unlock_node (rn);
+    }
+}
+
+struct external_info *
+ospf_external_info_lookup (u_char type, struct prefix_ipv4 *p)
+{
+  struct route_node *rn;
+  rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) p);
+  if (rn)
+    {
+      route_unlock_node (rn);
+      if (rn->info)
+	return rn->info;
+    }
+
+  return NULL;
+}
+
+struct ospf_lsa *
+ospf_external_info_find_lsa (struct prefix_ipv4 *p)
+{
+  struct ospf_lsa *lsa;
+  struct as_external_lsa *al;
+  struct in_addr mask, id;
+
+  lsa = ospf_lsdb_lookup_by_id (ospf_top->lsdb, OSPF_AS_EXTERNAL_LSA,
+			       p->prefix, ospf_top->router_id);
+
+  if (!lsa)
+    return NULL;
+
+  al = (struct as_external_lsa *) lsa->data;
+
+  masklen2ip (p->prefixlen, &mask);
+
+  if (mask.s_addr != al->mask.s_addr)
+    {
+      id.s_addr = p->prefix.s_addr | (~mask.s_addr);
+      lsa = ospf_lsdb_lookup_by_id (ospf_top->lsdb, OSPF_AS_EXTERNAL_LSA,
+				   id, ospf_top->router_id);
+      if (!lsa)
+	return NULL;
+    }
+
+  return lsa;
+}
+
+
+/* Update ASBR status. */
+void
+ospf_asbr_status_update (u_char status)
+{
+  zlog_info ("ASBR[Status:%d]: Update", status);
+
+  /* ASBR on. */
+  if (status)
+    {
+      /* Already ASBR. */
+      if (OSPF_IS_ASBR)
+	{
+	  zlog_info ("ASBR[Status:%d]: Already ASBR", status);
+	  return;
+	}
+      SET_FLAG (ospf_top->flags, OSPF_FLAG_ASBR);
+    }
+  else
+    {
+      /* Already non ASBR. */
+      if (! OSPF_IS_ASBR)
+	{
+	  zlog_info ("ASBR[Status:%d]: Already non ASBR", status);
+	  return;
+	}
+      UNSET_FLAG (ospf_top->flags, OSPF_FLAG_ASBR);
+    }
+
+  /* Transition from/to status ASBR, schedule timer. */
+  ospf_spf_calculate_schedule ();
+  OSPF_TIMER_ON (ospf_top->t_router_lsa_update,
+		 ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
+}
+
+void
+ospf_redistribute_withdraw (u_char type)
+{
+  struct route_node *rn;
+  struct external_info *ei;
+
+  /* Delete external info for specified type. */
+  if (EXTERNAL_INFO (type))
+    for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn))
+      if ((ei = rn->info))
+	if (ospf_external_info_find_lsa (&ei->p))
+	  {
+	    if (is_prefix_default (&ei->p) &&
+		ospf_top->default_originate != DEFAULT_ORIGINATE_NONE)
+	      continue;
+	    ospf_external_lsa_flush (type, &ei->p, ei->ifindex, ei->nexthop);
+	    ospf_external_info_delete (type, ei->p);
+	  }
+}
diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h
new file mode 100644
index 0000000..f368246
--- /dev/null
+++ b/ospfd/ospf_asbr.h
@@ -0,0 +1,75 @@
+/*
+ * OSPF AS Boundary Router functions.
+ * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_ASBR_H
+#define _ZEBRA_OSPF_ASBR_H
+
+struct route_map_set_values
+{
+  int32_t metric;
+  int32_t metric_type;
+};
+
+/* Redistributed external information. */
+struct external_info
+{
+  /* Type of source protocol. */
+  u_char type;
+
+  /* Prefix. */
+  struct prefix_ipv4 p;
+
+  /* Interface index. */
+  unsigned int ifindex;
+
+  /* Nexthop address. */
+  struct in_addr nexthop;
+
+  /* Additional Route tag. */
+  u_int32_t tag;
+
+  struct route_map_set_values route_map_set;
+#define ROUTEMAP_METRIC(E)      (E)->route_map_set.metric
+#define ROUTEMAP_METRIC_TYPE(E) (E)->route_map_set.metric_type
+};
+
+#define OSPF_ASBR_CHECK_DELAY 30
+
+void ospf_external_route_remove (struct prefix_ipv4 *p);
+struct external_info *ospf_external_info_new (u_char);
+void ospf_reset_route_map_set_values (struct route_map_set_values *values);
+int ospf_route_map_set_compare (struct route_map_set_values *values1,
+				struct route_map_set_values *values2);
+struct external_info *ospf_external_info_add (u_char, struct prefix_ipv4,
+					      unsigned int, struct in_addr);
+void ospf_external_info_delete (u_char, struct prefix_ipv4);
+struct external_info *ospf_external_info_lookup (u_char, struct prefix_ipv4 *);
+
+void ospf_asbr_status_update (u_char);
+
+void ospf_redistribute_withdraw (u_char);
+void ospf_asbr_check ();
+void ospf_schedule_asbr_check ();
+void ospf_asbr_route_install_lsa (struct ospf_lsa *);
+struct ospf_lsa *ospf_external_info_find_lsa (struct prefix_ipv4 *p);
+
+#endif /* _ZEBRA_OSPF_ASBR_H */
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
new file mode 100644
index 0000000..9194c56
--- /dev/null
+++ b/ospfd/ospf_ase.c
@@ -0,0 +1,838 @@
+/*
+ * OSPF AS external route calculation.
+ * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "hash.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "vty.h"
+#include "log.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ase.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_dump.h"
+
+#define DEBUG
+
+struct ospf_route *
+ospf_find_asbr_route (struct route_table *rtrs, struct prefix_ipv4 *asbr)
+{
+  struct route_node *rn;
+  struct ospf_route *or, *best = NULL;
+  listnode node;
+  list chosen;
+
+  /* Sanity check. */
+  if (rtrs == NULL)
+    return NULL;
+
+  rn = route_node_lookup (rtrs, (struct prefix *) asbr);
+  if (! rn)
+    return NULL;
+
+  route_unlock_node (rn);
+
+  chosen = list_new ();
+
+  /* First try to find intra-area non-bb paths. */
+  if (!CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+    for (node = listhead ((list) rn->info); node; nextnode (node))
+      if ((or = getdata (node)) != NULL)
+	if (or->cost < OSPF_LS_INFINITY)
+	  if (!OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id) &&
+	      or->path_type == OSPF_PATH_INTRA_AREA)
+	    listnode_add (chosen, or);
+
+  /* If none is found -- look through all. */
+  if (listcount (chosen) == 0)
+    {
+      list_free (chosen);
+      chosen = rn->info;
+    }
+
+  /* Now find the route with least cost. */
+  for (node = listhead (chosen); node; nextnode (node))
+    if ((or = getdata (node)) != NULL)
+      if (or->cost < OSPF_LS_INFINITY)
+	{
+	  if (best == NULL)
+	    best = or;
+	  else if (best->cost > or->cost)
+	    best = or;
+	  else if (best->cost == or->cost &&
+		   IPV4_ADDR_CMP (&best->u.std.area_id,
+				  &or->u.std.area_id) < 0)
+	    best = or;
+	}
+
+  if (chosen != rn->info)
+    list_delete (chosen);
+
+  return best;
+}
+
+struct ospf_route * 
+ospf_find_asbr_route_through_area (struct route_table *rtrs, 
+				   struct prefix_ipv4 *asbr, 
+				   struct ospf_area *area)
+{
+  struct route_node *rn;
+
+  /* Sanity check. */
+  if (rtrs == NULL)
+    return NULL;
+
+  rn = route_node_lookup (rtrs, (struct prefix *) asbr);
+ 
+  if (rn)
+    {
+      listnode node;
+      struct ospf_route *or;
+
+      route_unlock_node (rn);
+
+      for (node = listhead ((list) rn->info); node; nextnode (node))
+	if ((or = getdata (node)) != NULL)
+	  if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id))
+	    return or;
+    }
+
+  return NULL;
+}
+
+void
+ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop)
+{
+  listnode node;
+  struct ospf_path *op;
+
+  for (node = listhead (ro->path); node; nextnode (node))
+    if ((op = getdata (node)) != NULL)
+      if (op->nexthop.s_addr == 0)
+	op->nexthop.s_addr = nexthop.s_addr;
+}
+
+int
+ospf_ase_forward_address_check (struct in_addr fwd_addr)
+{
+  listnode ifn;
+  struct ospf_interface *oi;
+
+  for (ifn = listhead (ospf_top->oiflist); ifn; nextnode (ifn))
+    if ((oi = getdata (ifn)) != NULL)
+      if (if_is_up (oi->ifp))
+	if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
+	  if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &fwd_addr))
+	    return 0;
+  
+  return 1;
+}
+
+/* Calculate ASBR route. */
+struct ospf_route *
+ospf_ase_calculate_asbr_route (struct route_table *rt_network,
+			       struct route_table *rt_router,
+			       struct as_external_lsa *al)
+{
+  struct prefix_ipv4 asbr;
+  struct ospf_route *asbr_route;
+  struct route_node *rn;
+
+  /* Find ASBR route from Router routing table. */
+  asbr.family = AF_INET;
+  asbr.prefix = al->header.adv_router;
+  asbr.prefixlen = IPV4_MAX_BITLEN;
+  apply_mask_ipv4 (&asbr);
+
+  asbr_route = ospf_find_asbr_route (rt_router, &asbr);
+
+  if (asbr_route == NULL)
+    {
+      zlog_info ("ospf_ase_calculate(): Route to ASBR %s not found",
+		 inet_ntoa (asbr.prefix));
+      return NULL;
+    }
+
+  if (!(asbr_route->u.std.flags & ROUTER_LSA_EXTERNAL))
+    {
+      zlog_info ("ospf_ase_calculate(): Originating router is not an ASBR");
+      return NULL;
+    }
+   
+  if (al->e[0].fwd_addr.s_addr != 0)
+    {
+      zlog_info ("ospf_ase_calculate(): "
+		 "Forwarding address is not 0.0.0.0.");
+
+      if (! ospf_ase_forward_address_check (al->e[0].fwd_addr))
+	{
+	  zlog_info ("ospf_ase_calculate(): "
+		     "Forwarding address is one of our addresses, Ignore.");
+	  return NULL;
+        }
+
+      zlog_info ("ospf_ase_calculate(): "
+		 "Looking up in the Network Routing Table.");
+
+      /* Looking up the path to the fwd_addr from Network route. */
+      asbr.family = AF_INET;
+      asbr.prefix = al->e[0].fwd_addr;
+      asbr.prefixlen = IPV4_MAX_BITLEN;
+
+      rn = route_node_match (rt_network, (struct prefix *) &asbr);
+   
+      if (rn == NULL)
+	{
+	  zlog_info ("ospf_ase_calculate(): "
+		     "Couldn't find a route to the forwarding address.");
+	  return NULL;
+	}
+
+      route_unlock_node (rn);
+
+      if ((asbr_route = rn->info) == NULL)
+	{
+	  zlog_info ("ospf_ase_calculate(): "
+		     "Somehow OSPF route to ASBR is lost");
+	  return NULL;
+	}
+    }
+
+  return asbr_route;
+}
+
+struct ospf_route *
+ospf_ase_calculate_new_route (struct ospf_lsa *lsa,
+			      struct ospf_route *asbr_route, u_int32_t metric)
+{
+  struct as_external_lsa *al;
+  struct ospf_route *new;
+
+  al = (struct as_external_lsa *) lsa->data;
+
+  new = ospf_route_new ();
+
+  /* Set redistributed type -- does make sense? */
+  /* new->type = type; */
+  new->id = al->header.id;
+  new->mask = al->mask;
+
+  if (!IS_EXTERNAL_METRIC (al->e[0].tos))
+    {
+      zlog_info ("Route[External]: type-1 created.");
+      new->path_type = OSPF_PATH_TYPE1_EXTERNAL;
+      new->cost = asbr_route->cost + metric;		/* X + Y */
+    }
+  else
+    {
+      zlog_info ("Route[External]: type-2 created.");
+      new->path_type = OSPF_PATH_TYPE2_EXTERNAL;
+      new->cost = asbr_route->cost;			/* X */
+      new->u.ext.type2_cost = metric;			/* Y */
+    }
+
+  new->type = OSPF_DESTINATION_NETWORK;
+  new->path = list_new ();
+  new->u.ext.origin = lsa;
+  new->u.ext.tag = ntohl (al->e[0].route_tag);
+  new->u.ext.asbr = asbr_route;
+
+  assert (new != asbr_route);
+
+  return new;
+}
+
+#define OSPF_ASE_CALC_INTERVAL 1
+
+int
+ospf_ase_calculate_route (struct ospf_lsa * lsa, void * p_arg, int n_arg)
+{
+  u_int32_t metric;
+  struct as_external_lsa *al;
+  struct ospf_route *asbr_route;
+  struct prefix_ipv4 asbr, p;
+  struct route_node *rn;
+  struct ospf_route *new, *or;
+  int ret;
+  
+  assert (lsa);
+  al = (struct as_external_lsa *) lsa->data;
+
+#ifdef HAVE_NSSA
+  if (lsa->data->type == OSPF_AS_NSSA_LSA)
+    if (IS_DEBUG_OSPF_NSSA)
+      zlog_info ("ospf_ase_calc(): Processing Type-7");
+
+  /* Stay away from any Local Translated Type-7 LSAs */
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_ase_calc(): Rejecting Local Xlt'd");
+      return 0;
+    }
+#endif /* HAVE_NSSA */
+
+  zlog_info ("Route[External]: Calculate AS-external-LSA to %s/%d",
+	     inet_ntoa (al->header.id), ip_masklen (al->mask));
+  /* (1) If the cost specified by the LSA is LSInfinity, or if the
+         LSA's LS age is equal to MaxAge, then examine the next LSA. */
+  if ((metric = GET_METRIC (al->e[0].metric)) >= OSPF_LS_INFINITY)
+    {
+      zlog_info ("Route[External]: Metric is OSPF_LS_INFINITY");
+      return 0;
+    }
+  if (IS_LSA_MAXAGE (lsa))
+    {
+      zlog_info ("Route[External]: AS-external-LSA is MAXAGE");
+      return 0;
+    }
+  
+  /* (2) If the LSA was originated by the calculating router itself,
+     examine the next LSA. */
+  if (IS_LSA_SELF (lsa))
+    {
+      zlog_info ("Route[External]: AS-external-LSA is self originated");
+      return 0;
+    }
+
+  /* (3) Call the destination described by the LSA N.  N's address is
+         obtained by masking the LSA's Link State ID with the
+	 network/subnet mask contained in the body of the LSA.  Look
+	 up the routing table entries (potentially one per attached
+	 area) for the AS boundary router (ASBR) that originated the
+	 LSA. If no entries exist for router ASBR (i.e., ASBR is
+	 unreachable), do nothing with this LSA and consider the next
+	 in the list. */
+  
+  asbr.family = AF_INET;
+  asbr.prefix = al->header.adv_router;
+  asbr.prefixlen = IPV4_MAX_BITLEN;
+  apply_mask_ipv4 (&asbr);
+  
+  asbr_route = ospf_find_asbr_route (ospf_top->new_rtrs, &asbr);
+  if (asbr_route == NULL)
+    {
+      zlog_info ("Route[External]: Can't find originating ASBR route");
+      return 0;
+    }
+  if (!(asbr_route->u.std.flags & ROUTER_LSA_EXTERNAL))
+    {
+      zlog_info ("Route[External]: Originating router is not an ASBR");
+      return 0;
+    }
+  
+  /*     Else, this LSA describes an AS external path to destination
+	 N.  Examine the forwarding address specified in the AS-
+	 external-LSA.  This indicates the IP address to which
+	 packets for the destination should be forwarded. */
+  
+  if (al->e[0].fwd_addr.s_addr == 0)
+    {
+      /* If the forwarding address is set to 0.0.0.0, packets should
+	 be sent to the ASBR itself. Among the multiple routing table
+	 entries for the ASBR, select the preferred entry as follows.
+	 If RFC1583Compatibility is set to "disabled", prune the set
+	 of routing table entries for the ASBR as described in
+	 Section 16.4.1. In any case, among the remaining routing
+	 table entries, select the routing table entry with the least
+	 cost; when there are multiple least cost routing table
+	 entries the entry whose associated area has the largest OSPF
+	 Area ID (when considered as an unsigned 32-bit integer) is
+	 chosen. */
+
+      /* asbr_route already contains the requested route */
+    }
+  else
+    {
+      /* If the forwarding address is non-zero, look up the
+	 forwarding address in the routing table.[24] The matching
+	 routing table entry must specify an intra-area or inter-area
+	 path; if no such path exists, do nothing with the LSA and
+	 consider the next in the list. */
+      if (! ospf_ase_forward_address_check (al->e[0].fwd_addr))
+	{
+	  zlog_info ("Route[External]: Forwarding address is our router address");
+	  return 0;
+	}
+      
+      asbr.family = AF_INET;
+      asbr.prefix = al->e[0].fwd_addr;
+      asbr.prefixlen = IPV4_MAX_BITLEN;
+
+      rn = route_node_match (ospf_top->new_table, (struct prefix *) &asbr);
+      
+      if (rn == NULL || (asbr_route = rn->info) == NULL)
+	{
+	  zlog_info ("Route[External]: Can't find route to forwarding address");
+	  if (rn)
+	    route_unlock_node (rn);
+	  return 0;
+	}
+
+      route_unlock_node (rn);
+    }
+
+  /* (4) Let X be the cost specified by the preferred routing table
+         entry for the ASBR/forwarding address, and Y the cost
+	 specified in the LSA.  X is in terms of the link state
+	 metric, and Y is a type 1 or 2 external metric. */
+			 
+
+  /* (5) Look up the routing table entry for the destination N.  If
+         no entry exists for N, install the AS external path to N,
+	 with next hop equal to the list of next hops to the
+	 forwarding address, and advertising router equal to ASBR.
+	 If the external metric type is 1, then the path-type is set
+	 to type 1 external and the cost is equal to X+Y.  If the
+	 external metric type is 2, the path-type is set to type 2
+	 external, the link state component of the route's cost is X,
+	 and the type 2 cost is Y. */
+  new = ospf_ase_calculate_new_route (lsa, asbr_route, metric);
+
+  /* (6) Compare the AS external path described by the LSA with the
+         existing paths in N's routing table entry, as follows. If
+	 the new path is preferred, it replaces the present paths in
+	 N's routing table entry.  If the new path is of equal
+	 preference, it is added to N's routing table entry's list of
+	 paths. */
+
+  /* Set prefix. */
+  p.family = AF_INET;
+  p.prefix = al->header.id;
+  p.prefixlen = ip_masklen (al->mask);
+
+  /* if there is a Intra/Inter area route to the N
+     do not install external route */
+  if ((rn = route_node_lookup (ospf_top->new_table,
+			       (struct prefix *) &p)) != NULL
+      && (rn->info != NULL))
+    {
+      if (new)
+	ospf_route_free (new);
+      return 0;
+    }
+  
+  /* Find a route to the same dest */
+  /* If there is no route, create new one. */
+  if ((rn = route_node_lookup (ospf_top->new_external_route,
+			       (struct prefix *) &p)) == NULL 
+      || (or = rn->info) == NULL)
+    {
+      zlog_info ("Route[External]: Adding a new route %s/%d",
+		 inet_ntoa (p.prefix), p.prefixlen);
+
+      ospf_route_add (ospf_top->new_external_route, &p, new, asbr_route);
+
+      if (al->e[0].fwd_addr.s_addr)
+	ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr);
+      return 0;
+    }
+  else
+    {
+      /* (a) Intra-area and inter-area paths are always preferred
+             over AS external paths.
+
+         (b) Type 1 external paths are always preferred over type 2
+             external paths. When all paths are type 2 external
+	     paths, the paths with the smallest advertised type 2
+	     metric are always preferred. */
+      ret = ospf_route_cmp (new, or);
+  
+  /*     (c) If the new AS external path is still indistinguishable
+             from the current paths in the N's routing table entry,
+	     and RFC1583Compatibility is set to "disabled", select
+	     the preferred paths based on the intra-AS paths to the
+	     ASBR/forwarding addresses, as specified in Section
+	     16.4.1.
+
+         (d) If the new AS external path is still indistinguishable
+             from the current paths in the N's routing table entry,
+	     select the preferred path based on a least cost
+	     comparison.  Type 1 external paths are compared by
+	     looking at the sum of the distance to the forwarding
+	     address and the advertised type 1 metric (X+Y).  Type 2
+	     external paths advertising equal type 2 metrics are
+	     compared by looking at the distance to the forwarding
+	     addresses.
+  */
+      /* New route is better */
+      if (ret < 0)
+	{
+	  zlog_info ("Route[External]: New route is better");
+	  ospf_route_subst (rn, new, asbr_route);
+	  if (al->e[0].fwd_addr.s_addr)
+	    ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr);
+	  or = new;
+	  new = NULL;
+	}
+      /* Old route is better */
+      else if (ret > 0)
+	{
+	  zlog_info ("Route[External]: Old route is better");
+	  /* do nothing */
+	}
+      /* Routes are equal */
+      else
+	{
+	  zlog_info ("Route[External]: Routes are equal");
+	  ospf_route_copy_nexthops (or, asbr_route->path);
+	  if (al->e[0].fwd_addr.s_addr)
+	    ospf_ase_complete_direct_routes (or, al->e[0].fwd_addr);
+	}
+    }
+  /* Make sure setting newly calculated ASBR route.*/
+  or->u.ext.asbr = asbr_route;
+  if (new)
+    ospf_route_free (new);
+
+  lsa->route = or;
+  return 0;
+}
+
+int
+ospf_ase_route_match_same (struct route_table *rt, struct prefix *prefix,
+			   struct ospf_route *newor)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct ospf_path *op;
+  struct ospf_path *newop;
+  listnode n1;
+  listnode n2;
+
+  if (! rt || ! prefix)
+    return 0;
+
+   rn = route_node_lookup (rt, prefix);
+   if (! rn)
+     return 0;
+ 
+   route_unlock_node (rn);
+
+   or = rn->info;
+   if (or->path_type != newor->path_type)
+     return 0;
+
+   switch (or->path_type)
+     {
+     case OSPF_PATH_TYPE1_EXTERNAL:
+       if (or->cost != newor->cost)
+	 return 0;
+       break;
+     case OSPF_PATH_TYPE2_EXTERNAL:
+       if ((or->cost != newor->cost) ||
+	   (or->u.ext.type2_cost != newor->u.ext.type2_cost))
+	 return 0;
+       break;
+     default:
+       assert (0);
+       return 0;
+     }
+   
+   if (or->path->count != newor->path->count)
+     return 0;
+       
+   /* Check each path. */
+   for (n1 = listhead (or->path), n2 = listhead (newor->path);
+	n1 && n2; nextnode (n1), nextnode (n2))
+     { 
+       op = getdata (n1);
+       newop = getdata (n2);
+       
+       if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
+	 return 0;
+     }
+   return 1;
+}
+
+int
+ospf_ase_compare_tables (struct route_table *new_external_route,
+			 struct route_table *old_external_route)
+{
+  struct route_node *rn, *new_rn;
+  struct ospf_route *or;
+  
+  /* Remove deleted routes */
+  for (rn = route_top (old_external_route); rn; rn = route_next (rn))
+    if ((or = rn->info))
+      {
+	if (! (new_rn = route_node_lookup (new_external_route, &rn->p)))
+	  ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
+	else
+	  route_unlock_node (new_rn);
+      }
+  
+	
+  /* Install new routes */
+  for (rn = route_top (new_external_route); rn; rn = route_next (rn))
+    if ((or = rn->info) != NULL)
+      if (! ospf_ase_route_match_same (old_external_route, &rn->p, or))
+	ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
+				       
+  return 0;
+}
+
+int
+ospf_ase_calculate_timer (struct thread *t)
+{
+  struct ospf *ospf;
+
+#ifdef HAVE_NSSA
+      listnode node;
+      struct ospf_area *area;
+#endif /* HAVE_NSSA */
+
+  ospf = THREAD_ARG (t);
+  ospf->t_ase_calc = NULL;
+
+  if (ospf->ase_calc)
+    {
+      ospf->ase_calc = 0;
+
+      /* Calculate external route for each AS-external-LSA */
+      foreach_lsa (EXTERNAL_LSDB (ospf_top), NULL, 0,
+		   ospf_ase_calculate_route);
+
+#ifdef HAVE_NSSA
+      /*  This version simple adds to the table all NSSA areas  */
+      if (ospf_top->anyNSSA)
+	for (node = listhead (ospf_top->areas); node; nextnode (node))
+	  {
+	    area = getdata (node);
+	    if (IS_DEBUG_OSPF_NSSA)
+	      zlog_info ("ospf_ase_calculate_timer(): looking at area %s",
+			 inet_ntoa (area->area_id));
+
+	    if (area->external_routing == OSPF_AREA_NSSA)
+
+	      foreach_lsa (NSSA_LSDB (area), NULL, 0,
+			   ospf_ase_calculate_route);
+	  }
+#endif /* HAVE_NSSA */
+
+      /* Compare old and new external routing table and install the
+	 difference info zebra/kernel */
+      ospf_ase_compare_tables (ospf_top->new_external_route,
+			       ospf_top->old_external_route);
+
+      /* Delete old external routing table */
+      ospf_route_table_free (ospf_top->old_external_route);
+      ospf_top->old_external_route = ospf_top->new_external_route;
+      ospf_top->new_external_route = route_table_init ();
+    }
+  return 0;
+}
+
+void
+ospf_ase_calculate_schedule ()
+{
+  if (! ospf_top)
+    return;
+
+  ospf_top->ase_calc = 1;
+}
+
+void
+ospf_ase_calculate_timer_add ()
+{
+  if (! ospf_top)
+    return;
+
+  if (! ospf_top->t_ase_calc)
+    ospf_top->t_ase_calc = thread_add_timer (master, ospf_ase_calculate_timer,
+					     ospf_top, OSPF_ASE_CALC_INTERVAL);
+}
+
+void
+ospf_ase_register_external_lsa (struct ospf_lsa *lsa, struct ospf *top)
+{
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+  list lst;
+  struct as_external_lsa *al;
+
+  al = (struct as_external_lsa *) lsa->data;
+  p.family = AF_INET;
+  p.prefix = lsa->data->id;
+  p.prefixlen = ip_masklen (al->mask);
+  apply_mask_ipv4 (&p);
+
+  rn = route_node_get (top->external_lsas, (struct prefix *) &p);
+  if ((lst = rn->info) == NULL)
+    rn->info = lst = list_new();
+
+  /* We assume that if LSA is deleted from DB
+     is is also deleted from this RT */
+
+  listnode_add (lst, ospf_lsa_lock (lsa));
+}
+
+void
+ospf_ase_unregister_external_lsa (struct ospf_lsa *lsa, struct ospf *top)
+{
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+  list lst;
+  struct as_external_lsa *al;
+
+  al = (struct as_external_lsa *) lsa->data;
+  p.family = AF_INET;
+  p.prefix = lsa->data->id;
+  p.prefixlen = ip_masklen (al->mask);
+  apply_mask_ipv4 (&p);
+
+  rn = route_node_get (top->external_lsas, (struct prefix *) &p);
+  lst = rn->info;
+#ifdef ORIGINAL_CODING
+  assert (lst);
+
+  listnode_delete (lst, lsa);
+  ospf_lsa_unlock (lsa);
+#else /* ORIGINAL_CODING */
+  /* XXX lst can be NULL */
+  if (lst) {
+    listnode_delete (lst, lsa);
+    ospf_lsa_unlock (lsa);
+  }
+#endif /* ORIGINAL_CODING */
+}
+
+void
+ospf_ase_external_lsas_finish (struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_lsa *lsa;
+  list lst;
+  listnode node;
+  
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((lst = rn->info) != NULL)
+      {
+	for (node = listhead (lst); node; node = nextnode (node))
+	  if ((lsa = getdata (node)) != NULL)
+	    ospf_lsa_unlock (lsa);
+	list_delete (lst);
+      }
+  
+  route_table_finish (rt);
+}
+
+void
+ospf_ase_incremental_update (struct ospf_lsa *lsa, struct ospf *top)
+{
+  list lsas;
+  listnode node;
+  struct route_node *rn, *rn2;
+  struct prefix_ipv4 p;
+  struct route_table *tmp_old;
+  struct as_external_lsa *al;
+
+  al = (struct as_external_lsa *) lsa->data;
+  p.family = AF_INET;
+  p.prefix = lsa->data->id;
+  p.prefixlen = ip_masklen (al->mask);
+  apply_mask_ipv4 (&p);
+
+  /* if new_table is NULL, there was no spf calculation, thus
+     incremental update is unneeded */
+  if (!top->new_table)
+    return;
+  
+  /* If there is already an intra-area or inter-area route
+     to the destination, no recalculation is necessary
+     (internal routes take precedence). */
+  
+  rn = route_node_lookup (top->new_table, (struct prefix *) &p);
+  if (rn && rn->info)
+    {
+      route_unlock_node (rn);
+      return;
+    }
+
+  rn = route_node_lookup (top->external_lsas, (struct prefix *) &p);
+  assert (rn && rn->info);
+  lsas = rn->info;
+  
+  for (node = listhead (lsas); node; nextnode (node))
+    if ((lsa = getdata (node)) != NULL)
+      ospf_ase_calculate_route (lsa, NULL, 0);
+
+  /* prepare temporary old routing table for compare */
+  tmp_old = route_table_init ();
+  rn = route_node_lookup (top->old_external_route, (struct prefix *) &p);
+  if (rn && rn->info)
+    {
+      rn2 = route_node_get (tmp_old, (struct prefix *) &p);
+      rn2->info = rn->info;
+    }
+
+  /* install changes to zebra */
+  ospf_ase_compare_tables (top->new_external_route, tmp_old);
+
+  /* update top->old_external_route table */
+  if (rn && rn->info)
+    ospf_route_free ((struct ospf_route *) rn->info);
+
+  rn2 = route_node_lookup (top->new_external_route, (struct prefix *) &p);
+  /* if new route exists, install it to top->old_external_route */
+  if (rn2 && rn2->info)
+    {
+      if (!rn)
+	rn = route_node_get (top->old_external_route, (struct prefix *) &p);
+      rn->info = rn2->info;
+    }
+  else
+    {
+      /* remove route node from top->old_external_route */
+      if (rn)
+	{
+	  rn->info = NULL;
+	  route_unlock_node (rn);
+	  route_unlock_node (rn);
+	}
+    }
+
+  if (rn2)
+    {
+      /* rn2->info is stored in route node of top->old_external_route */
+      rn2->info = NULL;
+      route_unlock_node (rn2);
+      route_unlock_node (rn2);
+    }
+
+  route_table_finish (tmp_old);
+}
diff --git a/ospfd/ospf_ase.h b/ospfd/ospf_ase.h
new file mode 100644
index 0000000..f403e26
--- /dev/null
+++ b/ospfd/ospf_ase.h
@@ -0,0 +1,42 @@
+/*
+ * OSPF AS External route calculation.
+ * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_ASE_H
+#define _ZEBRA_OSPF_ASE_H
+
+
+struct ospf_route *ospf_find_asbr_route (struct route_table *,
+					 struct prefix_ipv4 *);
+struct ospf_route *ospf_find_asbr_route_through_area(struct route_table *, 
+						     struct prefix_ipv4 *, 
+						     struct ospf_area *);
+
+int ospf_ase_calculate_route (struct ospf_lsa *, void *, int);
+void ospf_ase_calculate_schedule ();
+void ospf_ase_calculate_timer_add ();
+
+void ospf_ase_external_lsas_finish (struct route_table *);
+void ospf_ase_incremental_update (struct ospf_lsa *, struct ospf *);
+void ospf_ase_register_external_lsa (struct ospf_lsa *, struct ospf *);
+void ospf_ase_unregister_external_lsa (struct ospf_lsa *, struct ospf *);
+
+#endif /* _ZEBRA_OSPF_ASE_H */
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
new file mode 100644
index 0000000..da2e097
--- /dev/null
+++ b/ospfd/ospf_dump.c
@@ -0,0 +1,1673 @@
+/*
+ * OSPFd dump routine.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA. 
+ */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "thread.h"
+#include "prefix.h"
+#include "command.h"
+#include "stream.h"
+#include "log.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_network.h"
+
+struct message ospf_ism_state_msg[] =
+{
+  { ISM_DependUpon,   "DependUpon" },
+  { ISM_Down,         "Down" },
+  { ISM_Loopback,     "Loopback" },
+  { ISM_Waiting,      "Waiting" },
+  { ISM_PointToPoint, "Point-To-Point" },
+  { ISM_DROther,      "DROther" },
+  { ISM_Backup,       "Backup" },
+  { ISM_DR,           "DR" },
+};
+int ospf_ism_state_msg_max = OSPF_ISM_STATE_MAX;
+
+struct message ospf_nsm_state_msg[] =
+{
+  { NSM_DependUpon, "DependUpon" },
+  { NSM_Down,       "Down" },
+  { NSM_Attempt,    "Attempt" },
+  { NSM_Init,       "Init" },
+  { NSM_TwoWay,     "2-Way" },
+  { NSM_ExStart,    "ExStart" },
+  { NSM_Exchange,   "Exchange" },
+  { NSM_Loading,    "Loading" },
+  { NSM_Full,       "Full" },
+};
+int ospf_nsm_state_msg_max = OSPF_NSM_STATE_MAX;
+
+struct message ospf_lsa_type_msg[] =
+{
+  { OSPF_UNKNOWN_LSA,      "unknown" },
+  { OSPF_ROUTER_LSA,       "router-LSA" },
+  { OSPF_NETWORK_LSA,      "network-LSA" },
+  { OSPF_SUMMARY_LSA,      "summary-LSA" },
+  { OSPF_ASBR_SUMMARY_LSA, "summary-LSA" },
+  { OSPF_AS_EXTERNAL_LSA,  "AS-external-LSA" },
+  { OSPF_GROUP_MEMBER_LSA, "GROUP MEMBER LSA" },
+  { OSPF_AS_NSSA_LSA,      "NSSA-LSA" },
+  { 8,                     "Type-8 LSA" },
+  { OSPF_OPAQUE_LINK_LSA,  "Link-Local Opaque-LSA" },
+  { OSPF_OPAQUE_AREA_LSA,  "Area-Local Opaque-LSA" },
+  { OSPF_OPAQUE_AS_LSA,    "AS-external Opaque-LSA" },
+};
+int ospf_lsa_type_msg_max = OSPF_MAX_LSA;
+
+struct message ospf_link_state_id_type_msg[] =
+{
+  { OSPF_UNKNOWN_LSA,      "(unknown)" },
+  { OSPF_ROUTER_LSA,       "" },
+  { OSPF_NETWORK_LSA,      "(address of Designated Router)" },
+  { OSPF_SUMMARY_LSA,      "(summary Network Number)" },
+  { OSPF_ASBR_SUMMARY_LSA, "(AS Boundary Router address)" },
+  { OSPF_AS_EXTERNAL_LSA,  "(External Network Number)" },
+  { OSPF_GROUP_MEMBER_LSA, "(Group membership information)" },
+  { OSPF_AS_NSSA_LSA,      "(External Network Number for NSSA)" },
+  { 8,                     "(Type-8 LSID)" },
+  { OSPF_OPAQUE_LINK_LSA,  "(Link-Local Opaque-Type/ID)" },
+  { OSPF_OPAQUE_AREA_LSA,  "(Area-Local Opaque-Type/ID)" },
+  { OSPF_OPAQUE_AS_LSA,    "(AS-external Opaque-Type/ID)" },
+};
+int ospf_link_state_id_type_msg_max = OSPF_MAX_LSA;
+
+struct message ospf_redistributed_proto[] =
+{
+  { ZEBRA_ROUTE_SYSTEM,   "System" },
+  { ZEBRA_ROUTE_KERNEL,   "Kernel" },
+  { ZEBRA_ROUTE_CONNECT,  "Connected" },
+  { ZEBRA_ROUTE_STATIC,   "Static" },
+  { ZEBRA_ROUTE_RIP,      "RIP" },
+  { ZEBRA_ROUTE_RIPNG,    "RIPng" },
+  { ZEBRA_ROUTE_OSPF,     "OSPF" },
+  { ZEBRA_ROUTE_OSPF6,    "OSPFv3" },
+  { ZEBRA_ROUTE_BGP,      "BGP" },
+  { ZEBRA_ROUTE_MAX,	  "Default" },
+};
+int ospf_redistributed_proto_max = ZEBRA_ROUTE_MAX + 1;
+
+struct message ospf_network_type_msg[] =
+{
+  { OSPF_IFTYPE_NONE,		  "NONE" },
+  { OSPF_IFTYPE_POINTOPOINT,      "Point-to-Point" },
+  { OSPF_IFTYPE_BROADCAST,        "Broadcast" },
+  { OSPF_IFTYPE_NBMA,             "NBMA" },
+  { OSPF_IFTYPE_POINTOMULTIPOINT, "Point-to-MultiPoint" },
+  { OSPF_IFTYPE_VIRTUALLINK,      "Virtual-Link" },
+};
+int ospf_network_type_msg_max = OSPF_IFTYPE_MAX;
+
+/* Configuration debug option variables. */
+unsigned long conf_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
+unsigned long conf_debug_ospf_event = 0;
+unsigned long conf_debug_ospf_ism = 0;
+unsigned long conf_debug_ospf_nsm = 0;
+unsigned long conf_debug_ospf_lsa = 0;
+unsigned long conf_debug_ospf_zebra = 0;
+unsigned long conf_debug_ospf_nssa = 0;
+
+/* Enable debug option variables -- valid only session. */
+unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
+unsigned long term_debug_ospf_event = 0;
+unsigned long term_debug_ospf_ism = 0;
+unsigned long term_debug_ospf_nsm = 0;
+unsigned long term_debug_ospf_lsa = 0;
+unsigned long term_debug_ospf_zebra = 0;
+unsigned long term_debug_ospf_nssa = 0;
+
+
+#define OSPF_AREA_STRING_MAXLEN  16
+char *
+ospf_area_name_string (struct ospf_area *area)
+{
+  static char buf[OSPF_AREA_STRING_MAXLEN] = "";
+  u_int32_t area_id;
+
+  if (!area)
+    return "-";
+
+  area_id = ntohl (area->area_id.s_addr);
+  snprintf (buf, OSPF_AREA_STRING_MAXLEN, "%d.%d.%d.%d",
+            (area_id >> 24) & 0xff, (area_id >> 16) & 0xff,
+            (area_id >> 8) & 0xff, area_id & 0xff);
+  return buf;
+}
+
+#define OSPF_AREA_DESC_STRING_MAXLEN  23
+char *
+ospf_area_desc_string (struct ospf_area *area)
+{
+  static char buf[OSPF_AREA_DESC_STRING_MAXLEN] = "";
+  u_char type;
+
+  if (!area)
+    return "(incomplete)";
+
+  type = area->external_routing;
+  switch (type)
+    {
+    case OSPF_AREA_NSSA:
+      snprintf (buf, OSPF_AREA_DESC_STRING_MAXLEN, "%s [NSSA]",
+                ospf_area_name_string (area));
+      break;
+    case OSPF_AREA_STUB:
+      snprintf (buf, OSPF_AREA_DESC_STRING_MAXLEN, "%s [Stub]",
+                ospf_area_name_string (area));
+      break;
+    default:
+      return ospf_area_name_string (area);
+      break;
+    }
+
+  return buf;
+}
+
+#define OSPF_IF_STRING_MAXLEN  40
+char *
+ospf_if_name_string (struct ospf_interface *oi)
+{
+  static char buf[OSPF_IF_STRING_MAXLEN] = "";
+  u_int32_t ifaddr;
+
+  if (!oi)
+    return "inactive";
+
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+    return oi->ifp->name;
+
+  ifaddr = ntohl (oi->address->u.prefix4.s_addr);
+  snprintf (buf, OSPF_IF_STRING_MAXLEN,
+            "%s:%d.%d.%d.%d", oi->ifp->name,
+            (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff,
+            (ifaddr >> 8) & 0xff, ifaddr & 0xff);
+  return buf;
+}
+
+
+void
+ospf_nbr_state_message (struct ospf_neighbor *nbr, char *buf, size_t size)
+{
+  int state;
+  struct ospf_interface *oi = nbr->oi;
+
+  if (IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
+    state = ISM_DR;
+  else if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4))
+    state = ISM_Backup;
+  else
+    state = ISM_DROther;
+
+  memset (buf, 0, size);
+
+  snprintf (buf, size, "%s/%s",
+	    LOOKUP (ospf_nsm_state_msg, nbr->state),
+	    LOOKUP (ospf_ism_state_msg, state));
+}
+
+char *
+ospf_timer_dump (struct thread *t, char *buf, size_t size)
+{
+  struct timeval now;
+  unsigned long h, m, s;
+
+  if (!t)
+    return "inactive";
+
+  h = m = s = 0;
+  memset (buf, 0, size);
+
+  gettimeofday (&now, NULL);
+
+  s = t->u.sands.tv_sec - now.tv_sec;
+  if (s >= 3600)
+    {
+      h = s / 3600;
+      s -= h * 3600;
+    }
+
+  if (s >= 60)
+    {
+      m = s / 60;
+      s -= m * 60;
+    }
+
+  snprintf (buf, size, "%02ld:%02ld:%02ld", h, m, s);
+
+  return buf;
+}
+
+#define OSPF_OPTION_STR_MAXLEN		24
+
+char *
+ospf_options_dump (u_char options)
+{
+  static char buf[OSPF_OPTION_STR_MAXLEN];
+
+  snprintf (buf, OSPF_OPTION_STR_MAXLEN, "*|%s|%s|%s|%s|%s|%s|*",
+	    (options & OSPF_OPTION_O) ? "O" : "-",
+	    (options & OSPF_OPTION_DC) ? "DC" : "-",
+	    (options & OSPF_OPTION_EA) ? "EA" : "-",
+	    (options & OSPF_OPTION_NP) ? "N/P" : "-",
+	    (options & OSPF_OPTION_MC) ? "MC" : "-",
+	    (options & OSPF_OPTION_E) ? "E" : "-");
+
+  return buf;
+}
+
+void
+ospf_packet_hello_dump (struct stream *s, u_int16_t length)
+{
+  struct ospf_hello *hello;
+  int i;
+
+  hello = (struct ospf_hello *) STREAM_PNT (s);
+
+  zlog_info ("Hello");
+  zlog_info ("  NetworkMask %s", inet_ntoa (hello->network_mask));
+  zlog_info ("  HelloInterval %d", ntohs (hello->hello_interval));
+  zlog_info ("  Options %d (%s)", hello->options,
+	     ospf_options_dump (hello->options));
+  zlog_info ("  RtrPriority %d", hello->priority);
+  zlog_info ("  RtrDeadInterval %ld", (u_long)ntohl (hello->dead_interval));
+  zlog_info ("  DRouter %s", inet_ntoa (hello->d_router));
+  zlog_info ("  BDRouter %s", inet_ntoa (hello->bd_router));
+
+  length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE;
+  zlog_info ("  # Neighbors %d", length / 4);
+  for (i = 0; length > 0; i++, length -= sizeof (struct in_addr))
+    zlog_info ("    Neighbor %s", inet_ntoa (hello->neighbors[i]));
+}
+
+char *
+ospf_dd_flags_dump (u_char flags, char *buf, size_t size)
+{
+  memset (buf, 0, size);
+
+  snprintf (buf, size, "%s|%s|%s",
+	    (flags & OSPF_DD_FLAG_I) ? "I" : "-",
+	    (flags & OSPF_DD_FLAG_M) ? "M" : "-",
+	    (flags & OSPF_DD_FLAG_MS) ? "MS" : "-");
+
+  return buf;
+}
+
+void
+ospf_lsa_header_dump (struct lsa_header *lsah)
+{
+  zlog_info ("  LSA Header");
+  zlog_info ("    LS age %d", ntohs (lsah->ls_age));
+  zlog_info ("    Options %d (%s)", lsah->options,
+	     ospf_options_dump (lsah->options));
+  zlog_info ("    LS type %d (%s)", lsah->type,
+	     LOOKUP (ospf_lsa_type_msg, lsah->type));
+  zlog_info ("    Link State ID %s", inet_ntoa (lsah->id));
+  zlog_info ("    Advertising Router %s", inet_ntoa (lsah->adv_router));
+  zlog_info ("    LS sequence number 0x%lx", (u_long)ntohl (lsah->ls_seqnum));
+  zlog_info ("    LS checksum 0x%x", ntohs (lsah->checksum));
+  zlog_info ("    length %d", ntohs (lsah->length));
+}
+
+char *
+ospf_router_lsa_flags_dump (u_char flags, char *buf, size_t size)
+{
+  memset (buf, 0, size);
+
+  snprintf (buf, size, "%s|%s|%s",
+	    (flags & ROUTER_LSA_VIRTUAL) ? "V" : "-",
+	    (flags & ROUTER_LSA_EXTERNAL) ? "E" : "-",
+	    (flags & ROUTER_LSA_BORDER) ? "B" : "-");
+
+  return buf;
+}
+
+void
+ospf_router_lsa_dump (struct stream *s, u_int16_t length)
+{
+  char buf[BUFSIZ];
+  struct router_lsa *rl;
+  int i, len;
+
+  rl = (struct router_lsa *) STREAM_PNT (s);
+
+  zlog_info ("  Router-LSA");
+  zlog_info ("    flags %s", 
+	     ospf_router_lsa_flags_dump (rl->flags, buf, BUFSIZ));
+  zlog_info ("    # links %d", ntohs (rl->links));
+
+  len = ntohs (rl->header.length) - OSPF_LSA_HEADER_SIZE - 4;
+  for (i = 0; len > 0; i++)
+    {
+      zlog_info ("    Link ID %s", inet_ntoa (rl->link[i].link_id));
+      zlog_info ("    Link Data %s", inet_ntoa (rl->link[i].link_data));
+      zlog_info ("    Type %d", (u_char) rl->link[i].type);
+      zlog_info ("    TOS %d", (u_char) rl->link[i].tos);
+      zlog_info ("    metric %d", ntohs (rl->link[i].metric));
+
+      len -= 12;
+    }
+}
+
+void
+ospf_network_lsa_dump (struct stream *s, u_int16_t length)
+{
+  struct network_lsa *nl;
+  int i, cnt;
+
+  nl = (struct network_lsa *) STREAM_PNT (s);
+  cnt = (ntohs (nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
+  
+  zlog_info ("  Network-LSA");
+  /*
+  zlog_info ("LSA total size %d", ntohs (nl->header.length));
+  zlog_info ("Network-LSA size %d", 
+  ntohs (nl->header.length) - OSPF_LSA_HEADER_SIZE);
+  */
+  zlog_info ("    Network Mask %s", inet_ntoa (nl->mask));
+  zlog_info ("    # Attached Routers %d", cnt);
+  for (i = 0; i < cnt; i++)
+    zlog_info ("      Attached Router %s", inet_ntoa (nl->routers[i]));
+}
+
+void
+ospf_summary_lsa_dump (struct stream *s, u_int16_t length)
+{
+  struct summary_lsa *sl;
+  int size;
+  int i;
+
+  sl = (struct summary_lsa *) STREAM_PNT (s);
+
+  zlog_info ("  Summary-LSA");
+  zlog_info ("    Network Mask %s", inet_ntoa (sl->mask));
+
+  size = ntohs (sl->header.length) - OSPF_LSA_HEADER_SIZE - 4;
+  for (i = 0; size > 0; size -= 4, i++)
+    zlog_info ("    TOS=%d metric %d", sl->tos,
+	       GET_METRIC (sl->metric));
+}
+
+void
+ospf_as_external_lsa_dump (struct stream *s, u_int16_t length)
+{
+  struct as_external_lsa *al;
+  int size;
+  int i;
+
+  al = (struct as_external_lsa *) STREAM_PNT (s);
+
+  zlog_info ("  AS-external-LSA");
+  zlog_info ("    Network Mask %s", inet_ntoa (al->mask));
+
+  size = ntohs (al->header.length) - OSPF_LSA_HEADER_SIZE -4;
+  for (i = 0; size > 0; size -= 12, i++)
+    {
+      zlog_info ("    bit %s TOS=%d metric %d",
+		 IS_EXTERNAL_METRIC (al->e[i].tos) ? "E" : "-",
+		 al->e[i].tos & 0x7f, GET_METRIC (al->e[i].metric));
+      zlog_info ("    Forwarding address %s", inet_ntoa (al->e[i].fwd_addr));
+      zlog_info ("    External Route Tag %d", al->e[i].route_tag);
+    }
+}
+
+void
+ospf_lsa_header_list_dump (struct stream *s, u_int16_t length)
+{
+  struct lsa_header *lsa;
+
+  zlog_info ("  # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE);
+
+  /* LSA Headers. */
+  while (length > 0)
+    {
+      lsa = (struct lsa_header *) STREAM_PNT (s);
+      ospf_lsa_header_dump (lsa);
+
+      stream_forward (s, OSPF_LSA_HEADER_SIZE);
+      length -= OSPF_LSA_HEADER_SIZE;
+    }
+}
+
+void
+ospf_packet_db_desc_dump (struct stream *s, u_int16_t length)
+{
+  struct ospf_db_desc *dd;
+  char dd_flags[8];
+
+  u_int32_t gp;
+
+  gp = stream_get_getp (s);
+  dd = (struct ospf_db_desc *) STREAM_PNT (s);
+
+  zlog_info ("Database Description");
+  zlog_info ("  Interface MTU %d", ntohs (dd->mtu));
+  zlog_info ("  Options %d (%s)", dd->options,
+	     ospf_options_dump (dd->options));
+  zlog_info ("  Flags %d (%s)", dd->flags,
+	     ospf_dd_flags_dump (dd->flags, dd_flags, sizeof dd_flags));
+  zlog_info ("  Sequence Number 0x%08lx", (u_long)ntohl (dd->dd_seqnum));
+
+  length -= OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE;
+
+  stream_forward (s, OSPF_DB_DESC_MIN_SIZE);
+
+  ospf_lsa_header_list_dump (s, length);
+
+  stream_set_getp (s, gp);
+}
+
+void
+ospf_packet_ls_req_dump (struct stream *s, u_int16_t length)
+{
+  u_int32_t sp;
+  u_int32_t ls_type;
+  struct in_addr ls_id;
+  struct in_addr adv_router;
+
+  sp = stream_get_getp (s);
+
+  length -= OSPF_HEADER_SIZE;
+
+  zlog_info ("Link State Request");
+  zlog_info ("  # Requests %d", length / 12);
+
+  for (; length > 0; length -= 12)
+    {
+      ls_type = stream_getl (s);
+      ls_id.s_addr = stream_get_ipv4 (s);
+      adv_router.s_addr = stream_get_ipv4 (s);
+
+      zlog_info ("  LS type %d", ls_type);
+      zlog_info ("  Link State ID %s", inet_ntoa (ls_id));
+      zlog_info ("  Advertising Router %s",
+		 inet_ntoa (adv_router));
+    }
+
+  stream_set_getp (s, sp);
+}
+
+void
+ospf_packet_ls_upd_dump (struct stream *s, u_int16_t length)
+{
+  u_int32_t sp;
+  struct lsa_header *lsa;
+  int lsa_len;
+  u_int32_t count;
+
+  length -= OSPF_HEADER_SIZE;
+
+  sp = stream_get_getp (s);
+
+  count = stream_getl (s);
+  length -= 4;
+
+  zlog_info ("Link State Update");
+  zlog_info ("  # LSAs %d", count);
+
+  while (length > 0 && count > 0)
+    {
+      if (length < OSPF_HEADER_SIZE || length % 4 != 0)
+	{
+          zlog_info ("  Remaining %d bytes; Incorrect length.", length);
+	  break;
+	}
+
+      lsa = (struct lsa_header *) STREAM_PNT (s);
+      lsa_len = ntohs (lsa->length);
+      ospf_lsa_header_dump (lsa);
+
+      switch (lsa->type)
+	{
+	case OSPF_ROUTER_LSA:
+	  ospf_router_lsa_dump (s, length);
+	  break;
+	case OSPF_NETWORK_LSA:
+	  ospf_network_lsa_dump (s, length);
+	  break;
+	case OSPF_SUMMARY_LSA:
+	case OSPF_ASBR_SUMMARY_LSA:
+	  ospf_summary_lsa_dump (s, length);
+	  break;
+	case OSPF_AS_EXTERNAL_LSA:
+	  ospf_as_external_lsa_dump (s, length);
+	  break;
+#ifdef HAVE_NSSA
+	case OSPF_AS_NSSA_LSA:
+	  /* XXX */
+	  break;
+#endif /* HAVE_NSSA */
+#ifdef HAVE_OPAQUE_LSA
+	case OSPF_OPAQUE_LINK_LSA:
+	case OSPF_OPAQUE_AREA_LSA:
+	case OSPF_OPAQUE_AS_LSA:
+	  ospf_opaque_lsa_dump (s, length);
+	  break;
+#endif /* HAVE_OPAQUE_LSA */
+	default:
+	  break;
+	}
+
+      stream_forward (s, lsa_len);
+      length -= lsa_len;
+      count--;
+    }
+
+  stream_set_getp (s, sp);
+}
+
+void
+ospf_packet_ls_ack_dump (struct stream *s, u_int16_t length)
+{
+  u_int32_t sp;
+
+  length -= OSPF_HEADER_SIZE;
+  sp = stream_get_getp (s);
+
+  zlog_info ("Link State Acknowledgment");
+  ospf_lsa_header_list_dump (s, length);
+
+  stream_set_getp (s, sp);
+}
+
+void
+ospf_ip_header_dump (struct stream *s)
+{
+  u_int16_t length;
+  struct ip *iph;
+
+  iph = (struct ip *) STREAM_PNT (s);
+
+#ifdef GNU_LINUX
+  length = ntohs (iph->ip_len);
+#else /* GNU_LINUX */
+  length = iph->ip_len;
+#endif /* GNU_LINUX */
+
+  /* IP Header dump. */
+  zlog_info ("ip_v %d", iph->ip_v);
+  zlog_info ("ip_hl %d", iph->ip_hl);
+  zlog_info ("ip_tos %d", iph->ip_tos);
+  zlog_info ("ip_len %d", length);
+  zlog_info ("ip_id %u", (u_int32_t) iph->ip_id);
+  zlog_info ("ip_off %u", (u_int32_t) iph->ip_off);
+  zlog_info ("ip_ttl %d", iph->ip_ttl);
+  zlog_info ("ip_p %d", iph->ip_p);
+  /* There is a report that Linux 2.0.37 does not have ip_sum.  But
+     I'm not sure.  Temporary commented out by kunihiro. */
+  /* zlog_info ("ip_sum 0x%x", (u_int32_t) ntohs (iph->ip_sum)); */
+  zlog_info ("ip_src %s",  inet_ntoa (iph->ip_src));
+  zlog_info ("ip_dst %s", inet_ntoa (iph->ip_dst));
+}
+
+void
+ospf_header_dump (struct ospf_header *ospfh)
+{
+  char buf[9];
+
+  zlog_info ("Header");
+  zlog_info ("  Version %d", ospfh->version);
+  zlog_info ("  Type %d (%s)", ospfh->type,
+	     ospf_packet_type_str[ospfh->type]);
+  zlog_info ("  Packet Len %d", ntohs (ospfh->length));
+  zlog_info ("  Router ID %s", inet_ntoa (ospfh->router_id));
+  zlog_info ("  Area ID %s", inet_ntoa (ospfh->area_id));
+  zlog_info ("  Checksum 0x%x", ntohs (ospfh->checksum));
+  zlog_info ("  AuType %d", ntohs (ospfh->auth_type));
+
+  switch (ntohs (ospfh->auth_type))
+    {
+    case OSPF_AUTH_NULL:
+      break;
+    case OSPF_AUTH_SIMPLE:
+      memset (buf, 0, 9);
+      strncpy (buf, ospfh->u.auth_data, 8);
+      zlog_info ("  Simple Password %s", buf);
+      break;
+    case OSPF_AUTH_CRYPTOGRAPHIC:
+      zlog_info ("  Cryptographic Authentication");
+      zlog_info ("  Key ID %d", ospfh->u.crypt.key_id);
+      zlog_info ("  Auth Data Len %d", ospfh->u.crypt.auth_data_len);
+      zlog_info ("  Sequence number %ld",
+		 (u_long)ntohl (ospfh->u.crypt.crypt_seqnum));
+      break;
+    default:
+      zlog_info ("* This is not supported authentication type");
+      break;
+    }
+    
+}
+
+void
+ospf_packet_dump (struct stream *s)
+{
+  struct ospf_header *ospfh;
+  unsigned long gp;
+
+  /* Preserve pointer. */
+  gp = stream_get_getp (s);
+
+  /* OSPF Header dump. */
+  ospfh = (struct ospf_header *) STREAM_PNT (s);
+
+  /* Until detail flag is set, return. */
+  if (!(term_debug_ospf_packet[ospfh->type - 1] & OSPF_DEBUG_DETAIL))
+    return;
+
+  /* Show OSPF header detail. */
+  ospf_header_dump (ospfh);
+  stream_forward (s, OSPF_HEADER_SIZE);
+
+  switch (ospfh->type)
+    {
+    case OSPF_MSG_HELLO:
+      ospf_packet_hello_dump (s, ntohs (ospfh->length));
+      break;
+    case OSPF_MSG_DB_DESC:
+      ospf_packet_db_desc_dump (s, ntohs (ospfh->length));
+      break;
+    case OSPF_MSG_LS_REQ:
+      ospf_packet_ls_req_dump (s, ntohs (ospfh->length));
+      break;
+    case OSPF_MSG_LS_UPD:
+      ospf_packet_ls_upd_dump (s, ntohs (ospfh->length));
+      break;
+    case OSPF_MSG_LS_ACK:
+      ospf_packet_ls_ack_dump (s, ntohs (ospfh->length));
+      break;
+    default:
+      break;
+    }
+
+  stream_set_getp (s, gp);
+}
+
+
+/*
+   [no] debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all)
+                          [send|recv [detail]]
+*/
+DEFUN (debug_ospf_packet,
+       debug_ospf_packet_all_cmd,
+       "debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all)",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF packets\n"
+       "OSPF Hello\n"
+       "OSPF Database Description\n"
+       "OSPF Link State Request\n"
+       "OSPF Link State Update\n"
+       "OSPF Link State Acknowledgment\n"
+       "OSPF all packets\n")
+{
+  int type = 0;
+  int flag = 0;
+  int i;
+
+  assert (argc > 0);
+
+  /* Check packet type. */
+  if (strncmp (argv[0], "h", 1) == 0)
+    type = OSPF_DEBUG_HELLO;
+  else if (strncmp (argv[0], "d", 1) == 0)
+    type = OSPF_DEBUG_DB_DESC;
+  else if (strncmp (argv[0], "ls-r", 4) == 0)
+    type = OSPF_DEBUG_LS_REQ;
+  else if (strncmp (argv[0], "ls-u", 4) == 0)
+    type = OSPF_DEBUG_LS_UPD;
+  else if (strncmp (argv[0], "ls-a", 4) == 0)
+    type = OSPF_DEBUG_LS_ACK;
+  else if (strncmp (argv[0], "a", 1) == 0)
+    type = OSPF_DEBUG_ALL;
+
+  /* Default, both send and recv. */
+  if (argc == 1)
+    flag = OSPF_DEBUG_SEND | OSPF_DEBUG_RECV;
+
+  /* send or recv. */
+  if (argc >= 2)
+    {
+      if (strncmp (argv[1], "s", 1) == 0)
+	flag = OSPF_DEBUG_SEND;
+      else if (strncmp (argv[1], "r", 1) == 0)
+	flag = OSPF_DEBUG_RECV;
+      else if (strncmp (argv[1], "d", 1) == 0)
+	flag = OSPF_DEBUG_SEND | OSPF_DEBUG_RECV | OSPF_DEBUG_DETAIL;
+    }
+
+  /* detail. */
+  if (argc == 3)
+    if (strncmp (argv[2], "d", 1) == 0)
+      flag |= OSPF_DEBUG_DETAIL;
+
+  for (i = 0; i < 5; i++)
+    if (type & (0x01 << i))
+      {
+	if (vty->node == CONFIG_NODE)
+	  DEBUG_PACKET_ON (i, flag);
+	else
+	  TERM_DEBUG_PACKET_ON (i, flag);
+      }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf_packet,
+       debug_ospf_packet_send_recv_cmd,
+       "debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv|detail)",
+       "Debugging functions\n"
+       "OSPF information\n"
+       "OSPF packets\n"
+       "OSPF Hello\n"
+       "OSPF Database Description\n"
+       "OSPF Link State Request\n"
+       "OSPF Link State Update\n"
+       "OSPF Link State Acknowledgment\n"
+       "OSPF all packets\n"
+       "Packet sent\n"
+       "Packet received\n"
+       "Detail information\n")
+
+ALIAS (debug_ospf_packet,
+       debug_ospf_packet_send_recv_detail_cmd,
+       "debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) (detail|)",
+       "Debugging functions\n"
+       "OSPF information\n"
+       "OSPF packets\n"
+       "OSPF Hello\n"
+       "OSPF Database Description\n"
+       "OSPF Link State Request\n"
+       "OSPF Link State Update\n"
+       "OSPF Link State Acknowledgment\n"
+       "OSPF all packets\n"
+       "Packet sent\n"
+       "Packet received\n"
+       "Detail Information\n")
+       
+
+DEFUN (no_debug_ospf_packet,
+       no_debug_ospf_packet_all_cmd,
+       "no debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all)",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF packets\n"
+       "OSPF Hello\n"
+       "OSPF Database Description\n"
+       "OSPF Link State Request\n"
+       "OSPF Link State Update\n"
+       "OSPF Link State Acknowledgment\n"
+       "OSPF all packets\n")
+{
+  int type = 0;
+  int flag = 0;
+  int i;
+
+  assert (argc > 0);
+
+  /* Check packet type. */
+  if (strncmp (argv[0], "h", 1) == 0)
+    type = OSPF_DEBUG_HELLO;
+  else if (strncmp (argv[0], "d", 1) == 0)
+    type = OSPF_DEBUG_DB_DESC;
+  else if (strncmp (argv[0], "ls-r", 4) == 0)
+    type = OSPF_DEBUG_LS_REQ;
+  else if (strncmp (argv[0], "ls-u", 4) == 0)
+    type = OSPF_DEBUG_LS_UPD;
+  else if (strncmp (argv[0], "ls-a", 4) == 0)
+    type = OSPF_DEBUG_LS_ACK;
+  else if (strncmp (argv[0], "a", 1) == 0)
+    type = OSPF_DEBUG_ALL;
+
+  /* Default, both send and recv. */
+  if (argc == 1)
+    flag = OSPF_DEBUG_SEND | OSPF_DEBUG_RECV | OSPF_DEBUG_DETAIL ;
+
+  /* send or recv. */
+  if (argc == 2)
+    {
+      if (strncmp (argv[1], "s", 1) == 0)
+	flag = OSPF_DEBUG_SEND | OSPF_DEBUG_DETAIL;
+      else if (strncmp (argv[1], "r", 1) == 0)
+	flag = OSPF_DEBUG_RECV | OSPF_DEBUG_DETAIL;
+      else if (strncmp (argv[1], "d", 1) == 0)
+	flag = OSPF_DEBUG_DETAIL;
+    }
+
+  /* detail. */
+  if (argc == 3)
+    if (strncmp (argv[2], "d", 1) == 0)
+      flag = OSPF_DEBUG_DETAIL;
+
+  for (i = 0; i < 5; i++)
+    if (type & (0x01 << i))
+      {
+	if (vty->node == CONFIG_NODE)
+	  DEBUG_PACKET_OFF (i, flag);
+	else
+	  TERM_DEBUG_PACKET_OFF (i, flag);
+      }
+
+#ifdef DEBUG
+  for (i = 0; i < 5; i++)
+    zlog_info ("flag[%d] = %d", i, ospf_debug_packet[i]);
+#endif /* DEBUG */
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf_packet,
+       no_debug_ospf_packet_send_recv_cmd,
+       "no debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv|detail)",
+       NO_STR
+       "Debugging functions\n"
+       "OSPF information\n"
+       "OSPF packets\n"
+       "OSPF Hello\n"
+       "OSPF Database Description\n"
+       "OSPF Link State Request\n"
+       "OSPF Link State Update\n"
+       "OSPF Link State Acknowledgment\n"
+       "OSPF all packets\n"
+       "Packet sent\n"
+       "Packet received\n"
+       "Detail Information\n")
+
+ALIAS (no_debug_ospf_packet,
+       no_debug_ospf_packet_send_recv_detail_cmd,
+       "no debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) (detail|)",
+       NO_STR
+       "Debugging functions\n"
+       "OSPF information\n"
+       "OSPF packets\n"
+       "OSPF Hello\n"
+       "OSPF Database Description\n"
+       "OSPF Link State Request\n"
+       "OSPF Link State Update\n"
+       "OSPF Link State Acknowledgment\n"
+       "OSPF all packets\n"
+       "Packet sent\n"
+       "Packet received\n"
+       "Detail Information\n")
+
+
+DEFUN (debug_ospf_ism,
+       debug_ospf_ism_cmd,
+       "debug ospf ism",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Interface State Machine\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_ON (ism, ISM);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "s", 1) == 0)
+	    DEBUG_ON (ism, ISM_STATUS);
+	  else if (strncmp (argv[0], "e", 1) == 0)
+	    DEBUG_ON (ism, ISM_EVENTS);
+	  else if (strncmp (argv[0], "t", 1) == 0)
+	    DEBUG_ON (ism, ISM_TIMERS);
+	}
+
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_ON (ism, ISM);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "s", 1) == 0)
+	TERM_DEBUG_ON (ism, ISM_STATUS);
+      else if (strncmp (argv[0], "e", 1) == 0)
+	TERM_DEBUG_ON (ism, ISM_EVENTS);
+      else if (strncmp (argv[0], "t", 1) == 0)
+	TERM_DEBUG_ON (ism, ISM_TIMERS);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf_ism,
+       debug_ospf_ism_sub_cmd,
+       "debug ospf ism (status|events|timers)",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Interface State Machine\n"
+       "ISM Status Information\n"
+       "ISM Event Information\n"
+       "ISM TImer Information\n")
+
+DEFUN (no_debug_ospf_ism,
+       no_debug_ospf_ism_cmd,
+       "no debug ospf ism",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Interface State Machine")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_OFF (ism, ISM);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "s", 1) == 0)
+	    DEBUG_OFF (ism, ISM_STATUS);
+	  else if (strncmp (argv[0], "e", 1) == 0)
+	    DEBUG_OFF (ism, ISM_EVENTS);
+	  else if (strncmp (argv[0], "t", 1) == 0)
+	    DEBUG_OFF (ism, ISM_TIMERS);
+	}
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_OFF (ism, ISM);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "s", 1) == 0)
+	TERM_DEBUG_OFF (ism, ISM_STATUS);
+      else if (strncmp (argv[0], "e", 1) == 0)
+	TERM_DEBUG_OFF (ism, ISM_EVENTS);
+      else if (strncmp (argv[0], "t", 1) == 0)
+	TERM_DEBUG_OFF (ism, ISM_TIMERS);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf_ism,
+       no_debug_ospf_ism_sub_cmd,
+       "no debug ospf ism (status|events|timers)",
+       NO_STR
+       "Debugging functions\n"
+       "OSPF information\n"
+       "OSPF Interface State Machine\n"
+       "ISM Status Information\n"
+       "ISM Event Information\n"
+       "ISM Timer Information\n")
+
+
+DEFUN (debug_ospf_nsm,
+       debug_ospf_nsm_cmd,
+       "debug ospf nsm",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Neighbor State Machine\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_ON (nsm, NSM);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "s", 1) == 0)
+	    DEBUG_ON (nsm, NSM_STATUS);
+	  else if (strncmp (argv[0], "e", 1) == 0)
+	    DEBUG_ON (nsm, NSM_EVENTS);
+	  else if (strncmp (argv[0], "t", 1) == 0)
+	    DEBUG_ON (nsm, NSM_TIMERS);
+	}
+
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_ON (nsm, NSM);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "s", 1) == 0)
+	TERM_DEBUG_ON (nsm, NSM_STATUS);
+      else if (strncmp (argv[0], "e", 1) == 0)
+	TERM_DEBUG_ON (nsm, NSM_EVENTS);
+      else if (strncmp (argv[0], "t", 1) == 0)
+	TERM_DEBUG_ON (nsm, NSM_TIMERS);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf_nsm,
+       debug_ospf_nsm_sub_cmd,
+       "debug ospf nsm (status|events|timers)",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Neighbor State Machine\n"
+       "NSM Status Information\n"
+       "NSM Event Information\n"
+       "NSM Timer Information\n")
+
+DEFUN (no_debug_ospf_nsm,
+       no_debug_ospf_nsm_cmd,
+       "no debug ospf nsm",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Neighbor State Machine")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_OFF (nsm, NSM);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "s", 1) == 0)
+	    DEBUG_OFF (nsm, NSM_STATUS);
+	  else if (strncmp (argv[0], "e", 1) == 0)
+	    DEBUG_OFF (nsm, NSM_EVENTS);
+	  else if (strncmp (argv[0], "t", 1) == 0)
+	    DEBUG_OFF (nsm, NSM_TIMERS);
+	}
+
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_OFF (nsm, NSM);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "s", 1) == 0)
+	TERM_DEBUG_OFF (nsm, NSM_STATUS);
+      else if (strncmp (argv[0], "e", 1) == 0)
+	TERM_DEBUG_OFF (nsm, NSM_EVENTS);
+      else if (strncmp (argv[0], "t", 1) == 0)
+	TERM_DEBUG_OFF (nsm, NSM_TIMERS);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf_nsm,
+       no_debug_ospf_nsm_sub_cmd,
+       "no debug ospf nsm (status|events|timers)",
+       NO_STR
+       "Debugging functions\n"
+       "OSPF information\n"
+       "OSPF Interface State Machine\n"
+       "NSM Status Information\n"
+       "NSM Event Information\n"
+       "NSM Timer Information\n")
+
+
+DEFUN (debug_ospf_lsa,
+       debug_ospf_lsa_cmd,
+       "debug ospf lsa",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Link State Advertisement\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_ON (lsa, LSA);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "g", 1) == 0)
+	    DEBUG_ON (lsa, LSA_GENERATE);
+	  else if (strncmp (argv[0], "f", 1) == 0)
+	    DEBUG_ON (lsa, LSA_FLOODING);
+	  else if (strncmp (argv[0], "i", 1) == 0)
+	    DEBUG_ON (lsa, LSA_INSTALL);
+	  else if (strncmp (argv[0], "r", 1) == 0)
+	    DEBUG_ON (lsa, LSA_REFRESH);
+	}
+
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_ON (lsa, LSA);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "g", 1) == 0)
+	TERM_DEBUG_ON (lsa, LSA_GENERATE);
+      else if (strncmp (argv[0], "f", 1) == 0)
+	TERM_DEBUG_ON (lsa, LSA_FLOODING);
+      else if (strncmp (argv[0], "i", 1) == 0)
+	TERM_DEBUG_ON (lsa, LSA_INSTALL);
+      else if (strncmp (argv[0], "r", 1) == 0)
+	TERM_DEBUG_ON (lsa, LSA_REFRESH);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf_lsa,
+       debug_ospf_lsa_sub_cmd,
+       "debug ospf lsa (generate|flooding|install|refresh)",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Link State Advertisement\n"
+       "LSA Generation\n"
+       "LSA Flooding\n"
+       "LSA Install/Delete\n"
+       "LSA Refresh\n")
+
+DEFUN (no_debug_ospf_lsa,
+       no_debug_ospf_lsa_cmd,
+       "no debug ospf lsa",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Link State Advertisement\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_OFF (lsa, LSA);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "g", 1) == 0)
+	    DEBUG_OFF (lsa, LSA_GENERATE);
+	  else if (strncmp (argv[0], "f", 1) == 0)
+	    DEBUG_OFF (lsa, LSA_FLOODING);
+	  else if (strncmp (argv[0], "i", 1) == 0)
+	    DEBUG_OFF (lsa, LSA_INSTALL);
+	  else if (strncmp (argv[0], "r", 1) == 0)
+	    DEBUG_OFF (lsa, LSA_REFRESH);
+	}
+
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_OFF (lsa, LSA);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "g", 1) == 0)
+	TERM_DEBUG_OFF (lsa, LSA_GENERATE);
+      else if (strncmp (argv[0], "f", 1) == 0)
+	TERM_DEBUG_OFF (lsa, LSA_FLOODING);
+      else if (strncmp (argv[0], "i", 1) == 0)
+	TERM_DEBUG_OFF (lsa, LSA_INSTALL);
+      else if (strncmp (argv[0], "r", 1) == 0)
+	TERM_DEBUG_OFF (lsa, LSA_REFRESH);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf_lsa,
+       no_debug_ospf_lsa_sub_cmd,
+       "no debug ospf lsa (generate|flooding|install|refresh)",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Link State Advertisement\n"
+       "LSA Generation\n"
+       "LSA Flooding\n"
+       "LSA Install/Delete\n"
+       "LSA Refres\n")
+
+
+DEFUN (debug_ospf_zebra,
+       debug_ospf_zebra_cmd,
+       "debug ospf zebra",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Zebra information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_ON (zebra, ZEBRA);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "i", 1) == 0)
+	    DEBUG_ON (zebra, ZEBRA_INTERFACE);
+	  else if (strncmp (argv[0], "r", 1) == 0)
+	    DEBUG_ON (zebra, ZEBRA_REDISTRIBUTE);
+	}
+
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_ON (zebra, ZEBRA);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "i", 1) == 0)
+	TERM_DEBUG_ON (zebra, ZEBRA_INTERFACE);
+      else if (strncmp (argv[0], "r", 1) == 0)
+	TERM_DEBUG_ON (zebra, ZEBRA_REDISTRIBUTE);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf_zebra,
+       debug_ospf_zebra_sub_cmd,
+       "debug ospf zebra (interface|redistribute)",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Zebra information\n"
+       "Zebra interface\n"
+       "Zebra redistribute\n")
+
+DEFUN (no_debug_ospf_zebra,
+       no_debug_ospf_zebra_cmd,
+       "no debug ospf zebra",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Zebra information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (argc == 0)
+	DEBUG_OFF (zebra, ZEBRA);
+      else if (argc == 1)
+	{
+	  if (strncmp (argv[0], "i", 1) == 0)
+	    DEBUG_OFF (zebra, ZEBRA_INTERFACE);
+	  else if (strncmp (argv[0], "r", 1) == 0)
+	    DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE);
+	}
+
+      return CMD_SUCCESS;
+    }
+
+  /* ENABLE_NODE. */
+  if (argc == 0)
+    TERM_DEBUG_OFF (zebra, ZEBRA);
+  else if (argc == 1)
+    {
+      if (strncmp (argv[0], "i", 1) == 0)
+	TERM_DEBUG_OFF (zebra, ZEBRA_INTERFACE);
+      else if (strncmp (argv[0], "r", 1) == 0)
+	TERM_DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf_zebra,
+       no_debug_ospf_zebra_sub_cmd,
+       "no debug ospf zebra (interface|redistribute)",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF Zebra information\n"
+       "Zebra interface\n"
+       "Zebra redistribute\n")
+
+DEFUN (debug_ospf_event,
+       debug_ospf_event_cmd,
+       "debug ospf event",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF event information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    CONF_DEBUG_ON (event, EVENT);
+  TERM_DEBUG_ON (event, EVENT);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf_event,
+       no_debug_ospf_event_cmd,
+       "no debug ospf event",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF event information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    CONF_DEBUG_OFF (event, EVENT);
+  TERM_DEBUG_OFF (event, EVENT);
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_ospf_nssa,
+       debug_ospf_nssa_cmd,
+       "debug ospf nssa",
+       DEBUG_STR
+       OSPF_STR
+       "OSPF nssa information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    CONF_DEBUG_ON (nssa, NSSA);
+  TERM_DEBUG_ON (nssa, NSSA);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf_nssa,
+       no_debug_ospf_nssa_cmd,
+       "no debug ospf nssa",
+       NO_STR
+       DEBUG_STR
+       OSPF_STR
+       "OSPF nssa information\n")
+{
+  if (vty->node == CONFIG_NODE)
+    CONF_DEBUG_OFF (nssa, NSSA);
+  TERM_DEBUG_OFF (nssa, NSSA);
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (show_debugging_ospf,
+       show_debugging_ospf_cmd,
+       "show debugging ospf",
+       SHOW_STR
+       DEBUG_STR
+       OSPF_STR)
+{
+  int i;
+
+  vty_out (vty, "Zebra debugging status:%s", VTY_NEWLINE);
+
+  /* Show debug status for ISM. */
+  if (IS_DEBUG_OSPF (ism, ISM) == OSPF_DEBUG_ISM)
+    vty_out (vty, "  OSPF ISM debugging is on%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_DEBUG_OSPF (ism, ISM_STATUS))
+	vty_out (vty, "  OSPF ISM status debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
+	vty_out (vty, "  OSPF ISM event debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (ism, ISM_TIMERS))
+	vty_out (vty, "  OSPF ISM timer debugging is on%s", VTY_NEWLINE);
+    }
+
+  /* Show debug status for NSM. */
+  if (IS_DEBUG_OSPF (nsm, NSM) == OSPF_DEBUG_NSM)
+    vty_out (vty, "  OSPF NSM debugging is on%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_DEBUG_OSPF (nsm, NSM_STATUS))
+	vty_out (vty, "  OSPF NSM status debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
+	vty_out (vty, "  OSPF NSM event debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
+	vty_out (vty, "  OSPF NSM timer debugging is on%s", VTY_NEWLINE);
+    }
+
+  /* Show debug status for OSPF Packets. */
+  for (i = 0; i < 5; i++)
+    if (IS_DEBUG_OSPF_PACKET (i, SEND) && IS_DEBUG_OSPF_PACKET (i, RECV))
+      {
+	vty_out (vty, "  OSPF packet %s%s debugging is on%s",
+		 ospf_packet_type_str[i + 1],
+		 IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
+		 VTY_NEWLINE);
+      }
+    else
+      {
+	if (IS_DEBUG_OSPF_PACKET (i, SEND))
+	  vty_out (vty, "  OSPF packet %s send%s debugging is on%s",
+		   ospf_packet_type_str[i + 1],
+		   IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
+		   VTY_NEWLINE);
+	if (IS_DEBUG_OSPF_PACKET (i, RECV))
+	  vty_out (vty, "  OSPF packet %s receive%s debugging is on%s",
+		   ospf_packet_type_str[i + 1],
+		   IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
+		   VTY_NEWLINE);
+      }
+
+  /* Show debug status for OSPF LSAs. */
+  if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
+    vty_out (vty, "  OSPF LSA debugging is on%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+	vty_out (vty, "  OSPF LSA generation debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+	vty_out (vty, "  OSPF LSA flooding debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
+	vty_out (vty, "  OSPF LSA install debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+	vty_out (vty, "  OSPF LSA refresh debugging is on%s", VTY_NEWLINE);
+    }
+
+  /* Show debug status for Zebra. */
+  if (IS_DEBUG_OSPF (zebra, ZEBRA) == OSPF_DEBUG_ZEBRA)
+    vty_out (vty, "  OSPF Zebra debugging is on%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+	vty_out (vty, "  OSPF Zebra interface debugging is on%s", VTY_NEWLINE);
+      if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	vty_out (vty, "  OSPF Zebra redistribute debugging is on%s", VTY_NEWLINE);
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* Debug node. */
+struct cmd_node debug_node =
+{
+  DEBUG_NODE,
+  ""
+};
+
+int
+config_write_debug (struct vty *vty)
+{
+  int write = 0;
+  int i, r;
+
+  char *type_str[] = {"hello", "dd", "ls-request", "ls-update", "ls-ack"};
+  char *detail_str[] = {"", " send", " recv", "", " detail",
+			" send detail", " recv detail", " detail"};
+
+  /* debug ospf ism (status|events|timers). */
+  if (IS_CONF_DEBUG_OSPF (ism, ISM) == OSPF_DEBUG_ISM)
+    vty_out (vty, "debug ospf ism%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_CONF_DEBUG_OSPF (ism, ISM_STATUS))
+	vty_out (vty, "debug ospf ism status%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (ism, ISM_EVENTS))
+	vty_out (vty, "debug ospf ism event%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (ism, ISM_TIMERS))
+	vty_out (vty, "debug ospf ism timer%s", VTY_NEWLINE);
+    }
+
+  /* debug ospf nsm (status|events|timers). */
+  if (IS_CONF_DEBUG_OSPF (nsm, NSM) == OSPF_DEBUG_NSM)
+    vty_out (vty, "debug ospf nsm%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_CONF_DEBUG_OSPF (nsm, NSM_STATUS))
+	vty_out (vty, "debug ospf ism status%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (nsm, NSM_EVENTS))
+	vty_out (vty, "debug ospf nsm event%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (nsm, NSM_TIMERS))
+	vty_out (vty, "debug ospf nsm timer%s", VTY_NEWLINE);
+    }
+
+  /* debug ospf lsa (generate|flooding|install|refresh). */
+  if (IS_CONF_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
+    vty_out (vty, "debug ospf lsa%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_CONF_DEBUG_OSPF (lsa, LSA_GENERATE))
+	vty_out (vty, "debug ospf lsa generate%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (lsa, LSA_FLOODING))
+	vty_out (vty, "debug ospf lsa flooding%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (lsa, LSA_INSTALL))
+	vty_out (vty, "debug ospf lsa install%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (lsa, LSA_REFRESH))
+	vty_out (vty, "debug ospf lsa refresh%s", VTY_NEWLINE);
+
+      write = 1;
+    }
+
+  /* debug ospf zebra (interface|redistribute). */
+  if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA) == OSPF_DEBUG_ZEBRA)
+    vty_out (vty, "debug ospf zebra%s", VTY_NEWLINE);
+  else
+    {
+      if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+	vty_out (vty, "debug ospf zebra interface%s", VTY_NEWLINE);
+      if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	vty_out (vty, "debug ospf zebra redistribute%s", VTY_NEWLINE);
+
+      write = 1;
+    }
+
+  /* debug ospf event. */
+  if (IS_CONF_DEBUG_OSPF (event, EVENT) == OSPF_DEBUG_EVENT)
+    {
+      vty_out (vty, "debug ospf event%s", VTY_NEWLINE);
+      write = 1;
+    }
+
+  /* debug ospf nssa. */
+  if (IS_CONF_DEBUG_OSPF (nssa, NSSA) == OSPF_DEBUG_NSSA)
+    {
+      vty_out (vty, "debug ospf nssa%s", VTY_NEWLINE);
+      write = 1;
+    }
+  
+  /* debug ospf packet all detail. */
+  r = OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL;
+  for (i = 0; i < 5; i++)
+    r &= conf_debug_ospf_packet[i] & (OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL);
+  if (r == (OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL))
+    {
+      vty_out (vty, "debug ospf packet all detail%s", VTY_NEWLINE);
+      return 1;
+    }
+
+  /* debug ospf packet all. */
+  r = OSPF_DEBUG_SEND_RECV;
+  for (i = 0; i < 5; i++)
+    r &= conf_debug_ospf_packet[i] & OSPF_DEBUG_SEND_RECV;
+  if (r == OSPF_DEBUG_SEND_RECV)
+    {
+      vty_out (vty, "debug ospf packet all%s", VTY_NEWLINE);
+      for (i = 0; i < 5; i++)
+	if (conf_debug_ospf_packet[i] & OSPF_DEBUG_DETAIL)
+	  vty_out (vty, "debug ospf packet %s detail%s",
+		   type_str[i],
+		   VTY_NEWLINE);
+      return 1;
+    }
+
+  /* debug ospf packet (hello|dd|ls-request|ls-update|ls-ack)
+     (send|recv) (detail). */
+  for (i = 0; i < 5; i++)
+    {
+      if (conf_debug_ospf_packet[i] == 0)
+	continue;
+      
+      vty_out (vty, "debug ospf packet %s%s%s",
+	       type_str[i], detail_str[conf_debug_ospf_packet[i]],
+	       VTY_NEWLINE);
+      write = 1;
+    }
+
+  return write;
+}
+
+/* Initialize debug commands. */
+void
+debug_init ()
+{
+  install_node (&debug_node, config_write_debug);
+
+  install_element (ENABLE_NODE, &show_debugging_ospf_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_packet_send_recv_detail_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_packet_send_recv_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_packet_all_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_ism_sub_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_ism_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_nsm_sub_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_nsm_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_lsa_sub_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_lsa_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_zebra_sub_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_zebra_cmd);
+  install_element (ENABLE_NODE, &debug_ospf_event_cmd);
+#ifdef HAVE_NSSA
+  install_element (ENABLE_NODE, &debug_ospf_nssa_cmd);
+#endif /* HAVE_NSSA */
+  install_element (ENABLE_NODE, &no_debug_ospf_packet_send_recv_detail_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_packet_send_recv_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_packet_all_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_ism_sub_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_ism_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_nsm_sub_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_nsm_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_lsa_sub_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_lsa_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_zebra_sub_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_zebra_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf_event_cmd);
+#ifdef HAVE_NSSA
+  install_element (ENABLE_NODE, &no_debug_ospf_nssa_cmd);
+#endif /* HAVE_NSSA */
+
+  install_element (CONFIG_NODE, &debug_ospf_packet_send_recv_detail_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_packet_send_recv_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_packet_all_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_ism_sub_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_ism_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_nsm_sub_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_nsm_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_lsa_sub_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_lsa_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_zebra_sub_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_zebra_cmd);
+  install_element (CONFIG_NODE, &debug_ospf_event_cmd);
+#ifdef HAVE_NSSA
+  install_element (CONFIG_NODE, &debug_ospf_nssa_cmd);
+#endif /* HAVE_NSSA */
+  install_element (CONFIG_NODE, &no_debug_ospf_packet_send_recv_detail_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_packet_send_recv_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_packet_all_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_ism_sub_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_ism_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_nsm_sub_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_nsm_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_lsa_sub_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_lsa_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_zebra_sub_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_zebra_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf_event_cmd);
+#ifdef HAVE_NSSA
+  install_element (CONFIG_NODE, &no_debug_ospf_nssa_cmd);
+#endif /* HAVE_NSSA */
+}
diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h
new file mode 100644
index 0000000..804d5f7
--- /dev/null
+++ b/ospfd/ospf_dump.h
@@ -0,0 +1,139 @@
+/*
+ * OSPFd dump routine.
+ * Copyright (C) 1999 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA. 
+ */
+
+#ifndef _ZEBRA_OSPF_DUMP_H
+#define _ZEBRA_OSPF_DUMP_H
+
+/* Debug Flags. */
+#define OSPF_DEBUG_HELLO	0x01
+#define OSPF_DEBUG_DB_DESC	0x02
+#define OSPF_DEBUG_LS_REQ	0x04
+#define OSPF_DEBUG_LS_UPD	0x08
+#define OSPF_DEBUG_LS_ACK	0x10
+#define OSPF_DEBUG_ALL		0x1f
+
+#define OSPF_DEBUG_SEND		0x01
+#define OSPF_DEBUG_RECV		0x02
+#define OSPF_DEBUG_SEND_RECV    0x03
+#define OSPF_DEBUG_DETAIL	0x04
+
+#define OSPF_DEBUG_ISM_STATUS	0x01
+#define OSPF_DEBUG_ISM_EVENTS	0x02
+#define OSPF_DEBUG_ISM_TIMERS	0x04
+#define OSPF_DEBUG_ISM		0x07
+#define OSPF_DEBUG_NSM_STATUS	0x01
+#define OSPF_DEBUG_NSM_EVENTS	0x02
+#define OSPF_DEBUG_NSM_TIMERS   0x04
+#define OSPF_DEBUG_NSM		0x07
+
+#define OSPF_DEBUG_LSA_GENERATE 0x01
+#define OSPF_DEBUG_LSA_FLOODING	0x02
+#define OSPF_DEBUG_LSA_INSTALL  0x04
+#define OSPF_DEBUG_LSA_REFRESH  0x08
+#define OSPF_DEBUG_LSA		0x0F
+
+#define OSPF_DEBUG_ZEBRA_INTERFACE     0x01
+#define OSPF_DEBUG_ZEBRA_REDISTRIBUTE  0x02
+#define OSPF_DEBUG_ZEBRA	       0x03
+
+#define OSPF_DEBUG_EVENT        0x01
+#define OSPF_DEBUG_NSSA		0x02
+
+/* Macro for setting debug option. */
+#define CONF_DEBUG_PACKET_ON(a, b)	    conf_debug_ospf_packet[a] |= (b)
+#define CONF_DEBUG_PACKET_OFF(a, b)	    conf_debug_ospf_packet[a] &= ~(b)
+#define TERM_DEBUG_PACKET_ON(a, b)	    term_debug_ospf_packet[a] |= (b)
+#define TERM_DEBUG_PACKET_OFF(a, b)	    term_debug_ospf_packet[a] &= ~(b)
+#define DEBUG_PACKET_ON(a, b) \
+    do { \
+      CONF_DEBUG_PACKET_ON(a, b); \
+      TERM_DEBUG_PACKET_ON(a, b); \
+    } while (0)
+#define DEBUG_PACKET_OFF(a, b) \
+    do { \
+      CONF_DEBUG_PACKET_OFF(a, b); \
+      TERM_DEBUG_PACKET_OFF(a, b); \
+    } while (0)
+
+#define CONF_DEBUG_ON(a, b)	 conf_debug_ospf_ ## a |= (OSPF_DEBUG_ ## b)
+#define CONF_DEBUG_OFF(a, b)	 conf_debug_ospf_ ## a &= ~(OSPF_DEBUG_ ## b)
+#define TERM_DEBUG_ON(a, b)	 term_debug_ospf_ ## a |= (OSPF_DEBUG_ ## b)
+#define TERM_DEBUG_OFF(a, b)	 term_debug_ospf_ ## a &= ~(OSPF_DEBUG_ ## b)
+#define DEBUG_ON(a, b) \
+     do { \
+       CONF_DEBUG_ON(a, b); \
+       TERM_DEBUG_ON(a, b); \
+     } while (0)
+#define DEBUG_OFF(a, b) \
+     do { \
+       CONF_DEBUG_OFF(a, b); \
+       TERM_DEBUG_OFF(a, b); \
+     } while (0)
+
+/* Macro for checking debug option. */
+#define IS_DEBUG_OSPF_PACKET(a, b) \
+	(term_debug_ospf_packet[a] & OSPF_DEBUG_ ## b)
+#define IS_DEBUG_OSPF(a, b) \
+	(term_debug_ospf_ ## a & OSPF_DEBUG_ ## b)
+#define IS_DEBUG_OSPF_EVENT IS_DEBUG_OSPF(event,EVENT)
+
+#define IS_DEBUG_OSPF_NSSA  IS_DEBUG_OSPF(event,NSSA)
+
+#define IS_CONF_DEBUG_OSPF_PACKET(a, b) \
+	(conf_debug_ospf_packet[a] & OSPF_DEBUG_ ## b)
+#define IS_CONF_DEBUG_OSPF(a, b) \
+	(conf_debug_ospf_ ## a & OSPF_DEBUG_ ## b)
+
+#ifdef ORIGINAL_CODING
+#else /* ORIGINAL_CODING */
+struct stream;
+#endif /* ORIGINAL_CODING */
+
+#define AREA_NAME(A)    ospf_area_name_string ((A))
+#define IF_NAME(I)      ospf_if_name_string ((I))
+
+/* Extern debug flag. */
+extern unsigned long term_debug_ospf_packet[];
+extern unsigned long term_debug_ospf_event;
+extern unsigned long term_debug_ospf_ism;
+extern unsigned long term_debug_ospf_nsm;
+extern unsigned long term_debug_ospf_lsa;
+extern unsigned long term_debug_ospf_zebra;
+extern unsigned long term_debug_ospf_nssa;
+
+/* Message Strings. */
+extern char *ospf_packet_type_str[];
+extern char *ospf_lsa_type_str[];
+
+/* Prototypes. */
+char *ospf_area_name_string (struct ospf_area *);
+char *ospf_area_desc_string (struct ospf_area *);
+char *ospf_if_name_string (struct ospf_interface *);
+void ospf_nbr_state_message (struct ospf_neighbor *, char *, size_t);
+char *ospf_options_dump (u_char);
+char *ospf_timer_dump (struct thread *, char *, size_t);
+void ospf_ip_header_dump (struct stream *);
+void ospf_packet_dump (struct stream *);
+void ospf_lsa_header_dump (struct lsa_header *);
+void debug_init ();
+
+#endif /* _ZEBRA_OSPF_DUMP_H */
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
new file mode 100644
index 0000000..bd33c34
--- /dev/null
+++ b/ospfd/ospf_flood.c
@@ -0,0 +1,1048 @@
+/*
+ * OSPF Flooding -- RFC2328 Section 13.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ * 
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "command.h"
+#include "table.h"
+#include "thread.h"
+#include "memory.h"
+#include "log.h"
+#include "zclient.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_dump.h"
+
+extern struct zclient *zclient;
+
+/* Do the LSA acking specified in table 19, Section 13.5, row 2
+ * This get called from ospf_flood_out_interface. Declared inline 
+ * for speed. */
+static void
+ospf_flood_delayed_lsa_ack (struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
+{
+  /* LSA is more recent than database copy, but was not
+     flooded back out receiving interface.  Delayed
+     acknowledgment sent. If interface is in Backup state
+     delayed acknowledgment sent only if advertisement
+     received from Designated Router, otherwise do nothing See
+     RFC 2328 Section 13.5 */
+
+  /* Whether LSA is more recent or not, and whether this is in
+     response to the LSA being sent out recieving interface has been 
+     worked out previously */
+
+  /* Deal with router as BDR */
+  if (inbr->oi->state == ISM_Backup && ! NBR_IS_DR (inbr))
+    return;
+
+  /* Schedule a delayed LSA Ack to be sent */ 
+  listnode_add (inbr->oi->ls_ack, ospf_lsa_lock (lsa));
+}
+
+/* Check LSA is related to external info. */
+struct external_info *
+ospf_external_info_check (struct ospf_lsa *lsa)
+{
+  struct as_external_lsa *al;
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+  int type;
+
+  al = (struct as_external_lsa *) lsa->data;
+
+  p.family = AF_INET;
+  p.prefix = lsa->data->id;
+  p.prefixlen = ip_masklen (al->mask);
+
+  for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
+    {
+      int redist_type = is_prefix_default (&p) ? DEFAULT_ROUTE : type;
+      if (ospf_is_type_redistributed (redist_type))
+	if (EXTERNAL_INFO (type))
+	  {
+	    rn = route_node_lookup (EXTERNAL_INFO (type),
+				    (struct prefix *) &p);
+	    if (rn)
+	      {
+		route_unlock_node (rn);
+		if (rn->info != NULL)
+		  return (struct external_info *) rn->info;
+	      }
+	  }
+    }
+
+  return NULL;
+}
+
+void
+ospf_process_self_originated_lsa (struct ospf_lsa *new, struct ospf_area *area)
+{
+  struct ospf_interface *oi;
+  struct external_info *ei;
+  listnode node;
+  
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("LSA[Type%d:%s]: Process self-originated LSA",
+	       new->data->type, inet_ntoa (new->data->id));
+
+  /* If we're here, we installed a self-originated LSA that we received
+     from a neighbor, i.e. it's more recent.  We must see whether we want
+     to originate it.
+     If yes, we should use this LSA's sequence number and reoriginate
+     a new instance.
+     if not --- we must flush this LSA from the domain. */
+  switch (new->data->type)
+    {
+    case OSPF_ROUTER_LSA:
+      /* Originate a new instance and schedule flooding */
+      /* It shouldn't be necessary, but anyway */
+      ospf_lsa_unlock (area->router_lsa_self);
+      area->router_lsa_self = ospf_lsa_lock (new);
+
+      ospf_router_lsa_timer_add (area);
+      return;
+    case OSPF_NETWORK_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      /* We must find the interface the LSA could belong to.
+	 If the interface is no more a broadcast type or we are no more
+	 the DR, we flush the LSA otherwise -- create the new instance and
+	 schedule flooding. */
+
+      /* Look through all interfaces, not just area, since interface
+	 could be moved from one area to another. */
+      for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+	/* These are sanity check. */
+	if ((oi = getdata (node)) != NULL)
+	  if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &new->data->id))
+	    {
+	      if (oi->area != area ||
+		  oi->type != OSPF_IFTYPE_BROADCAST ||
+		  !IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)))
+		{
+		  ospf_schedule_lsa_flush_area (area, new);
+		  return;
+		}
+	      
+#ifdef HAVE_OPAQUE_LSA
+              if (new->data->type == OSPF_OPAQUE_LINK_LSA)
+                {
+                  ospf_opaque_lsa_refresh (new);
+                  return;
+                }
+#endif /* HAVE_OPAQUE_LSA */
+
+	      ospf_lsa_unlock (oi->network_lsa_self);
+	      oi->network_lsa_self = ospf_lsa_lock (new);
+	      
+	      /* Schedule network-LSA origination. */
+	      ospf_network_lsa_timer_add (oi);
+	      return;
+	    }
+      break;
+    case OSPF_SUMMARY_LSA:
+    case OSPF_ASBR_SUMMARY_LSA:
+      ospf_schedule_abr_task ();
+      break;
+    case OSPF_AS_EXTERNAL_LSA :
+#ifdef HAVE_NSSA
+    case OSPF_AS_NSSA_LSA:
+#endif /* HAVE_NSSA */
+      ei = ospf_external_info_check (new);
+      if (ei)
+	ospf_external_lsa_refresh (new, ei, LSA_REFRESH_FORCE);
+      else
+	ospf_lsa_flush_as (new);
+      break;
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AREA_LSA:
+      ospf_opaque_lsa_refresh (new);
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      ospf_opaque_lsa_refresh (new); /* Reconsideration may needed. *//* XXX */
+      break;
+#endif /* HAVE_OPAQUE_LSA */
+    default:
+      break;
+    }
+}
+
+/* OSPF LSA flooding -- RFC2328 Section 13.(5). */
+
+/* Now Updated for NSSA operation, as follows:
+
+
+	Type-5's have no change.  Blocked to STUB or NSSA.
+
+	Type-7's can be received, and if a DR
+	they will also flood the local NSSA Area as Type-7's
+
+	If a Self-Originated LSA (now an ASBR), 
+	The LSDB will be updated as Type-5's, (for continual re-fresh)
+
+	    If an NSSA-IR it is installed/flooded as Type-7, P-bit on.
+	    if an NSSA-ABR it is installed/flooded as Type-7, P-bit off.
+
+	Later, during the ABR TASK, if the ABR is the Elected NSSA
+	translator, then All Type-7s (with P-bit ON) are Translated to
+	Type-5's and flooded to all non-NSSA/STUB areas.
+
+	During ASE Calculations, 
+	    non-ABRs calculate external routes from Type-7's
+	    ABRs calculate external routes from Type-5's and non-self Type-7s
+*/
+int
+ospf_flood (struct ospf_neighbor *nbr, struct ospf_lsa *current,
+	    struct ospf_lsa *new)
+{
+  struct ospf_interface *oi;
+  struct timeval now;
+  int lsa_ack_flag;
+
+  /* Type-7 LSA's will be flooded throughout their native NSSA area,
+     but will also be flooded as Type-5's into ABR capable links.  */
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]",
+               inet_ntoa (nbr->router_id),
+               LOOKUP (ospf_nsm_state_msg, nbr->state),
+               current,
+               dump_lsa_key (new));
+
+  lsa_ack_flag = 0;
+  oi = nbr->oi;
+
+  /* Get current time. */
+  gettimeofday (&now, NULL);
+
+  /* If there is already a database copy, and if the
+     database copy was received via flooding and installed less
+     than MinLSArrival seconds ago, discard the new LSA
+     (without acknowledging it). */
+  if (current != NULL)		/* -- endo. */
+    {
+      if (IS_LSA_SELF (current)
+      && (ntohs (current->data->ls_age)    == 0
+      &&  ntohl (current->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER))
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("LSA[Flooding]: Got a self-originated LSA, "
+		       "while local one is initial instance.");
+          ; /* Accept this LSA for quick LSDB resynchronization. */
+        }
+      else if (tv_cmp (tv_sub (now, current->tv_recv),
+	               int2tv (OSPF_MIN_LS_ARRIVAL)) < 0)
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("LSA[Flooding]: LSA is received recently.");
+          return -1;
+        }
+    }
+
+  /* Flood the new LSA out some subset of the router's interfaces.
+     In some cases (e.g., the state of the receiving interface is
+     DR and the LSA was received from a router other than the
+     Backup DR) the LSA will be flooded back out the receiving
+     interface. */
+  lsa_ack_flag = ospf_flood_through (nbr, new);
+
+#ifdef HAVE_OPAQUE_LSA
+  /* Remove the current database copy from all neighbors' Link state
+     retransmission lists.  AS_EXTERNAL and AS_EXTERNAL_OPAQUE does
+                                        ^^^^^^^^^^^^^^^^^^^^^^^
+     not have area ID.
+     All other (even NSSA's) do have area ID.  */
+#else /* HAVE_OPAQUE_LSA */
+  /* Remove the current database copy from all neighbors' Link state
+     retransmission lists.  Only AS_EXTERNAL does not have area ID.
+     All other (even NSSA's) do have area ID.  */
+#endif /* HAVE_OPAQUE_LSA */
+  if (current)
+    {
+      switch (current->data->type)
+        {
+        case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+        case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+          ospf_ls_retransmit_delete_nbr_all (NULL, current);
+          break;
+        default:
+          ospf_ls_retransmit_delete_nbr_all (nbr->oi->area, current);
+          break;
+        }
+    }
+
+  /* Do some internal house keeping that is needed here */
+  SET_FLAG (new->flags, OSPF_LSA_RECEIVED);
+  ospf_lsa_is_self_originated (new); /* Let it set the flag */
+
+  /* Install the new LSA in the link state database
+     (replacing the current database copy).  This may cause the
+     routing table calculation to be scheduled.  In addition,
+     timestamp the new LSA with the current time.  The flooding
+     procedure cannot overwrite the newly installed LSA until
+     MinLSArrival seconds have elapsed. */  
+
+  new = ospf_lsa_install (nbr->oi, new);
+
+#ifdef HAVE_NSSA 
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("LSA[Flooding]: Type-%d installed", new->data->type);
+
+  /* if  (new->data->type == OSPF_AS_NSSA_LSA )
+     return 0;  */
+#endif /* HAVE_NSSA */
+
+  /* Acknowledge the receipt of the LSA by sending a Link State
+     Acknowledgment packet back out the receiving interface. */
+  if (lsa_ack_flag)
+    ospf_flood_delayed_lsa_ack (nbr, new);     
+
+  /* If this new LSA indicates that it was originated by the
+     receiving router itself, the router must take special action,
+     either updating the LSA or in some cases flushing it from
+     the routing domain. */
+  if (ospf_lsa_is_self_originated (new))
+    ospf_process_self_originated_lsa (new, oi->area);
+  else
+    /* Update statistics value for OSPF-MIB. */
+    ospf_top->rx_lsa_count++;
+
+  return 0;
+}
+
+/* OSPF LSA flooding -- RFC2328 Section 13.3. */
+int
+ospf_flood_through_interface (struct ospf_interface *oi,
+			      struct ospf_neighbor *inbr,
+			      struct ospf_lsa *lsa)
+{
+  struct ospf_neighbor *onbr;
+  struct route_node *rn;
+  int retx_flag;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_flood_through_interface(): "
+	       "considering int %s, INBR(%s), LSA[%s]",
+	       IF_NAME (oi), inbr ? inet_ntoa (inbr->router_id) : "NULL",
+               dump_lsa_key (lsa));
+
+  if (!ospf_if_is_enable (oi))
+    return 0;
+
+  /* Remember if new LSA is aded to a retransmit list. */
+  retx_flag = 0;
+
+  /* Each of the neighbors attached to this interface are examined,
+     to determine whether they must receive the new LSA.  The following
+     steps are executed for each neighbor: */
+  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+    {
+      struct ospf_lsa *ls_req;
+ 
+      if (rn->info == NULL)
+	continue;
+
+      onbr = rn->info;
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_flood_through_interface(): considering nbr %s (%s)",
+		   inet_ntoa (onbr->router_id),
+                   LOOKUP (ospf_nsm_state_msg, onbr->state));
+
+      /* If the neighbor is in a lesser state than Exchange, it
+	 does not participate in flooding, and the next neighbor
+	 should be examined. */
+      if (onbr->state < NSM_Exchange)
+	continue;
+
+      /* If the adjacency is not yet full (neighbor state is
+	 Exchange or Loading), examine the Link state request
+	 list associated with this adjacency.  If there is an
+	 instance of the new LSA on the list, it indicates that
+	 the neighboring router has an instance of the LSA
+	 already.  Compare the new LSA to the neighbor's copy: */
+      if (onbr->state < NSM_Full)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_flood_through_interface(): nbr adj is not Full");
+	  ls_req = ospf_ls_request_lookup (onbr, lsa);
+	  if (ls_req != NULL)
+	    {
+	      int ret;
+
+	      ret = ospf_lsa_more_recent (ls_req, lsa);
+	      /* The new LSA is less recent. */
+	      if (ret > 0)
+		continue;
+	      /* The two copies are the same instance, then delete
+		 the LSA from the Link state request list. */
+	      else if (ret == 0)
+		{
+		  ospf_ls_request_delete (onbr, ls_req);
+		  ospf_check_nbr_loading (onbr);
+		  continue;
+		}
+	      /* The new LSA is more recent.  Delete the LSA
+		 from the Link state request list. */
+	      else
+		{
+		  ospf_ls_request_delete (onbr, ls_req);
+		  ospf_check_nbr_loading (onbr);
+		}
+	    }
+	}
+
+#ifdef HAVE_OPAQUE_LSA
+      if (IS_OPAQUE_LSA (lsa->data->type))
+        {
+          if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O))
+            {
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: Not Opaque-capable.");
+              continue;
+            }
+
+          if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (ospf_top->opaque)
+          &&  IS_LSA_SELF (lsa)
+          &&  onbr->state == NSM_Full)
+            {
+              /* Small attempt to reduce unnecessary retransmission. */
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: Initial flushing done.");
+              continue;
+            }
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      /* If the new LSA was received from this neighbor,
+	 examine the next neighbor. */
+#ifdef ORIGINAL_CODING
+      if (inbr)
+	if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id))
+	  continue;
+#else /* ORIGINAL_CODING */
+      if (inbr)
+        {
+          /*
+           * Triggered by LSUpd message parser "ospf_ls_upd ()".
+           * E.g., all LSAs handling here is received via network.
+           */
+          if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id))
+            {
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: inbr == onbr");
+              continue;
+            }
+        }
+      else
+        {
+          /*
+           * Triggered by MaxAge remover, so far.
+           * NULL "inbr" means flooding starts from this node.
+           */
+          if (IPV4_ADDR_SAME (&lsa->data->adv_router, &onbr->router_id))
+            {
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: lsah->adv_router == onbr");
+              continue;
+            }
+        }
+#endif /* ORIGINAL_CODING */
+
+      /* Add the new LSA to the Link state retransmission list
+	 for the adjacency. The LSA will be retransmitted
+	 at intervals until an acknowledgment is seen from
+	 the neighbor. */
+      ospf_ls_retransmit_add (onbr, lsa);
+      retx_flag = 1;
+    }
+
+  /* If in the previous step, the LSA was NOT added to any of
+     the Link state retransmission lists, there is no need to
+     flood the LSA out the interface. */
+  if (retx_flag == 0) 
+    {
+      return (inbr && inbr->oi == oi);
+    }
+
+  /* if we've received the lsa on this interface we need to perform
+     additional checking */
+  if (inbr && (inbr->oi == oi))
+    {
+      /* If the new LSA was received on this interface, and it was
+	 received from either the Designated Router or the Backup
+	 Designated Router, chances are that all the neighbors have
+	 received the LSA already. */
+      if (NBR_IS_DR (inbr) || NBR_IS_BDR (inbr))
+	{
+#ifdef HAVE_NSSA
+	  if (IS_DEBUG_OSPF_NSSA)
+	    zlog_info ("ospf_flood_through_interface(): "
+		       "DR/BDR NOT SEND to int %s", IF_NAME (oi));
+#endif /* HAVE_NSSA */
+	  return 1;
+	}
+	  
+      /* If the new LSA was received on this interface, and the
+	 interface state is Backup, examine the next interface.  The
+	 Designated Router will do the flooding on this interface.
+	 However, if the Designated Router fails the router will
+	 end up retransmitting the updates. */
+
+      if (oi->state == ISM_Backup)
+	{
+#ifdef HAVE_NSSA
+	  if (IS_DEBUG_OSPF_NSSA)
+	    zlog_info ("ospf_flood_through_interface(): "
+		       "ISM_Backup NOT SEND to int %s", IF_NAME (oi));
+#endif /* HAVE_NSSA */
+	  return 1;
+	}
+    }
+
+  /* The LSA must be flooded out the interface. Send a Link State
+     Update packet (including the new LSA as contents) out the
+     interface.  The LSA's LS age must be incremented by InfTransDelay
+     (which	must be	> 0) when it is copied into the outgoing Link
+     State Update packet (until the LS age field reaches the maximum
+     value of MaxAge). */
+
+#ifdef HAVE_NSSA
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_flood_through_interface(): "
+	       "DR/BDR sending upd to int %s", IF_NAME (oi));
+#else /* ! HAVE_NSSA */
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_flood_through_interface(): "
+	       "sending upd to int %s", IF_NAME (oi));
+#endif /* HAVE_NSSA */
+
+  /*  RFC2328  Section 13.3
+      On non-broadcast networks, separate	Link State Update
+      packets must be sent, as unicasts, to each adjacent	neighbor
+      (i.e., those in state Exchange or greater).	 The destination
+      IP addresses for these packets are the neighbors' IP
+      addresses.   */
+  if (oi->type == OSPF_IFTYPE_NBMA)
+    {
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+        if ((nbr = rn->info) != NULL)
+	  if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
+	    ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT);
+    }
+  else
+    ospf_ls_upd_send_lsa (oi->nbr_self, lsa, OSPF_SEND_PACKET_INDIRECT);
+
+  return 0;
+}
+
+int
+ospf_flood_through_area (struct ospf_area * area,struct ospf_neighbor *inbr,
+			 struct ospf_lsa *lsa)
+{
+  listnode node;
+  int lsa_ack_flag = 0;
+
+  /* All other types are specific to a single area (Area A).  The
+     eligible interfaces are all those interfaces attaching to the
+     Area A.  If Area A is the backbone, this includes all the virtual
+     links.  */
+  for (node = listhead (area->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+
+      if (area->area_id.s_addr != OSPF_AREA_BACKBONE &&
+	  oi->type ==  OSPF_IFTYPE_VIRTUALLINK) 
+	continue;
+
+#ifdef HAVE_OPAQUE_LSA
+      if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) && (lsa->oi != oi))
+        {
+          /*
+           * Link local scoped Opaque-LSA should only be flooded
+           * for the link on which the LSA has received.
+           */
+          if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+            zlog_info ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", lsa->oi, oi);
+          continue;
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      if (ospf_flood_through_interface (oi, inbr, lsa))
+	lsa_ack_flag = 1;
+    }
+
+  return (lsa_ack_flag);
+}
+
+int
+ospf_flood_through_as (struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
+{
+  listnode node;
+  int lsa_ack_flag;
+
+  lsa_ack_flag = 0;
+
+  /* The incoming LSA is type 5 or type 7  (AS-EXTERNAL or AS-NSSA )
+
+    Divert the Type-5 LSA's to all non-NSSA/STUB areas
+
+    Divert the Type-7 LSA's to all NSSA areas
+
+     AS-external-LSAs are flooded throughout the entire AS, with the
+     exception of stub areas (see Section 3.6).  The eligible
+     interfaces are all the router's interfaces, excluding virtual
+     links and those interfaces attaching to stub areas.  */
+
+#ifdef HAVE_NSSA
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7  */
+    if (IS_DEBUG_OSPF_NSSA)
+      zlog_info ("Flood/AS: NSSA TRANSLATED LSA");
+#endif /* HAVE_NSSA */
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      int continue_flag = 0;
+      struct ospf_area *area = getdata (node);
+      listnode if_node;
+
+      switch (area->external_routing)
+	{
+	  /* Don't send AS externals into stub areas.  Various types
+             of support for partial stub areas can be implemented
+             here.  NSSA's will receive Type-7's that have areas
+             matching the originl LSA. */
+	case OSPF_AREA_NSSA:	/* Sending Type 5 or 7 into NSSA area */
+#ifdef HAVE_NSSA
+	  /* Type-7, flood NSSA area */
+          if (lsa->data->type == OSPF_AS_NSSA_LSA) 
+	    /* We will send it. */
+	    continue_flag = 0;
+          else
+	    continue_flag = 1;  /* Skip this NSSA area for Type-5's et al */
+          break;
+#endif /* HAVE_NSSA */
+
+	case OSPF_AREA_TYPE_MAX:
+	case OSPF_AREA_STUB:
+	  continue_flag = 1;	/* Skip this area. */
+	  break;
+
+	case OSPF_AREA_DEFAULT:
+	default:
+#ifdef HAVE_NSSA
+	  /* No Type-7 into normal area */
+          if (lsa->data->type == OSPF_AS_NSSA_LSA) 
+	    continue_flag = 1; /* skip Type-7 */
+          else
+#endif /* HAVE_NSSA */
+	    continue_flag = 0;	/* Do this area. */
+	  break;
+	}
+      
+      /* Do continue for above switch.  Saves a big if then mess */
+      if (continue_flag) 
+	continue; /* main for-loop */
+      
+      /* send to every interface in this area */
+
+      for (if_node = listhead (area->oiflist); if_node; nextnode (if_node))
+	{
+	  struct ospf_interface *oi = getdata (if_node);
+
+	  /* Skip virtual links */
+	  if (oi->type !=  OSPF_IFTYPE_VIRTUALLINK)
+	    if (ospf_flood_through_interface (oi, inbr, lsa)) /* lsa */
+	      lsa_ack_flag = 1;
+	}
+    } /* main area for-loop */
+  
+  return (lsa_ack_flag);
+}
+
+int
+ospf_flood_through (struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
+{
+  int lsa_ack_flag = 0;
+  
+  /* Type-7 LSA's for NSSA are flooded throughout the AS here, and
+     upon return are updated in the LSDB for Type-7's.  Later,
+     re-fresh will re-send them (and also, if ABR, packet code will
+     translate to Type-5's)
+  
+     As usual, Type-5 LSA's (if not DISCARDED because we are STUB or
+     NSSA) are flooded throughout the AS, and are updated in the
+     global table.  */
+#ifdef ORIGINAL_CODING
+  switch (lsa->data->type)
+    {
+    case OSPF_ROUTER_LSA:
+    case OSPF_NETWORK_LSA:
+    case OSPF_SUMMARY_LSA:
+    case OSPF_ASBR_SUMMARY_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */
+    case OSPF_OPAQUE_AREA_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa);
+      break;
+    case OSPF_AS_EXTERNAL_LSA: /* Type-5 */
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      lsa_ack_flag = ospf_flood_through_as (inbr, lsa);
+      break;
+#ifdef HAVE_NSSA
+      /* Type-7 Only received within NSSA, then flooded */
+    case OSPF_AS_NSSA_LSA:
+      /* Any P-bit was installed with the Type-7. */
+      lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa);
+
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7.");
+      break;
+#endif /* HAVE_NSSA */
+    default:
+      break;
+    }
+#else /* ORIGINAL_CODING */
+  /*
+   * At the common sub-sub-function "ospf_flood_through_interface()",
+   * a parameter "inbr" will be used to distinguish the called context
+   * whether the given LSA was received from the neighbor, or the
+   * flooding for the LSA starts from this node (e.g. the LSA was self-
+   * originated, or the LSA is going to be flushed from routing domain).
+   *
+   * So, for consistency reasons, this function "ospf_flood_through()"
+   * should also allow the usage that the given "inbr" parameter to be
+   * NULL. If we do so, corresponding AREA parameter should be referred
+   * by "lsa->area", instead of "inbr->oi->area".
+   */
+  switch (lsa->data->type)
+    {
+    case OSPF_AS_EXTERNAL_LSA: /* Type-5 */
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      lsa_ack_flag = ospf_flood_through_as (inbr, lsa);
+      break;
+#ifdef HAVE_NSSA
+      /* Type-7 Only received within NSSA, then flooded */
+    case OSPF_AS_NSSA_LSA:
+      /* Any P-bit was installed with the Type-7. */
+
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7.");
+      /* Fallthrough */
+#endif /* HAVE_NSSA */
+    default:
+      lsa_ack_flag = ospf_flood_through_area (lsa->area, inbr, lsa);
+      break;
+    }
+#endif /* ORIGINAL_CODING */
+  
+  return (lsa_ack_flag);
+}
+
+
+
+/* Management functions for neighbor's Link State Request list. */
+void
+ospf_ls_request_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  /*
+   * We cannot make use of the newly introduced callback function
+   * "lsdb->new_lsa_hook" to replace debug output below, just because
+   * it seems no simple and smart way to pass neighbor information to
+   * the common function "ospf_lsdb_add()" -- endo.
+   */
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+      zlog_info ("RqstL(%lu)++, NBR(%s), LSA[%s]",
+                  ospf_ls_request_count (nbr),
+                  inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+
+  ospf_lsdb_add (&nbr->ls_req, lsa);
+}
+
+unsigned long
+ospf_ls_request_count (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_count_all (&nbr->ls_req);
+}
+
+int
+ospf_ls_request_isempty (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_isempty (&nbr->ls_req);
+}
+
+/* Remove LSA from neighbor's ls-request list. */
+void
+ospf_ls_request_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  if (nbr->ls_req_last == lsa)
+    {
+      ospf_lsa_unlock (nbr->ls_req_last);
+      nbr->ls_req_last = NULL;
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))	/* -- endo. */
+      zlog_info ("RqstL(%lu)--, NBR(%s), LSA[%s]",
+                  ospf_ls_request_count (nbr),
+                  inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+
+  ospf_lsdb_delete (&nbr->ls_req, lsa);
+}
+
+/* Remove all LSA from neighbor's ls-requenst list. */
+void
+ospf_ls_request_delete_all (struct ospf_neighbor *nbr)
+{
+  ospf_lsa_unlock (nbr->ls_req_last);
+  nbr->ls_req_last = NULL;
+  ospf_lsdb_delete_all (&nbr->ls_req);
+}
+
+/* Lookup LSA from neighbor's ls-request list. */
+struct ospf_lsa *
+ospf_ls_request_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  return ospf_lsdb_lookup (&nbr->ls_req, lsa);
+}
+
+struct ospf_lsa *
+ospf_ls_request_new (struct lsa_header *lsah)
+{
+  struct ospf_lsa *new;
+
+  new = ospf_lsa_new ();
+  new->data = ospf_lsa_data_new (OSPF_LSA_HEADER_SIZE);
+  memcpy (new->data, lsah, OSPF_LSA_HEADER_SIZE);
+
+  return new;
+}
+
+
+/* Management functions for neighbor's ls-retransmit list. */
+unsigned long
+ospf_ls_retransmit_count (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_count_all (&nbr->ls_rxmt);
+}
+
+unsigned long
+ospf_ls_retransmit_count_self (struct ospf_neighbor *nbr, int lsa_type)
+{
+  return ospf_lsdb_count_self (&nbr->ls_rxmt, lsa_type);
+}
+
+int
+ospf_ls_retransmit_isempty (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_isempty (&nbr->ls_rxmt);
+}
+
+/* Add LSA to be retransmitted to neighbor's ls-retransmit list. */
+void
+ospf_ls_retransmit_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  struct ospf_lsa *old;
+
+  old = ospf_ls_retransmit_lookup (nbr, lsa);
+
+  if (ospf_lsa_more_recent (old, lsa) < 0)
+    {
+      if (old)
+	{
+	  old->retransmit_counter--;
+	  ospf_lsdb_delete (&nbr->ls_rxmt, old);
+	}
+      lsa->retransmit_counter++;
+      /*
+       * We cannot make use of the newly introduced callback function
+       * "lsdb->new_lsa_hook" to replace debug output below, just because
+       * it seems no simple and smart way to pass neighbor information to
+       * the common function "ospf_lsdb_add()" -- endo.
+       */
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+	  zlog_info ("RXmtL(%lu)++, NBR(%s), LSA[%s]",
+                     ospf_ls_retransmit_count (nbr),
+		     inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+      ospf_lsdb_add (&nbr->ls_rxmt, lsa);
+    }
+}
+
+/* Remove LSA from neibghbor's ls-retransmit list. */
+void
+ospf_ls_retransmit_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  if (ospf_ls_retransmit_lookup (nbr, lsa))
+    {
+      lsa->retransmit_counter--;  
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))		/* -- endo. */
+	  zlog_info ("RXmtL(%lu)--, NBR(%s), LSA[%s]",
+                     ospf_ls_retransmit_count (nbr),
+		     inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+      ospf_lsdb_delete (&nbr->ls_rxmt, lsa);
+    }
+}
+
+/* Clear neighbor's ls-retransmit list. */
+void
+ospf_ls_retransmit_clear (struct ospf_neighbor *nbr)
+{
+  struct ospf_lsdb *lsdb;
+  int i;
+
+  lsdb = &nbr->ls_rxmt;
+
+  for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+    {
+      struct route_table *table = lsdb->type[i].db;
+      struct route_node *rn;
+      struct ospf_lsa *lsa;
+
+      for (rn = route_top (table); rn; rn = route_next (rn))
+	if ((lsa = rn->info) != NULL)
+	  ospf_ls_retransmit_delete (nbr, lsa);
+    }
+
+  ospf_lsa_unlock (nbr->ls_req_last);
+  nbr->ls_req_last = NULL;
+}
+
+/* Lookup LSA from neighbor's ls-retransmit list. */
+struct ospf_lsa *
+ospf_ls_retransmit_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  return ospf_lsdb_lookup (&nbr->ls_rxmt, lsa);
+}
+
+/* Remove All neighbor/interface's Link State Retransmit list in area. */
+void
+ospf_ls_retransmit_delete_nbr_all (struct ospf_area *area,
+				   struct ospf_lsa *lsa)
+{
+  listnode node;
+  list oiflist = area ? area->oiflist : ospf_top->oiflist;
+  
+  for (node = listhead (oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+      struct ospf_lsa *lsr;
+      
+      if (ospf_if_is_enable (oi))
+	for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	  /* If LSA find in LS-retransmit list, then remove it. */
+	  if ((nbr = rn->info) != NULL)
+	    {
+	      lsr = ospf_ls_retransmit_lookup (nbr, lsa);
+	     
+	      /* If LSA find in ls-retransmit list, remove it. */
+	      if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
+		ospf_ls_retransmit_delete (nbr, lsr);
+	    }
+    }
+}
+
+/* Add LSA to the current database copy of all neighbors'
+   Link state retransmission lists. */
+void
+ospf_ls_retransmit_add_nbr_all (struct ospf_interface *ospfi,
+				struct ospf_lsa *lsa)
+{
+  listnode node;
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+      struct ospf_lsa *old;
+
+      if (ospf_if_is_enable (oi))
+	if (OSPF_AREA_SAME (&ospfi->area, &oi->area))
+	  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	    if ((nbr = rn->info) != NULL)
+	      if (nbr->state == NSM_Full)
+		{
+		  if ((old = ospf_ls_retransmit_lookup (nbr, lsa)))
+		    ospf_ls_retransmit_delete (nbr, old);
+
+		  ospf_ls_retransmit_add (nbr, lsa);
+		}
+    }
+}
+
+
+/* Sets ls_age to MaxAge and floods throu the area. 
+   When we implement ASE routing, there will be anothe function
+   flushing an LSA from the whole domain. */
+void
+ospf_lsa_flush_area (struct ospf_lsa *lsa, struct ospf_area *area)
+{
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  ospf_flood_through_area (area, NULL, lsa);
+  ospf_lsa_maxage (lsa);
+}
+
+void
+ospf_lsa_flush_as (struct ospf_lsa *lsa)
+{
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  ospf_flood_through_as (NULL, lsa);
+  ospf_lsa_maxage (lsa);
+}
+
+/* Flush LSA through AS -- used for AS-external-LSAs. */
+void
+ospf_flush_through_as (struct ospf_lsa *lsa)
+{
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  ospf_flood_through_as (NULL, lsa);
+  ospf_lsa_maxage (lsa);
+}
diff --git a/ospfd/ospf_flood.h b/ospfd/ospf_flood.h
new file mode 100644
index 0000000..1a6ab97
--- /dev/null
+++ b/ospfd/ospf_flood.h
@@ -0,0 +1,65 @@
+/*
+ * OSPF Flooding -- RFC2328 Section 13.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ * 
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_FLOODING_H
+#define _ZEBRA_OSPF_FLOODING_H
+
+int ospf_flood (struct ospf_neighbor *, struct ospf_lsa *, struct ospf_lsa *);
+int ospf_flood_through (struct ospf_neighbor *, struct ospf_lsa *);
+int ospf_flood_through_area (struct ospf_area *, struct ospf_neighbor *,
+			     struct ospf_lsa *);
+int ospf_flood_through_as (struct ospf_neighbor *, struct ospf_lsa *);
+
+unsigned long ospf_ls_request_count (struct ospf_neighbor *);
+int ospf_ls_request_isempty (struct ospf_neighbor *);
+struct ospf_lsa *ospf_ls_request_new (struct lsa_header *);
+void ospf_ls_request_free (struct ospf_lsa *);
+void ospf_ls_request_add (struct ospf_neighbor *, struct ospf_lsa *);
+void ospf_ls_request_delete (struct ospf_neighbor *, struct ospf_lsa *);
+void ospf_ls_request_delete_all (struct ospf_neighbor *);
+struct ospf_lsa *ospf_ls_request_lookup (struct ospf_neighbor *,
+					 struct ospf_lsa *);
+
+unsigned long ospf_ls_retransmit_count (struct ospf_neighbor *);
+unsigned long ospf_ls_retransmit_count_self (struct ospf_neighbor *, int);
+int ospf_ls_retransmit_isempty (struct ospf_neighbor *);
+void ospf_ls_retransmit_add (struct ospf_neighbor *, struct ospf_lsa *);
+void ospf_ls_retransmit_delete (struct ospf_neighbor *, struct ospf_lsa *);
+void ospf_ls_retransmit_clear (struct ospf_neighbor *);
+struct ospf_lsa *ospf_ls_retransmit_lookup (struct ospf_neighbor *,
+					    struct ospf_lsa *);
+void ospf_ls_retransmit_delete_nbr_all (struct ospf_area *, struct ospf_lsa *);
+void ospf_ls_retransmit_add_nbr_all (struct ospf_interface *,
+				     struct ospf_lsa *);
+
+void ospf_flood_lsa_area (struct ospf_lsa *, struct ospf_area *);
+void ospf_flood_lsa_as (struct ospf_lsa *);
+void ospf_lsa_flush_area (struct ospf_lsa *, struct ospf_area *);
+void ospf_lsa_flush_as (struct ospf_lsa *);
+void ospf_flush_through_as (struct ospf_lsa *);
+struct external_info *ospf_external_info_check (struct ospf_lsa *);
+
+void debug_ospf_ls_retransmit (struct ospf_neighbor *);
+
+void ospf_lsdb_init (struct ospf_lsdb *);
+
+#endif /* _ZEBRA_OSPF_FLOODING_H */
diff --git a/ospfd/ospf_ia.c b/ospfd/ospf_ia.c
new file mode 100644
index 0000000..32c8d86
--- /dev/null
+++ b/ospfd/ospf_ia.c
@@ -0,0 +1,726 @@
+/*
+ * OSPF inter-area routing.
+ * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "hash.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "table.h"
+#include "log.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ase.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_ia.h"
+#include "ospfd/ospf_dump.h"
+
+#define DEBUG
+
+struct ospf_route *
+ospf_find_abr_route (struct route_table *rtrs, 
+                     struct prefix_ipv4 *abr,
+                     struct ospf_area *area)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  listnode node;
+
+  if ((rn = route_node_lookup (rtrs, (struct prefix *) abr)) == NULL)
+    return NULL;
+
+  route_unlock_node (rn);
+
+  for (node = listhead ((list) rn->info); node; nextnode (node))
+    if ((or = getdata (node)) != NULL)
+      if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id) && (or->u.std.flags & ROUTER_LSA_BORDER))
+	return or;
+
+  return NULL;
+}
+
+void
+ospf_ia_network_route (struct route_table *rt, struct prefix_ipv4 *p,
+                       struct ospf_route *new_or, struct ospf_route *abr_or)
+{
+  struct route_node *rn1;
+  struct ospf_route *or;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_ia_network_route(): processing summary route to %s/%d", 
+	       inet_ntoa (p->prefix), p->prefixlen);
+
+  /* Find a route to the same dest */
+  if ((rn1 = route_node_lookup (rt, (struct prefix *) p)))
+    {
+      int res;
+
+      route_unlock_node (rn1);
+
+      if ((or = rn1->info))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_ia_network_route(): "
+		       "Found a route to the same network");
+	  /* Check the existing route. */
+	  if ((res = ospf_route_cmp (new_or, or)) < 0)
+	    {
+	      /* New route is better, so replace old one. */
+	      ospf_route_subst (rn1, new_or, abr_or);
+	    }
+	  else if (res == 0)
+	    {
+	      /* New and old route are equal, so next hops can be added. */
+	      route_lock_node (rn1);
+	      ospf_route_copy_nexthops (or, abr_or->path);
+	      route_unlock_node (rn1);
+
+	      /* new route can be deleted, because existing route has been updated. */
+	      ospf_route_free (new_or);
+	    }
+	  else
+	    {
+	      /* New route is worse, so free it. */
+	      ospf_route_free (new_or);
+	      return;
+	    }
+	} /* if (or)*/
+    } /*if (rn1)*/
+  else
+    { /* no route */
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_ia_network_route(): add new route to %s/%d",
+		   inet_ntoa (p->prefix), p->prefixlen);
+      ospf_route_add (rt, p, new_or, abr_or);
+    }
+}
+
+void
+ospf_ia_router_route (struct route_table *rt, struct prefix_ipv4 *p,
+                      struct ospf_route *new_or, struct ospf_route *abr_or)
+{
+  struct route_node *rn;
+  struct ospf_route *or = NULL;
+  int ret;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_ia_router_route(): considering %s/%d", 
+	       inet_ntoa (p->prefix), p->prefixlen);
+  /* Find a route to the same dest */
+  rn = route_node_get (rt,(struct prefix *) p);
+   
+  if (rn->info == NULL)
+    /* This is a new route */
+    rn->info = list_new ();
+  else
+    {
+      struct ospf_area *or_area;
+      or_area = ospf_area_lookup_by_area_id (new_or->u.std.area_id);
+      assert (or_area);
+      /* This is an additional route */
+      route_unlock_node (rn);
+      or = ospf_find_asbr_route_through_area (rt, p, or_area);
+    }
+
+  if (or)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_ia_router_route(): "
+		   "a route to the same ABR through the same area exists");
+      /* New route is better */
+      if ((ret = ospf_route_cmp (new_or, or)) < 0)
+	{
+	  listnode_delete (rn->info, or);
+	  ospf_route_free (or);
+	  /* proceed down */
+	}
+      /* Routes are the same */
+      else if (ret == 0)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_ia_router_route(): merging the new route");
+
+	  ospf_route_copy_nexthops (or, abr_or->path);
+	  ospf_route_free (new_or);
+	  return;
+	}
+      /* New route is worse */
+      else
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_ia_router_route(): skipping the new route");
+	  ospf_route_free (new_or);
+	  return;
+	}
+    }
+
+  ospf_route_copy_nexthops (new_or, abr_or->path);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_ia_router_route(): adding the new route"); 
+
+  listnode_add (rn->info, new_or);
+}
+
+
+struct ia_args
+{
+  struct route_table *rt;
+  struct route_table *rtrs;
+  struct ospf_area *area;
+};
+
+int
+process_summary_lsa (struct ospf_lsa *l, void *v, int i)
+{
+  struct ospf_area_range *range;
+  struct ospf_route *abr_or, *new_or;
+  struct summary_lsa *sl;
+  struct prefix_ipv4 p, abr;
+  u_int32_t metric;
+  struct ia_args *args;
+
+  if (l == NULL)
+    return 0;
+
+  args = (struct ia_args *) v;
+  sl = (struct summary_lsa *) l->data;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("process_summary_lsa(): LS ID: %s", inet_ntoa (sl->header.id));
+
+  metric = GET_METRIC (sl->metric);
+   
+  if (metric == OSPF_LS_INFINITY)
+    return 0;
+
+  if (IS_LSA_MAXAGE (l))
+    return 0;
+
+  if (ospf_lsa_is_self_originated (l))
+    return 0;
+
+  p.family = AF_INET;
+  p.prefix = sl->header.id;
+   
+  if (sl->header.type == OSPF_SUMMARY_LSA)
+    p.prefixlen = ip_masklen (sl->mask);
+  else
+    p.prefixlen = IPV4_MAX_BITLEN;
+      
+  apply_mask_ipv4 (&p);
+
+  if (sl->header.type == OSPF_SUMMARY_LSA &&
+      (range = ospf_area_range_match_any (ospf_top, &p)) &&
+      ospf_area_range_active (range))
+    return 0;
+
+  if (ospf_top->abr_type != OSPF_ABR_STAND &&
+      args->area->external_routing != OSPF_AREA_DEFAULT &&
+      p.prefix.s_addr == OSPF_DEFAULT_DESTINATION &&
+      p.prefixlen == 0)
+    return 0; /* Ignore summary default from a stub area */
+
+  abr.family = AF_INET;
+  abr.prefix = sl->header.adv_router;
+  abr.prefixlen = IPV4_MAX_BITLEN;
+  apply_mask_ipv4 (&abr);
+
+  abr_or = ospf_find_abr_route (args->rtrs, &abr, args->area);
+
+  if (abr_or == NULL)
+    return 0;
+
+  new_or = ospf_route_new ();
+  new_or->type = OSPF_DESTINATION_NETWORK;
+  new_or->id = sl->header.id;
+  new_or->mask = sl->mask;
+  new_or->u.std.options = sl->header.options;
+  new_or->u.std.origin = (struct lsa_header *) sl;
+  new_or->cost = abr_or->cost + metric;
+  new_or->u.std.area_id = args->area->area_id;
+#ifdef HAVE_NSSA
+  new_or->u.std.external_routing = args->area->external_routing;
+#endif /* HAVE_NSSA */
+  new_or->path_type = OSPF_PATH_INTER_AREA;
+
+  if (sl->header.type == OSPF_SUMMARY_LSA)
+    ospf_ia_network_route (args->rt, &p, new_or, abr_or);
+  else 
+    {
+      new_or->type = OSPF_DESTINATION_ROUTER;
+      new_or->u.std.flags = ROUTER_LSA_EXTERNAL;
+      ospf_ia_router_route (args->rtrs, &p, new_or, abr_or);
+    }
+
+  return 0;
+}
+
+void
+ospf_examine_summaries (struct ospf_area * area,
+			struct route_table *lsdb_rt,
+                        struct route_table *rt,
+                        struct route_table *rtrs)
+{
+  struct ia_args args = {rt, rtrs, area};
+  foreach_lsa (lsdb_rt, &args, 0, process_summary_lsa);
+}
+
+int
+ospf_area_is_transit (struct ospf_area *area)
+{
+  return (area->transit == OSPF_TRANSIT_TRUE) ||
+    ospf_full_virtual_nbrs(area); /* Cisco forgets to set the V-bit :( */
+}
+
+void
+ospf_update_network_route (struct route_table *rt, 
+                           struct route_table *rtrs,
+                           struct summary_lsa *lsa,
+                           struct prefix_ipv4 *p,
+                           struct ospf_area *area)
+{
+  struct route_node *rn;
+  struct ospf_route *or, *abr_or, *new_or;
+  struct prefix_ipv4 abr;
+  u_int32_t cost;
+
+  abr.family = AF_INET;
+  abr.prefix =lsa->header.adv_router;
+  abr.prefixlen = IPV4_MAX_BITLEN;
+  apply_mask_ipv4 (&abr);
+
+  abr_or = ospf_find_abr_route (rtrs, &abr, area);
+
+  if (abr_or == NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_update_network_route(): can't find a route to the ABR");
+      return;
+    }
+
+  cost = abr_or->cost + GET_METRIC (lsa->metric);
+
+  rn = route_node_lookup (rt, (struct prefix *) p);
+
+  if (! rn)
+    {
+      if (ospf_top->abr_type != OSPF_ABR_SHORTCUT)
+        return; /* Standard ABR can update only already installed
+                   backbone paths                                       */
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_update_network_route(): "
+		   "Allowing Shortcut ABR to add new route");
+      new_or = ospf_route_new ();
+      new_or->type = OSPF_DESTINATION_NETWORK;
+      new_or->id = lsa->header.id;
+      new_or->mask = lsa->mask;
+      new_or->u.std.options = lsa->header.options;
+      new_or->u.std.origin = (struct lsa_header *) lsa;
+      new_or->cost = cost;
+      new_or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+      new_or->u.std.external_routing = area->external_routing;
+#endif /* HAVE_NSSA */
+      new_or->path_type = OSPF_PATH_INTER_AREA;
+      ospf_route_add (rt, p, new_or, abr_or);
+
+      return;
+    }
+  else
+    {
+      route_unlock_node (rn);
+      if (rn->info == NULL)
+        return;
+    }
+
+  or = rn->info;
+
+  if (or->path_type != OSPF_PATH_INTRA_AREA &&
+      or->path_type != OSPF_PATH_INTER_AREA)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_update_network_route(): ERR: path type is wrong");
+      return;
+    }
+
+  if (ospf_top->abr_type == OSPF_ABR_SHORTCUT)
+    {
+      if (or->path_type == OSPF_PATH_INTRA_AREA &&
+	  !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_update_network_route(): Shortcut: "
+		       "this intra-area path is not backbone");
+	  return;
+	}
+    }
+  else   /* Not Shortcut ABR */
+    {
+      if (!OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_update_network_route(): "
+		       "route is not BB-associated");
+	  return; /* We can update only BB routes */
+	}
+    }
+
+  if (or->cost < cost)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_update_network_route(): new route is worse");
+      return;
+    }
+
+  if (or->cost == cost)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_update_network_route(): "
+		   "new route is same distance, adding nexthops");
+      ospf_route_copy_nexthops (or, abr_or->path);
+    }
+
+  if (or->cost > cost)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_update_network_route(): "
+		   "new route is better, overriding nexthops");
+      ospf_route_subst_nexthops (or, abr_or->path);
+      or->cost = cost;
+
+      if ((ospf_top->abr_type == OSPF_ABR_SHORTCUT) &&
+	  !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id))
+	{
+	  or->path_type = OSPF_PATH_INTER_AREA;
+	  or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+	  or->u.std.external_routing = area->external_routing;
+#endif /* HAVE_NSSA */
+          /* Note that we can do this only in Shortcut ABR mode,
+             because standard ABR must leave the route type and area
+             unchanged
+          */
+        }
+    }
+}
+
+void
+ospf_update_router_route (struct route_table *rtrs, 
+                          struct summary_lsa *lsa,
+                          struct prefix_ipv4 *p,
+                          struct ospf_area *area)
+{
+  struct ospf_route *or, *abr_or, *new_or;
+  struct prefix_ipv4 abr;
+  u_int32_t cost;
+
+  abr.family = AF_INET;
+  abr.prefix = lsa->header.adv_router;
+  abr.prefixlen = IPV4_MAX_BITLEN;
+  apply_mask_ipv4 (&abr);
+
+  abr_or = ospf_find_abr_route (rtrs, &abr, area);
+
+  if (abr_or == NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_update_router_route(): can't find a route to the ABR");
+      return;
+    }
+
+  cost = abr_or->cost + GET_METRIC (lsa->metric);
+
+  /* First try to find a backbone path,
+     because standard ABR can update only BB-associated paths */
+
+  if ((ospf_top->backbone == NULL) &&
+      (ospf_top->abr_type != OSPF_ABR_SHORTCUT))
+
+     /* no BB area, not Shortcut ABR, exiting */
+     return;
+ 
+  or = ospf_find_asbr_route_through_area (rtrs, p, ospf_top->backbone);
+
+  if (or == NULL)
+    {
+      if (ospf_top->abr_type != OSPF_ABR_SHORTCUT)
+
+         /* route to ASBR through the BB not found
+            the router is not Shortcut ABR, exiting */
+
+          return;
+      else
+	/* We're a Shortcut ABR*/
+	{
+	  /* Let it either add a new router or update the route
+	     through the same (non-BB) area. */
+
+	  new_or = ospf_route_new ();
+	  new_or->type = OSPF_DESTINATION_ROUTER;
+	  new_or->id = lsa->header.id;
+	  new_or->mask = lsa->mask;
+	  new_or->u.std.options = lsa->header.options;
+	  new_or->u.std.origin = (struct lsa_header *)lsa;
+	  new_or->cost = cost;
+	  new_or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+	  new_or->u.std.external_routing = area->external_routing;
+#endif /* HAVE_NSSA */
+	  new_or->path_type = OSPF_PATH_INTER_AREA;
+	  new_or->u.std.flags = ROUTER_LSA_EXTERNAL;
+	  ospf_ia_router_route (rtrs, p, new_or, abr_or);
+
+          return;
+        }
+    }
+
+  /* At this point the "or" is always bb-associated */
+
+  if (!(or->u.std.flags & ROUTER_LSA_EXTERNAL))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_upd_router_route(): the remote router is not an ASBR");
+      return;
+    }
+
+  if (or->path_type != OSPF_PATH_INTRA_AREA &&
+      or->path_type != OSPF_PATH_INTER_AREA)
+    return;
+
+  if (or->cost < cost)
+    return;
+
+  else if (or->cost == cost)
+    ospf_route_copy_nexthops (or, abr_or->path);
+
+  else if (or->cost > cost)
+    {
+      ospf_route_subst_nexthops (or, abr_or->path);
+      or->cost = cost;
+
+      /* Even if the ABR runs in Shortcut mode, we can't change
+         the path type and area, because the "or" is always bb-associated
+         at this point and even Shortcut ABR can't change these attributes */
+    }
+}
+
+int
+process_transit_summary_lsa (struct ospf_lsa *l, void *v, int i)
+{
+  struct summary_lsa *sl;
+  struct prefix_ipv4 p;
+  u_int32_t metric;
+  struct ia_args *args;
+
+  if (l == NULL)
+    return 0;
+
+  args = (struct ia_args *) v;
+  sl = (struct summary_lsa *) l->data;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("process_transit_summaries(): LS ID: %s",
+	       inet_ntoa (l->data->id));
+  metric = GET_METRIC (sl->metric);
+   
+  if (metric == OSPF_LS_INFINITY)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("process_transit_summaries(): metric is infinity, skip");
+      return 0;
+    }
+
+  if (IS_LSA_MAXAGE (l))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("process_transit_summaries(): This LSA is too old");
+      return 0;
+    }
+
+  if (ospf_lsa_is_self_originated (l))
+    { 
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("process_transit_summaries(): This LSA is mine, skip");
+      return 0;
+    }
+
+  p.family = AF_INET;
+  p.prefix = sl->header.id;
+   
+  if (sl->header.type == OSPF_SUMMARY_LSA)
+    p.prefixlen = ip_masklen (sl->mask);
+  else
+    p.prefixlen = IPV4_MAX_BITLEN;
+      
+  apply_mask_ipv4 (&p);
+
+  if (sl->header.type == OSPF_SUMMARY_LSA)
+    ospf_update_network_route (args->rt, args->rtrs, sl, &p, args->area);
+  else
+    ospf_update_router_route (args->rtrs, sl, &p, args->area);
+ 
+  return 0;
+}
+
+void
+ospf_examine_transit_summaries (struct ospf_area *area,
+                                /* struct ospf_lsdb *lsdb, */
+				struct route_table *lsdb_rt,
+                                struct route_table *rt,
+                                struct route_table *rtrs)
+{
+  struct ia_args args = {rt, rtrs, area};
+
+  /* ospf_lsdb_iterator (lsdb, &args, 0, process_transit_summary_lsa); */
+  foreach_lsa (lsdb_rt, &args, 0, process_transit_summary_lsa);
+}
+
+void
+ospf_ia_routing (struct route_table *rt,
+                 struct route_table *rtrs)
+{
+  struct ospf_area * area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_ia_routing():start");
+
+  if (OSPF_IS_ABR)
+    {
+      listnode node; 
+      struct ospf_area *area;
+
+      switch (ospf_top->abr_type)
+        {
+        case OSPF_ABR_STAND:
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_ia_routing():Standard ABR");
+
+          if ((area = ospf_top->backbone))
+            {
+              listnode node;
+
+	      if (IS_DEBUG_OSPF_EVENT)
+		{
+		  zlog_info ("ospf_ia_routing():backbone area found");
+		  zlog_info ("ospf_ia_routing():examining summaries");
+		}
+
+              OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs);
+
+	      for (node = listhead (ospf_top->areas); node; nextnode (node))
+                if ((area = getdata (node)) != NULL)
+                  if (area != ospf_top->backbone)
+		    if (ospf_area_is_transit (area))
+		      OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs);
+            }
+          else
+	    if (IS_DEBUG_OSPF_EVENT)
+	      zlog_info ("ospf_ia_routing():backbone area NOT found");
+          break;
+        case OSPF_ABR_IBM:
+        case OSPF_ABR_CISCO:
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_ia_routing():Alternative Cisco/IBM ABR");
+          area = ospf_top->backbone; /* Find the BB */
+
+          /* If we have an active BB connection */
+          if (area && ospf_act_bb_connection ())
+            {
+	      if (IS_DEBUG_OSPF_EVENT)
+		{
+		  zlog_info ("ospf_ia_routing(): backbone area found");
+		  zlog_info ("ospf_ia_routing(): examining BB summaries");
+		}
+
+              OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs);
+
+	      for (node = listhead (ospf_top->areas); node; nextnode (node))
+                if ((area = getdata (node)) != NULL)
+                  if (area != ospf_top->backbone)
+		    if (ospf_area_is_transit (area))
+		      OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs);
+            }
+          else
+            { /* No active BB connection--consider all areas */
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("ospf_ia_routing(): "
+			   "Active BB connection not found");
+	      for (node = listhead (ospf_top->areas); node; nextnode (node))
+                if ((area = getdata (node)) != NULL)
+                  OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs);
+            }
+          break;
+        case OSPF_ABR_SHORTCUT:
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_ia_routing():Alternative Shortcut");
+          area = ospf_top->backbone; /* Find the BB */
+
+          /* If we have an active BB connection */
+          if (area && ospf_act_bb_connection ())
+            {
+	      if (IS_DEBUG_OSPF_EVENT)
+		{
+		  zlog_info ("ospf_ia_routing(): backbone area found");
+		  zlog_info ("ospf_ia_routing(): examining BB summaries");
+		}
+              OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs);
+            }
+
+	  for (node = listhead (ospf_top->areas); node; nextnode (node))
+            if ((area = getdata (node)) != NULL)
+              if (area != ospf_top->backbone)
+		if (ospf_area_is_transit (area) ||
+		    ((area->shortcut_configured != OSPF_SHORTCUT_DISABLE) &&
+		     ((ospf_top->backbone == NULL) ||
+                      ((area->shortcut_configured == OSPF_SHORTCUT_ENABLE) &&
+		       area->shortcut_capability))))
+		  OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs);
+          break;
+        default:
+          break;
+        }
+    }
+  else 
+    {
+      listnode node;
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_ia_routing():not ABR, considering all areas");
+
+      for (node = listhead (ospf_top->areas); node; nextnode (node))
+        if ((area = getdata (node)) != NULL)
+          OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs);
+    }
+}
diff --git a/ospfd/ospf_ia.h b/ospfd/ospf_ia.h
new file mode 100644
index 0000000..afb2d4d
--- /dev/null
+++ b/ospfd/ospf_ia.h
@@ -0,0 +1,42 @@
+/*
+ * OSPF inter-area routing.
+ * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_IA_H
+#define _ZEBRA_OSPF_IA_H
+
+/* Macros. */
+#define OSPF_EXAMINE_SUMMARIES_ALL(A,N,R) \
+	{ \
+	  ospf_examine_summaries ((A), SUMMARY_LSDB ((A)), (N), (R)); \
+	  ospf_examine_summaries ((A), ASBR_SUMMARY_LSDB ((A)), (N), (R)); \
+	}
+
+#define OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(A,N,R) \
+	{ \
+	  ospf_examine_transit_summaries ((A), SUMMARY_LSDB ((A)), (N), (R)); \
+	  ospf_examine_transit_summaries ((A), ASBR_SUMMARY_LSDB ((A)), (N), (R)); \
+	}
+
+void ospf_ia_routing (struct route_table *, struct route_table *);
+int ospf_area_is_transit (struct ospf_area *);
+
+#endif /* _ZEBRA_OSPF_IA_H */
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
new file mode 100644
index 0000000..ddae980
--- /dev/null
+++ b/ospfd/ospf_interface.c
@@ -0,0 +1,1045 @@
+/*
+ * OSPF Interface functions.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ * 
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "memory.h"
+#include "command.h"
+#include "stream.h"
+#include "log.h"
+
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_network.h"
+#include "ospfd/ospf_dump.h"
+#ifdef HAVE_SNMP
+#include "ospfd/ospf_snmp.h"
+#endif /* HAVE_SNMP */
+
+
+int
+ospf_if_get_output_cost (struct ospf_interface *oi)
+{
+  /* If all else fails, use default OSPF cost */
+  u_int32_t cost;
+  u_int32_t bw, refbw;
+
+  bw = oi->ifp->bandwidth ? oi->ifp->bandwidth : OSPF_DEFAULT_BANDWIDTH;
+  refbw = ospf_top ? ospf_top->ref_bandwidth : OSPF_DEFAULT_REF_BANDWIDTH;
+
+  /* A specifed ip ospf cost overrides a calculated one. */
+  if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (oi->ifp), output_cost_cmd) ||
+      OSPF_IF_PARAM_CONFIGURED (oi->params, output_cost_cmd))
+    cost = OSPF_IF_PARAM (oi, output_cost_cmd);
+  /* See if a cost can be calculated from the zebra processes
+     interface bandwidth field. */
+  else
+    {
+      cost = (u_int32_t) ((double)refbw / (double)bw + (double)0.5);
+      if (cost < 1)
+	cost = 1;
+      else if (cost > 65535)
+	cost = 65535;
+    }
+
+  return cost;
+}
+
+void
+ospf_if_recalculate_output_cost (struct interface *ifp)
+{
+  u_int32_t newcost;
+  struct route_node *rn;
+  
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi;
+      
+      if ( (oi = rn->info) == NULL)
+	continue;
+
+      newcost = ospf_if_get_output_cost (oi);
+
+      /* Is actual output cost changed? */
+      if (oi->output_cost != newcost)
+	{
+	  oi->output_cost = newcost;
+	  ospf_router_lsa_timer_add (oi->area);
+	}
+    }
+}
+
+void
+ospf_if_reset_variables (struct ospf_interface *oi)
+{
+  /* Set default values. */
+  /* don't clear this flag.  oi->flag = OSPF_IF_DISABLE; */
+
+  if (oi->vl_data)
+    oi->type = OSPF_IFTYPE_VIRTUALLINK;
+  else 
+  /* preserve network-type */
+  if (oi->type != OSPF_IFTYPE_NBMA)
+    oi->type = OSPF_IFTYPE_BROADCAST;
+
+  oi->state = ISM_Down;
+
+  oi->crypt_seqnum = 0;
+
+  /* This must be short, (less than RxmtInterval) 
+     - RFC 2328 Section 13.5 para 3.  Set to 1 second to avoid Acks being
+       held back for too long - MAG */
+  oi->v_ls_ack = 1;  
+}
+
+void
+ospf_add_to_if (struct interface *ifp, struct ospf_interface *oi)
+{
+  struct route_node *rn;
+  struct prefix p;
+
+  p = *oi->address;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+
+  rn = route_node_get (IF_OIFS (ifp), &p);
+  assert (! rn->info);
+  rn->info = oi;
+}
+
+void
+ospf_delete_from_if (struct interface *ifp, struct ospf_interface *oi)
+{
+  struct route_node *rn;
+  struct prefix p;
+
+  p = *oi->address;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+
+  rn = route_node_lookup (IF_OIFS (oi->ifp), &p);
+  assert (rn);
+  assert (rn->info);
+  rn->info = NULL;
+  route_unlock_node (rn);
+  route_unlock_node (rn);
+}
+
+struct ospf_interface *
+ospf_if_new (struct interface *ifp, struct prefix *p)
+{
+  struct ospf_interface *oi;
+
+  oi = XCALLOC (MTYPE_OSPF_IF, sizeof (struct ospf_interface));
+  memset (oi, 0, sizeof (struct ospf_interface));
+
+  /* Set zebra interface pointer. */
+  oi->ifp = ifp;
+  oi->address = p;
+  
+  ospf_add_to_if (ifp, oi);
+  listnode_add (ospf_top->oiflist, oi);
+  
+  /* Clear self-originated network-LSA. */
+  oi->network_lsa_self = NULL;
+
+  /* Initialize neighbor list. */
+  oi->nbrs = route_table_init ();
+
+  /* Initialize static neighbor list. */
+  oi->nbr_nbma = list_new ();
+
+  /* Initialize Link State Acknowledgment list. */
+  oi->ls_ack = list_new ();
+  oi->ls_ack_direct.ls_ack = list_new ();
+
+  /* Set default values. */
+  ospf_if_reset_variables (oi);
+
+  /* Add pseudo neighbor. */
+  oi->nbr_self = ospf_nbr_new (oi);
+  oi->nbr_self->state = NSM_TwoWay;
+  /*  oi->nbr_self->router_id = ospf_top->router_id; */
+  oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
+  oi->nbr_self->options = OSPF_OPTION_E;
+
+  oi->ls_upd_queue = route_table_init ();
+  oi->t_ls_upd_event = NULL;
+  oi->t_ls_ack_direct = NULL;
+
+#ifdef HAVE_OPAQUE_LSA
+  ospf_opaque_type9_lsa_init (oi);
+#endif /* HAVE_OPAQUE_LSA */
+
+  oi->ospf = ospf_top;
+  
+  return oi;
+}
+
+/* Restore an interface to its pre UP state
+   Used from ism_interface_down only */
+void
+ospf_if_cleanup (struct ospf_interface *oi)
+{
+  struct route_node *rn;
+  listnode node;
+  struct ospf_neighbor *nbr;
+
+  /* oi->nbrs and oi->nbr_nbma should be deletete on InterafceDown event */
+  /* delete all static neighbors attached to this interface */
+  for (node = listhead (oi->nbr_nbma); node; )
+    {
+      struct ospf_nbr_nbma *nbr_nbma = getdata (node);
+      nextnode (node);
+
+      OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
+
+      if (nbr_nbma->nbr)
+	{
+	  nbr_nbma->nbr->nbr_nbma = NULL;
+	  nbr_nbma->nbr = NULL;
+	}
+
+      nbr_nbma->oi = NULL;
+      
+      listnode_delete (oi->nbr_nbma, nbr_nbma);
+    }
+
+  /* send Neighbor event KillNbr to all associated neighbors. */
+  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+    if ((nbr = rn->info) != NULL)
+      if (nbr != oi->nbr_self)
+	OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr);
+
+  /* Cleanup Link State Acknowlegdment list. */
+  for (node = listhead (oi->ls_ack); node; nextnode (node))
+    ospf_lsa_unlock (node->data);
+  list_delete_all_node (oi->ls_ack);
+
+  oi->crypt_seqnum = 0;
+  
+  /* Empty link state update queue */
+  ospf_ls_upd_queue_empty (oi);
+  
+ /* Handle pseudo neighbor. */
+  ospf_nbr_delete (oi->nbr_self);
+  oi->nbr_self = ospf_nbr_new (oi);
+  oi->nbr_self->state = NSM_TwoWay;
+  oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
+  oi->nbr_self->options = OSPF_OPTION_E;
+
+  ospf_lsa_unlock (oi->network_lsa_self);
+  oi->network_lsa_self = NULL;
+  OSPF_TIMER_OFF (oi->t_network_lsa_self);
+}
+
+void
+ospf_if_free (struct ospf_interface *oi)
+{
+  ospf_if_down (oi);
+
+  assert (oi->state == ISM_Down);
+
+#ifdef HAVE_OPAQUE_LSA
+  ospf_opaque_type9_lsa_term (oi);
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* Free Pseudo Neighbour */
+  ospf_nbr_delete (oi->nbr_self);
+  
+  route_table_finish (oi->nbrs);
+  route_table_finish (oi->ls_upd_queue);
+  
+  /* Free any lists that should be freed */
+  list_free (oi->nbr_nbma);
+  
+  list_free (oi->ls_ack);
+  list_free (oi->ls_ack_direct.ls_ack);
+  
+  ospf_delete_from_if (oi->ifp, oi);
+
+  listnode_delete (ospf_top->oiflist, oi);
+  listnode_delete (oi->area->oiflist, oi);
+
+  memset (oi, 0, sizeof (*oi));
+  XFREE (MTYPE_OSPF_IF, oi);
+}
+
+
+/*
+*  check if interface with given address is configured and
+*  return it if yes.
+*/
+struct ospf_interface *
+ospf_if_is_configured (struct in_addr *address)
+{
+  listnode node;
+  struct ospf_interface *oi;
+  struct prefix *addr;
+  
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
+      {
+	if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+	  addr = oi->connected->destination;
+	else
+	  addr = oi->address;
+	
+	if (IPV4_ADDR_SAME (address, &addr->u.prefix4))
+	  return oi;
+      }
+
+  return NULL;
+}
+
+int
+ospf_if_is_up (struct ospf_interface *oi)
+{
+  return if_is_up (oi->ifp);
+}
+
+struct ospf_interface *
+ospf_if_lookup_by_local_addr (struct interface *ifp, struct in_addr address)
+{
+  listnode node;
+  struct ospf_interface *oi;
+  
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
+      {
+	if (ifp && oi->ifp != ifp)
+	  continue;
+	
+	if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
+	  return oi;
+      }
+
+  return NULL;
+}
+
+struct ospf_interface *
+ospf_if_lookup_by_prefix (struct prefix_ipv4 *p)
+{
+  listnode node;
+  struct ospf_interface *oi;
+  struct prefix ptmp;
+  
+  /* Check each Interface. */
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node)) {
+    if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
+      {
+	if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
+	  prefix_copy (&ptmp, oi->connected->destination);
+	  ptmp.prefixlen = IPV4_MAX_BITLEN;
+	}
+	else
+	  prefix_copy (&ptmp, oi->address);
+	
+	apply_mask (&ptmp);
+	if (prefix_same (&ptmp, (struct prefix *) p))
+	  return oi;
+      }
+  }
+  return NULL;
+}
+
+/* determine receiving interface by source of packet */
+struct ospf_interface *
+ospf_if_lookup_recv_interface (struct in_addr src)
+{
+  listnode node;
+  struct prefix_ipv4 addr;
+  struct ospf_interface *oi, *match;
+
+  addr.family = AF_INET;
+  addr.prefix = src;
+  addr.prefixlen = IPV4_MAX_BITLEN;
+
+  match = NULL;
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      oi = getdata (node);
+      
+      if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+	continue;
+      
+      if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+	{
+	  if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
+	    return oi;
+	}
+      else
+	{
+	  if (prefix_match (oi->address, (struct prefix *) &addr))
+	    match = oi;
+	}
+    }
+
+  return match;
+}
+
+void
+ospf_if_stream_set (struct ospf_interface *oi)
+{
+  /* set output fifo queue. */
+  if (oi->obuf == NULL) 
+    oi->obuf = ospf_fifo_new ();
+}
+
+void
+ospf_if_stream_unset (struct ospf_interface *oi)
+{
+  if (oi->obuf)
+    {
+     ospf_fifo_free (oi->obuf);
+     oi->obuf = NULL;
+
+     if (oi->on_write_q)
+       {
+	 listnode_delete (ospf_top->oi_write_q, oi);
+         if (list_isempty(ospf_top->oi_write_q))
+           OSPF_TIMER_OFF (ospf_top->t_write);
+	 oi->on_write_q = 0;
+       }
+    }
+}
+
+struct ospf_if_params *
+ospf_new_if_params ()
+{
+  struct ospf_if_params *oip;
+
+  oip = XMALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params));
+  memset (oip, 0, sizeof (struct ospf_if_params));
+
+  if (!oip)
+    return NULL;
+
+  memset (oip, 0, sizeof (struct ospf_if_params));
+
+  UNSET_IF_PARAM (oip, output_cost_cmd);
+  UNSET_IF_PARAM (oip, transmit_delay);
+  UNSET_IF_PARAM (oip, retransmit_interval);
+  UNSET_IF_PARAM (oip, passive_interface);
+  UNSET_IF_PARAM (oip, v_hello);
+  UNSET_IF_PARAM (oip, v_wait);
+  UNSET_IF_PARAM (oip, priority);
+  UNSET_IF_PARAM (oip, type);
+  UNSET_IF_PARAM (oip, auth_simple);
+  UNSET_IF_PARAM (oip, auth_crypt);
+  UNSET_IF_PARAM (oip, auth_type);
+  
+  oip->auth_crypt = list_new ();
+
+  return oip;
+}
+
+void
+ospf_del_if_params (struct ospf_if_params *oip)
+{
+  list_delete (oip->auth_crypt);
+  XFREE (MTYPE_OSPF_IF_PARAMS, oip);
+}
+
+void
+ospf_free_if_params (struct interface *ifp, struct in_addr addr)
+{
+  struct ospf_if_params *oip;
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+  p.prefix = addr;
+  rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
+  if (!rn || !rn->info)
+    return;
+
+  oip = rn->info;
+  route_unlock_node (rn);
+  
+  if (!OSPF_IF_PARAM_CONFIGURED (oip, output_cost_cmd) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, transmit_delay) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, retransmit_interval) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, passive_interface) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, v_hello) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, v_wait) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, priority) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, type) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) &&
+      !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) &&
+      listcount (oip->auth_crypt) == 0)
+    {
+      ospf_del_if_params (oip);
+      rn->info = NULL;
+      route_unlock_node (rn);
+    }
+}
+
+struct ospf_if_params *
+ospf_lookup_if_params (struct interface *ifp, struct in_addr addr)
+{
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+  p.prefix = addr;
+
+  rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
+  
+  if (rn)
+    {
+      route_unlock_node (rn);
+      return rn->info;
+    }
+
+  return NULL;
+}
+
+struct ospf_if_params *
+ospf_get_if_params (struct interface *ifp, struct in_addr addr)
+{
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+  p.prefix = addr;
+
+  rn = route_node_get (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
+  
+  if (rn->info == NULL)
+    rn->info = ospf_new_if_params ();
+  else
+    route_unlock_node (rn);
+  
+  return rn->info;
+}
+
+void
+ospf_if_update_params (struct interface *ifp, struct in_addr addr)
+{
+  struct route_node *rn;
+  struct ospf_interface *oi;
+  
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      if ((oi = rn->info) == NULL)
+	continue;
+
+      if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &addr))
+	oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
+    }
+}
+
+int
+ospf_if_new_hook (struct interface *ifp)
+{
+  int rc = 0;
+
+  ifp->info = XMALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info));
+  memset (ifp->info, 0, sizeof (struct ospf_if_info));
+  
+  IF_OIFS (ifp) = route_table_init ();
+  IF_OIFS_PARAMS (ifp) = route_table_init ();
+  
+  IF_DEF_PARAMS (ifp) = ospf_new_if_params ();
+  
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay);
+  IF_DEF_PARAMS (ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
+  
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval);
+  IF_DEF_PARAMS (ifp)->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
+
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), priority);
+  IF_DEF_PARAMS (ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
+
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), passive_interface);
+  IF_DEF_PARAMS (ifp)->passive_interface = OSPF_IF_ACTIVE;
+
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
+  IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
+
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
+  IF_DEF_PARAMS (ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
+
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_simple);
+  memset (IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE);
+  
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_crypt);
+  IF_DEF_PARAMS (ifp)->auth_crypt = list_new ();
+
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
+  IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET;
+  
+#ifdef HAVE_OPAQUE_LSA
+  rc = ospf_opaque_new_if (ifp);
+#endif /* HAVE_OPAQUE_LSA */
+  return rc;
+}
+
+int
+ospf_if_delete_hook (struct interface *ifp)
+{
+  int rc = 0;
+#ifdef HAVE_OPAQUE_LSA
+  rc = ospf_opaque_del_if (ifp);
+#endif /* HAVE_OPAQUE_LSA */
+  route_table_finish (IF_OIFS (ifp));
+  route_table_finish (IF_OIFS_PARAMS (ifp));
+  XFREE (MTYPE_OSPF_IF_INFO, ifp->info);
+  ifp->info = NULL;
+
+  return rc;
+}
+
+int
+ospf_if_is_enable (struct ospf_interface *oi)
+{
+  if (!if_is_loopback (oi->ifp))
+    if (if_is_up (oi->ifp))
+	return 1;
+
+  return 0;
+}
+
+int
+ospf_if_up (struct ospf_interface *oi)
+{
+  if (oi == NULL)
+    return 0;
+
+  if (oi->type == OSPF_IFTYPE_LOOPBACK)
+    OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd);
+  else
+    {
+      if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
+	ospf_if_add_allspfrouters (ospf_top, oi->address, oi->ifp->ifindex);
+      ospf_if_stream_set (oi);
+      OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
+    }
+
+  return 1;
+}
+
+int
+ospf_if_down (struct ospf_interface *oi)
+{
+  if (oi == NULL)
+    return 0;
+
+  OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
+  /* Shutdown packet reception and sending */
+  ospf_if_stream_unset (oi);
+  if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
+    ospf_if_drop_allspfrouters (ospf_top, oi->address, oi->ifp->ifindex);
+
+
+  return 1;
+}
+
+
+/* Virtual Link related functions. */
+
+struct ospf_vl_data *
+ospf_vl_data_new (struct ospf_area *area, struct in_addr vl_peer)
+{
+  struct ospf_vl_data *vl_data;
+
+  vl_data = XMALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data));
+  memset (vl_data, 0, sizeof (struct ospf_vl_data));
+
+  vl_data->vl_peer.s_addr = vl_peer.s_addr;
+  vl_data->vl_area_id = area->area_id;
+  vl_data->format = area->format;
+
+  return vl_data;
+}
+
+void
+ospf_vl_data_free (struct ospf_vl_data *vl_data)
+{
+  XFREE (MTYPE_OSPF_VL_DATA, vl_data);
+}
+
+u_int vlink_count = 0;
+
+struct ospf_interface * 
+ospf_vl_new (struct ospf_vl_data *vl_data)
+{
+  struct ospf_interface * voi;
+  struct interface * vi;
+  char   ifname[INTERFACE_NAMSIZ + 1];
+  struct ospf_area *area;
+  struct in_addr area_id;
+  struct connected *co;
+  struct prefix_ipv4 *p;
+  
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_vl_new(): Start");
+  if (vlink_count == OSPF_VL_MAX_COUNT)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_vl_new(): Alarm: "
+		   "cannot create more than OSPF_MAX_VL_COUNT virtual links");
+      return NULL;
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_vl_new(): creating pseudo zebra interface");
+
+  vi = if_create ();
+  co = connected_new ();
+  co->ifp = vi;
+  listnode_add (vi->connected, co);
+
+  p = prefix_ipv4_new ();
+  p->family = AF_INET;
+  p->prefix.s_addr = 0;
+  p->prefixlen = 0;
+ 
+  co->address = (struct prefix *)p;
+  
+  voi = ospf_if_new (vi, co->address);
+  if (voi == NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_vl_new(): Alarm: OSPF int structure is not created");
+      return NULL;
+    }
+  voi->connected = co;
+  voi->vl_data = vl_data;
+  voi->ifp->mtu = OSPF_VL_MTU;
+  voi->type = OSPF_IFTYPE_VIRTUALLINK;
+
+  sprintf (ifname, "VLINK%d", vlink_count++);
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_vl_new(): Created name: %s", ifname);
+  strncpy (vi->name, ifname, IFNAMSIZ);
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_vl_new(): set if->name to %s", vi->name);
+
+  area_id.s_addr = 0;
+  area = ospf_area_get (area_id, OSPF_AREA_ID_FORMAT_ADDRESS);
+  voi->area = area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_vl_new(): set associated area to the backbone");
+
+  ospf_area_add_if (voi->area, voi);
+
+  ospf_if_stream_set (voi);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_vl_new(): Stop");
+  return voi;
+}
+
+void
+ospf_vl_if_delete (struct ospf_vl_data *vl_data)
+{
+  struct interface *ifp = vl_data->vl_oi->ifp;
+  vl_data->vl_oi->address->u.prefix4.s_addr = 0;
+  vl_data->vl_oi->address->prefixlen = 0;
+  ospf_if_free (vl_data->vl_oi);
+  if_delete (ifp);
+  vlink_count--;
+}
+
+struct ospf_vl_data *
+ospf_vl_lookup (struct ospf_area *area, struct in_addr vl_peer)
+{
+  struct ospf_vl_data *vl_data;
+  listnode node;
+
+  for (node = listhead (ospf_top->vlinks); node; nextnode (node))
+    if ((vl_data = getdata (node)) != NULL)
+      if (vl_data->vl_peer.s_addr == vl_peer.s_addr &&
+          IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
+        return vl_data;
+
+  return NULL;
+}
+
+void 
+ospf_vl_shutdown (struct ospf_vl_data *vl_data)
+{
+  struct ospf_interface *oi;
+
+  if ((oi = vl_data->vl_oi) == NULL)
+    return;
+
+  oi->address->u.prefix4.s_addr = 0;
+  oi->address->prefixlen = 0;
+
+  UNSET_FLAG (oi->ifp->flags, IFF_UP);
+  /* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */
+  OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
+}
+
+void
+ospf_vl_add (struct ospf_vl_data *vl_data)
+{
+  listnode_add (ospf_top->vlinks, vl_data);
+#ifdef HAVE_SNMP
+  ospf_snmp_vl_add (vl_data);
+#endif /* HAVE_SNMP */
+}
+
+void
+ospf_vl_delete (struct ospf_vl_data *vl_data)
+{
+  ospf_vl_shutdown (vl_data);
+  ospf_vl_if_delete (vl_data);
+
+#ifdef HAVE_SNMP
+  ospf_snmp_vl_delete (vl_data);
+#endif /* HAVE_SNMP */
+  listnode_delete (ospf_top->vlinks, vl_data);
+
+  ospf_vl_data_free (vl_data);
+}
+
+void
+ospf_vl_set_params (struct ospf_vl_data *vl_data, struct vertex *v)
+{
+  int changed = 0;
+  struct ospf_interface *voi;
+  listnode node;
+  struct vertex_nexthop *nh;
+  int i;
+  struct router_lsa *rl;
+
+  voi = vl_data->vl_oi;
+
+  if (voi->output_cost != v->distance)
+    {
+      voi->output_cost = v->distance;
+      changed = 1;
+    }
+
+  for (node = listhead (v->nexthop); node; nextnode (node))
+    if ((nh = getdata (node)) != NULL)
+      {
+	vl_data->out_oi = (struct ospf_interface *) nh->oi;
+
+	voi->address->u.prefix4 = vl_data->out_oi->address->u.prefix4;
+	voi->address->prefixlen = vl_data->out_oi->address->prefixlen;
+
+	break; /* We take the first interface. */
+      }
+
+  rl = (struct router_lsa *)v->lsa;
+  
+  for (i = 0; i < ntohs (rl->links); i++)
+    {
+      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;
+	}
+    }
+}
+
+
+void
+ospf_vl_up_check (struct ospf_area * area, struct in_addr rid,
+                  struct vertex *v)
+{
+  listnode node;
+  struct ospf_vl_data *vl_data;
+  struct ospf_interface *oi;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    {
+      zlog_info ("ospf_vl_up_check(): Start");
+      zlog_info ("ospf_vl_up_check(): Router ID is %s", inet_ntoa (rid));
+      zlog_info ("ospf_vl_up_check(): Area is %s", inet_ntoa (area->area_id));
+    }
+
+  for (node = listhead (ospf_top->vlinks); node; nextnode (node))
+    {
+      if ((vl_data = getdata (node)) == NULL)
+        continue;
+  
+      if (IS_DEBUG_OSPF_EVENT)
+	{
+	  zlog_info ("ospf_vl_up_check(): considering VL, name: %s", 
+		     vl_data->vl_oi->ifp->name);
+	  zlog_info ("ospf_vl_up_check(): VL area: %s, peer ID: %s", 
+		     inet_ntoa (vl_data->vl_area_id),
+		     inet_ntoa (vl_data->vl_peer));
+	}
+
+      if (IPV4_ADDR_SAME (&vl_data->vl_peer, &rid) &&
+          IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
+        {
+          oi = vl_data->vl_oi;
+          SET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
+
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_vl_up_check(): this VL matched");
+
+          if (oi->state == ISM_Down)
+            {
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("ospf_vl_up_check(): VL is down, waking it up");
+              SET_FLAG (oi->ifp->flags, IFF_UP);
+              OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
+            }
+
+          ospf_vl_set_params (vl_data, v);
+        }
+    }
+}
+
+void
+ospf_vl_unapprove ()
+{
+  listnode node;
+  struct ospf_vl_data *vl_data;
+
+  for (node = listhead (ospf_top->vlinks); node; nextnode (node))
+    if ((vl_data = getdata (node)) != NULL)
+      UNSET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
+}
+
+void
+ospf_vl_shut_unapproved ()
+{
+  listnode node;
+  struct ospf_vl_data *vl_data;
+
+  for (node = listhead (ospf_top->vlinks); node; nextnode (node))
+    if ((vl_data = getdata (node)) != NULL)
+      if (!CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
+        ospf_vl_shutdown (vl_data);
+}
+
+int
+ospf_full_virtual_nbrs (struct ospf_area *area)
+{
+  if (IS_DEBUG_OSPF_EVENT)
+    {
+      zlog_info ("counting fully adjacent virtual neighbors in area %s",
+		 inet_ntoa (area->area_id));
+      zlog_info ("there are %d of them", area->full_vls);
+    }
+
+  return area->full_vls;
+}
+
+int
+ospf_vls_in_area (struct ospf_area *area)
+{
+  listnode node;
+  struct ospf_vl_data *vl_data;
+  int c = 0;
+
+  for (node = listhead (ospf_top->vlinks); node; nextnode (node))
+    if ((vl_data = getdata (node)) != NULL)
+      if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
+        c++;
+
+  return c;
+}
+
+
+struct crypt_key *
+ospf_crypt_key_new ()
+{
+  struct crypt_key *ck;
+
+  ck = XMALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key));
+  memset (ck, 0, sizeof (struct crypt_key));
+
+  return ck;
+}
+
+void
+ospf_crypt_key_add (list crypt, struct crypt_key *ck)
+{
+  listnode_add (crypt, ck);
+}
+
+struct crypt_key *
+ospf_crypt_key_lookup (list auth_crypt, u_char key_id)
+{
+  listnode node;
+  struct crypt_key *ck;
+
+  for (node = listhead (auth_crypt); node; nextnode (node))
+    {
+      ck = getdata (node);
+      if (ck->key_id == key_id)
+        return ck;
+    }
+
+  return NULL;
+}
+
+int
+ospf_crypt_key_delete (list auth_crypt, u_char key_id)
+{
+  listnode node;
+  struct crypt_key *ck;
+
+  for (node = listhead (auth_crypt); node; nextnode (node))
+    {
+      ck = getdata (node);
+      if (ck->key_id == key_id)
+        {
+          listnode_delete (auth_crypt, ck);
+          return 1;
+        }
+    }
+
+  return 0;
+}
+
+void
+ospf_if_init ()
+{
+  /* Initialize Zebra interface data structure. */
+  if_init ();
+  if_add_hook (IF_NEW_HOOK, ospf_if_new_hook);
+  if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook);
+}
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
new file mode 100644
index 0000000..6dc01ae
--- /dev/null
+++ b/ospfd/ospf_interface.h
@@ -0,0 +1,245 @@
+/*
+ * OSPF Interface functions.
+ * Copyright (C) 1999 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ * 
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_INTERFACE_H
+#define _ZEBRA_OSPF_INTERFACE_H
+
+#define OSPF_AUTH_SIMPLE_SIZE           8
+#define OSPF_AUTH_MD5_SIZE             16
+
+#define IF_OSPF_IF_INFO(I) ((struct ospf_if_info *)((I)->info))
+#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)
+			    
+#define OSPF_IF_PARAM_CONFIGURED(S, P) ((S) && (S)->P##__config)
+#define OSPF_IF_PARAM(O, P) \
+        (OSPF_IF_PARAM_CONFIGURED ((O)->params, P)?\
+                        (O)->params->P:IF_DEF_PARAMS((O)->ifp)->P)
+
+#define DECLARE_IF_PARAM(T, P) T P; u_char P##__config:1
+#define UNSET_IF_PARAM(S, P) ((S)->P##__config) = 0
+#define SET_IF_PARAM(S, P) ((S)->P##__config) = 1
+
+struct ospf_if_params
+{
+  DECLARE_IF_PARAM (u_int32_t, transmit_delay); /* Interface Transmisson Delay */
+  DECLARE_IF_PARAM (u_int32_t, output_cost_cmd);/* Command Interface Output Cost */
+  DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */
+  DECLARE_IF_PARAM (u_char, passive_interface);      /* OSPF Interface is passive */
+  DECLARE_IF_PARAM (u_char, priority);               /* OSPF Interface priority */
+  DECLARE_IF_PARAM (u_char, type);                   /* type of interface */
+#define OSPF_IF_ACTIVE                  0
+#define OSPF_IF_PASSIVE		        1
+  
+  DECLARE_IF_PARAM (u_int32_t, v_hello);             /* Hello Interval */
+  DECLARE_IF_PARAM (u_int32_t, v_wait);              /* Router Dead Interval */
+
+  /* Authentication data. */
+  u_char auth_simple[OSPF_AUTH_SIMPLE_SIZE + 1];       /* Simple password. */
+  u_char auth_simple__config:1;
+  
+  DECLARE_IF_PARAM (list, auth_crypt);                 /* List of Auth cryptographic data. */
+  DECLARE_IF_PARAM (int, auth_type);               /* OSPF authentication type */
+};
+
+struct ospf_if_info
+{
+  struct ospf_if_params *def_params;
+  struct route_table *params;
+  struct route_table *oifs;
+};
+
+struct ospf_interface;
+
+struct ospf_vl_data
+{
+  struct in_addr    vl_peer;	   /* Router-ID of the peer for VLs. */
+  struct in_addr    vl_area_id;	   /* Transit area for this VL. */
+  int format;                      /* area ID format */
+  struct ospf_interface *vl_oi;	   /* Interface data structure for the VL. */
+  struct ospf_interface *out_oi;   /* The interface to go out. */
+  struct in_addr    peer_addr;	   /* Address used to reach the peer. */
+  u_char flags;
+};
+
+
+#define OSPF_VL_MAX_COUNT 256
+#define OSPF_VL_MTU	  1500
+
+#define OSPF_VL_FLAG_APPROVED 0x01
+
+struct crypt_key
+{
+  u_char key_id;
+  u_char auth_key[OSPF_AUTH_MD5_SIZE + 1];
+};
+
+/* OSPF interface structure. */
+struct ospf_interface
+{
+  /* This interface's parent ospf instance. */
+  struct ospf *ospf;
+
+  /* OSPF Area. */
+  struct ospf_area *area;
+
+  /* Interface data from zebra. */
+  struct interface *ifp;
+  struct ospf_vl_data *vl_data;		/* Data for Virtual Link */
+  
+  /* Packet send buffer. */
+  struct ospf_fifo *obuf;		/* Output queue */
+
+  /* OSPF Network Type. */
+  u_char type;
+#define OSPF_IFTYPE_NONE		0
+#define OSPF_IFTYPE_POINTOPOINT		1
+#define OSPF_IFTYPE_BROADCAST		2
+#define OSPF_IFTYPE_NBMA		3
+#define OSPF_IFTYPE_POINTOMULTIPOINT	4
+#define OSPF_IFTYPE_VIRTUALLINK		5
+#define OSPF_IFTYPE_LOOPBACK            6
+#define OSPF_IFTYPE_MAX			7
+
+  /* State of Interface State Machine. */
+  u_char state;
+
+  struct prefix *address;		/* Interface prefix */
+  struct connected *connected;          /* Pointer to connected */ 
+
+  /* Configured varables. */
+  struct ospf_if_params *params;
+  u_int32_t crypt_seqnum;		/* Cryptographic Sequence Number */ 
+  u_int32_t output_cost;	        /* Acutual Interface Output Cost */
+
+  /* Neighbor information. */
+  struct route_table *nbrs;             /* OSPF Neighbor List */
+  struct ospf_neighbor *nbr_self;	/* Neighbor Self */
+#define DR(I)			((I)->nbr_self->d_router)
+#define BDR(I)			((I)->nbr_self->bd_router)
+#define OPTIONS(I)		((I)->nbr_self->options)
+#define PRIORITY(I)		((I)->nbr_self->priority)
+
+  /* List of configured NBMA neighbor. */
+  list nbr_nbma;
+
+  /* self-originated LSAs. */
+  struct ospf_lsa *network_lsa_self;	/* network-LSA. */
+#ifdef HAVE_OPAQUE_LSA
+  list opaque_lsa_self;			/* Type-9 Opaque-LSAs */
+#endif /* HAVE_OPAQUE_LSA */
+
+  struct route_table *ls_upd_queue;
+
+  list ls_ack;				/* Link State Acknowledgment list. */
+  
+  struct
+  {
+    list ls_ack;
+    struct in_addr dst;
+  } ls_ack_direct;
+
+  /* Timer values. */
+  u_int32_t v_ls_ack;			/* Delayed Link State Acknowledgment */
+
+  /* Threads. */
+  struct thread *t_hello;               /* timer */
+  struct thread *t_wait;                /* timer */
+  struct thread *t_ls_ack;              /* timer */
+  struct thread *t_ls_ack_direct;       /* event */
+  struct thread *t_ls_upd_event;        /* event */
+  struct thread *t_network_lsa_self;    /* self-originated network-LSA
+                                           reflesh thread. timer */
+#ifdef HAVE_OPAQUE_LSA
+  struct thread *t_opaque_lsa_self;     /* Type-9 Opaque-LSAs */
+#endif /* HAVE_OPAQUE_LSA */
+
+  int on_write_q;
+  
+  /* Statistics fields. */
+  u_int32_t hello_in;	        /* Hello message input count. */
+  u_int32_t hello_out;	        /* Hello message output count. */
+  u_int32_t db_desc_in;         /* database desc. message input count. */
+  u_int32_t db_desc_out;        /* database desc. message output count. */
+  u_int32_t ls_req_in;          /* LS request message input count. */
+  u_int32_t ls_req_out;         /* LS request message output count. */
+  u_int32_t ls_upd_in;          /* LS update message input count. */
+  u_int32_t ls_upd_out;         /* LS update message output count. */
+  u_int32_t ls_ack_in;          /* LS Ack message input count. */
+  u_int32_t ls_ack_out;         /* LS Ack message output count. */
+  u_int32_t discarded;		/* discarded input count by error. */
+  u_int32_t state_change;	/* Number of status change. */
+
+  u_int full_nbrs;
+};
+
+/* Prototypes. */
+char *ospf_if_name (struct ospf_interface *);
+struct ospf_interface *ospf_if_new ();
+void ospf_if_cleanup (struct ospf_interface *);
+void ospf_if_free (struct ospf_interface *);
+int ospf_if_up (struct ospf_interface *);
+int ospf_if_down (struct ospf_interface *);
+
+int ospf_if_is_up (struct ospf_interface *);
+struct ospf_interface *ospf_if_lookup_by_name (char *);
+struct ospf_interface *ospf_if_lookup_by_local_addr (struct interface *, struct in_addr);
+struct ospf_interface *ospf_if_lookup_by_prefix (struct prefix_ipv4 *);
+struct ospf_interface *ospf_if_addr_local (struct in_addr src);
+struct ospf_interface *ospf_if_lookup_recv_interface (struct in_addr src);
+struct ospf_interface *ospf_if_is_configured (struct in_addr *);
+
+struct ospf_if_params *ospf_lookup_if_params (struct interface *, struct in_addr);
+struct ospf_if_params *ospf_get_if_params (struct interface *, struct in_addr);
+void ospf_del_if_params (struct ospf_if_params *);
+void ospf_free_if_params (struct interface *, struct in_addr);
+void ospf_if_update_params (struct interface *, struct in_addr);
+
+int ospf_if_new_hook (struct interface *);
+void ospf_if_init ();
+void ospf_if_stream_set (struct ospf_interface *);
+void ospf_if_stream_unset (struct ospf_interface *);
+void ospf_if_reset_variables (struct ospf_interface *);
+int ospf_if_is_enable (struct ospf_interface *);
+int ospf_if_get_output_cost (struct ospf_interface *);
+void ospf_if_recalculate_output_cost (struct interface *);
+
+struct ospf_interface *ospf_vl_new (struct ospf_vl_data *);
+struct ospf_vl_data *ospf_vl_data_new (struct ospf_area *, struct in_addr);
+struct ospf_vl_data *ospf_vl_lookup (struct ospf_area *, struct in_addr);
+void ospf_vl_data_free (struct ospf_vl_data *);
+void ospf_vl_add (struct ospf_vl_data *);
+void ospf_vl_delete (struct ospf_vl_data *);
+void ospf_vl_up_check (struct ospf_area *, struct in_addr, struct vertex *);
+void ospf_vl_unapprove ();
+void ospf_vl_shut_unapproved ();
+int ospf_full_virtual_nbrs (struct ospf_area *);
+int ospf_vls_in_area (struct ospf_area *);
+
+struct crypt_key *ospf_crypt_key_lookup (list, u_char);
+struct crypt_key *ospf_crypt_key_new ();
+void ospf_crypt_key_add (list, struct crypt_key *);
+int ospf_crypt_key_delete (list, u_char key_id);
+
+
+#endif /* _ZEBRA_OSPF_INTERFACE_H */
diff --git a/ospfd/ospf_ism.h b/ospfd/ospf_ism.h
new file mode 100644
index 0000000..b04865a
--- /dev/null
+++ b/ospfd/ospf_ism.h
@@ -0,0 +1,88 @@
+/*
+ * OSPF version 2  Interface State Machine.
+ *   From RFC2328 [OSPF Version 2]
+ * Copyright (C) 1999 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_ISM_H
+#define _ZEBRA_OSPF_ISM_H
+
+/* OSPF Interface State Machine Status. */
+#define ISM_DependUpon                    0
+#define ISM_Down                          1
+#define ISM_Loopback                      2
+#define ISM_Waiting                       3
+#define ISM_PointToPoint                  4
+#define ISM_DROther                       5
+#define ISM_Backup                        6
+#define ISM_DR                            7
+#define OSPF_ISM_STATE_MAX   	          8
+
+/* OSPF Interface State Machine Event. */
+#define ISM_NoEvent                       0
+#define ISM_InterfaceUp                   1
+#define ISM_WaitTimer                     2
+#define ISM_BackupSeen                    3
+#define ISM_NeighborChange                4
+#define ISM_LoopInd                       5
+#define ISM_UnloopInd                     6
+#define ISM_InterfaceDown                 7
+#define OSPF_ISM_EVENT_MAX                8
+
+#define OSPF_ISM_WRITE_ON()                                                   \
+      do                                                                      \
+        {                                                                     \
+          if (oi->on_write_q == 0)                                            \
+	    {                                                                 \
+              listnode_add (ospf_top->oi_write_q, oi);                        \
+	      oi->on_write_q = 1;                                             \
+	    }                                                                 \
+	  if (ospf_top->t_write == NULL)                                      \
+	    ospf_top->t_write =                                               \
+	      thread_add_write (master, ospf_write, ospf_top, ospf_top->fd);  \
+        } while (0)
+     
+/* Macro for OSPF ISM timer turn on. */
+#define OSPF_ISM_TIMER_ON(T,F,V) \
+      if (!(T)) \
+        (T) = thread_add_timer (master, (F), oi, (V))
+
+/* Macro for OSPF ISM timer turn off. */
+#define OSPF_ISM_TIMER_OFF(X) \
+      if (X) \
+        { \
+          thread_cancel (X); \
+          (X) = NULL; \
+        }
+
+/* Macro for OSPF schedule event. */
+#define OSPF_ISM_EVENT_SCHEDULE(I,E) \
+      thread_add_event (master, ospf_ism_event, (I), (E))
+
+/* Macro for OSPF execute event. */
+#define OSPF_ISM_EVENT_EXECUTE(I,E) \
+      thread_execute (master, ospf_ism_event, (I), (E))
+
+/* Prototypes. */
+int ospf_ism_event (struct thread *);
+void ism_change_status (struct ospf_interface *, int);
+int ospf_hello_timer (struct thread *thread);
+
+#endif /* _ZEBRA_OSPF_ISM_H */
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
new file mode 100644
index 0000000..5b63a76
--- /dev/null
+++ b/ospfd/ospf_lsa.c
@@ -0,0 +1,3315 @@
+/*
+ * OSPF Link State Advertisement
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "memory.h"
+#include "stream.h"
+#include "log.h"
+#include "thread.h"
+#include "hash.h"
+#include "sockunion.h"		/* for inet_aton() */
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ase.h"
+#include "ospfd/ospf_zebra.h"
+
+
+u_int32_t
+get_metric (u_char *metric)
+{
+  u_int32_t m;
+  m = metric[0];
+  m = (m << 8) + metric[1];
+  m = (m << 8) + metric[2];
+  return m;
+}
+
+
+struct timeval
+tv_adjust (struct timeval a)
+{
+  while (a.tv_usec >= 1000000)
+    {
+      a.tv_usec -= 1000000;
+      a.tv_sec++;
+    }
+
+  while (a.tv_usec < 0)
+    {
+      a.tv_usec += 1000000;
+      a.tv_sec--;
+    }
+
+  return a;
+}
+
+int
+tv_ceil (struct timeval a)
+{
+  a = tv_adjust (a);
+
+  return (a.tv_usec ? a.tv_sec + 1 : a.tv_sec);
+}
+
+int
+tv_floor (struct timeval a)
+{
+  a = tv_adjust (a);
+
+  return a.tv_sec;
+}
+
+struct timeval
+int2tv (int a)
+{
+  struct timeval ret;
+
+  ret.tv_sec = a;
+  ret.tv_usec = 0;
+
+  return ret;
+}
+
+struct timeval
+tv_add (struct timeval a, struct timeval b)
+{
+  struct timeval ret;
+
+  ret.tv_sec = a.tv_sec + b.tv_sec;
+  ret.tv_usec = a.tv_usec + b.tv_usec;
+
+  return tv_adjust (ret);
+}
+
+struct timeval
+tv_sub (struct timeval a, struct timeval b)
+{
+  struct timeval ret;
+
+  ret.tv_sec = a.tv_sec - b.tv_sec;
+  ret.tv_usec = a.tv_usec - b.tv_usec;
+
+  return tv_adjust (ret);
+}
+
+int
+tv_cmp (struct timeval a, struct timeval b)
+{
+  return (a.tv_sec == b.tv_sec ?
+	  a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
+}
+
+int
+ospf_lsa_refresh_delay (struct ospf_lsa *lsa)
+{
+  struct timeval delta, now;
+  int delay = 0;
+
+  gettimeofday (&now, NULL);
+  delta = tv_sub (now, lsa->tv_orig);
+
+  if (tv_cmp (delta, int2tv (OSPF_MIN_LS_INTERVAL)) < 0)
+    {
+      delay = tv_ceil (tv_sub (int2tv (OSPF_MIN_LS_INTERVAL), delta));
+
+      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+        zlog_info ("LSA[Type%d:%s]: Refresh timer delay %d seconds",
+	           lsa->data->type, inet_ntoa (lsa->data->id), delay);
+
+      assert (delay > 0);
+    }
+
+  return delay;
+}
+
+
+int
+get_age (struct ospf_lsa *lsa)
+{
+  int age;
+  struct timeval now;
+
+  gettimeofday (&now, NULL);
+  age = ntohs (lsa->data->ls_age) + tv_floor (tv_sub (now, lsa->tv_recv));
+
+  return age;
+}
+
+
+/* Fletcher Checksum -- Refer to RFC1008. */
+#define MODX                 4102
+#define LSA_CHECKSUM_OFFSET    15
+
+u_int16_t
+ospf_lsa_checksum (struct lsa_header *lsa)
+{
+  u_char *sp, *ep, *p, *q;
+  int c0 = 0, c1 = 0;
+  int x, y;
+  u_int16_t length;
+
+  lsa->checksum = 0;
+  length = ntohs (lsa->length) - 2;
+  sp = (char *) &lsa->options;
+
+  for (ep = sp + length; sp < ep; sp = q)
+    {
+      q = sp + MODX;
+      if (q > ep)
+        q = ep;
+      for (p = sp; p < q; p++)
+        {
+          c0 += *p;
+          c1 += c0;
+        }
+      c0 %= 255;
+      c1 %= 255;
+    }
+
+  x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
+  if (x <= 0)
+    x += 255;
+  y = 510 - c0 - x;
+  if (y > 255)
+    y -= 255;
+
+  /* take care endian issue. */
+  lsa->checksum = htons ((x << 8) + y);
+
+  return (lsa->checksum);
+}
+
+
+
+/* Create OSPF LSA. */
+struct ospf_lsa *
+ospf_lsa_new ()
+{
+  struct ospf_lsa *new;
+
+  new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa));
+  memset (new, 0, sizeof (struct ospf_lsa));
+
+  new->flags = 0;
+  new->lock = 1;
+  new->retransmit_counter = 0;
+  gettimeofday (&new->tv_recv, NULL);
+  new->tv_orig = new->tv_recv;
+  new->refresh_list = -1;
+  
+  return new;
+}
+
+/* Duplicate OSPF LSA. */
+struct ospf_lsa *
+ospf_lsa_dup (struct ospf_lsa *lsa)
+{
+  struct ospf_lsa *new;
+
+  if (lsa == NULL)
+    return NULL;
+
+  new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa));
+
+  memcpy (new, lsa, sizeof (struct ospf_lsa));
+  UNSET_FLAG (new->flags, OSPF_LSA_DISCARD);
+  new->lock = 1;
+  new->retransmit_counter = 0;
+  new->data = ospf_lsa_data_dup (lsa->data);
+
+  return new;
+}
+
+/* Free OSPF LSA. */
+void
+ospf_lsa_free (struct ospf_lsa *lsa)
+{
+  assert (lsa->lock == 0);
+  
+  if (IS_DEBUG_OSPF (lsa, LSA))
+    zlog_info ("LSA: freed %p", lsa);
+
+  /* Delete LSA data. */
+  if (lsa->data != NULL)
+    ospf_lsa_data_free (lsa->data);
+
+  assert (lsa->refresh_list < 0);
+
+  memset (lsa, 0, sizeof (struct ospf_lsa)); 
+  XFREE (MTYPE_OSPF_LSA, lsa);
+}
+
+/* Lock LSA. */
+struct ospf_lsa *
+ospf_lsa_lock (struct ospf_lsa *lsa)
+{
+  lsa->lock++;
+  return lsa;
+}
+
+/* Unlock LSA. */
+void
+ospf_lsa_unlock (struct ospf_lsa *lsa)
+{
+  /* This is sanity check. */
+  if (!lsa)
+    return;
+  
+  lsa->lock--;
+
+  assert (lsa->lock >= 0);
+
+  if (lsa->lock == 0)
+    {
+      assert (CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD));
+      ospf_lsa_free (lsa);
+    }
+}
+
+/* Check discard flag. */
+void
+ospf_lsa_discard (struct ospf_lsa *lsa)
+{
+  if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
+    {
+      SET_FLAG (lsa->flags, OSPF_LSA_DISCARD);
+      ospf_lsa_unlock (lsa);
+    }
+}
+
+/* Create LSA data. */
+struct lsa_header *
+ospf_lsa_data_new (size_t size)
+{
+  struct lsa_header *new;
+
+  new = (struct lsa_header *) XMALLOC (MTYPE_OSPF_LSA_DATA, size);
+  memset (new, 0, size);
+
+  return new;
+}
+
+/* Duplicate LSA data. */
+struct lsa_header *
+ospf_lsa_data_dup (struct lsa_header *lsah)
+{
+  struct lsa_header *new;
+
+  new = ospf_lsa_data_new (ntohs (lsah->length));
+  memcpy (new, lsah, ntohs (lsah->length));
+
+  return new;
+}
+
+/* Free LSA data. */
+void
+ospf_lsa_data_free (struct lsa_header *lsah)
+{
+  if (IS_DEBUG_OSPF (lsa, LSA))
+    zlog_info ("LSA[Type%d:%s]: data freed %p",
+	       lsah->type, inet_ntoa (lsah->id), lsah);
+
+  XFREE (MTYPE_OSPF_LSA_DATA, lsah);
+}
+
+
+/* LSA general functions. */
+
+const char *
+dump_lsa_key (struct ospf_lsa *lsa)
+{
+  static char buf[] = {
+    "Type255,id(255.255.255.255),ar(255.255.255.255)",
+  };
+  struct lsa_header *lsah;
+
+  if (lsa != NULL && (lsah = lsa->data) != NULL)
+    {
+      char id[INET_ADDRSTRLEN], ar[INET_ADDRSTRLEN];
+      strcpy (id, inet_ntoa (lsah->id));
+      strcpy (ar, inet_ntoa (lsah->adv_router));
+
+      sprintf (buf, "Type%d,id(%s),ar(%s)", lsah->type, id, ar);
+    }
+  else
+    strcpy (buf, "NULL");
+
+  return buf;
+}
+
+u_int32_t
+lsa_seqnum_increment (struct ospf_lsa *lsa)
+{
+  u_int32_t seqnum;
+
+  seqnum = ntohl (lsa->data->ls_seqnum) + 1;
+
+  return htonl (seqnum);
+}
+
+void
+lsa_header_set (struct stream *s, u_char options,
+		u_char type, struct in_addr id)
+{
+  struct lsa_header *lsah;
+
+  lsah = (struct lsa_header *) STREAM_DATA (s);
+
+  lsah->ls_age = htons (0);
+  lsah->options = options;
+  lsah->type = type;
+  lsah->id = id;
+  lsah->adv_router = ospf_top->router_id;
+  lsah->ls_seqnum = htonl (OSPF_INITIAL_SEQUENCE_NUMBER);
+
+  ospf_output_forward (s, OSPF_LSA_HEADER_SIZE);
+}
+
+/* router-LSA related functions. */
+/* Get router-LSA flags. */
+u_char
+router_lsa_flags (struct ospf_area *area)
+{
+  u_char flags;
+
+  flags = ospf_top->flags;
+
+  /* Set virtual link flag. */
+  if (ospf_full_virtual_nbrs (area))
+    SET_FLAG (flags, ROUTER_LSA_VIRTUAL);
+  else
+    /* Just sanity check */
+    UNSET_FLAG (flags, ROUTER_LSA_VIRTUAL);
+
+  /* Set Shortcut ABR behabiour flag. */
+  UNSET_FLAG (flags, ROUTER_LSA_SHORTCUT);
+  if (ospf_top->abr_type == OSPF_ABR_SHORTCUT)
+    if (!OSPF_IS_AREA_BACKBONE (area))
+      if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
+	   !ospf_top->backbone) ||
+	  area->shortcut_configured == OSPF_SHORTCUT_ENABLE)
+	SET_FLAG (flags, ROUTER_LSA_SHORTCUT);
+
+  /* ASBR can't exit in stub area. */
+  if (area->external_routing == OSPF_AREA_STUB)
+    UNSET_FLAG (flags, OSPF_FLAG_ASBR);
+
+  return flags;
+}
+
+/* Lookup neighbor other than myself.
+   And check neighbor count,
+   Point-to-Point link must have only 1 neighbor. */
+struct ospf_neighbor *
+ospf_nbr_lookup_ptop (struct route_table *nbrs, struct in_addr router_id)
+{
+  struct route_node *rn;
+  struct ospf_neighbor *nbr = NULL;
+
+  /* Search neighbor, there must be one of two nbrs. */
+  for (rn = route_top (nbrs); rn; rn = route_next (rn))
+    if ((nbr = rn->info) != NULL)
+      /* Ignore myself. */
+      if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf_top->router_id))
+	if (nbr->state == NSM_Full)
+	  break;
+
+  /* PtoP link must have only 1 neighbor. */
+  if (ospf_nbr_count (nbrs, 0) > 1)
+    zlog_warn ("Point-to-Point link has more than 1 neighobrs.");
+
+  return nbr;
+}
+
+/* Set a link information. */
+void
+link_info_set (struct stream *s, struct in_addr id,
+	       struct in_addr data, u_char type, u_char tos, u_int16_t cost)
+{
+  /* TOS based routing is not supported. */
+  stream_put_ipv4 (s, id.s_addr);		/* Link ID. */
+  stream_put_ipv4 (s, data.s_addr);		/* Link Data. */
+  stream_putc (s, type);			/* Link Type. */
+  stream_putc (s, tos);				/* TOS = 0. */
+  stream_putw (s, cost);			/* Link Cost. */
+}
+
+/* Describe Point-to-Point link. */
+int
+lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
+{
+  int links = 0;
+  struct ospf_neighbor *nbr;
+  struct in_addr id, mask;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type1]: Set link Point-to-Point");
+
+  if ((nbr = ospf_nbr_lookup_ptop (oi->nbrs, ospf_top->router_id)))
+    if (nbr->state == NSM_Full)
+      {
+	/* For unnumbered point-to-point networks, the Link Data field
+	   should specify the interface's MIB-II ifIndex value. */
+	link_info_set (s, nbr->router_id, oi->address->u.prefix4,
+		       LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost);
+	links++;
+      }
+
+  if (oi->connected->destination != NULL)
+    {
+      /* Option 1:
+	 link_type = LSA_LINK_TYPE_STUB;
+	 link_id = nbr->address.u.prefix4;
+	 link_data.s_addr = 0xffffffff;
+	 link_cost = o->output_cost; */
+      
+      id.s_addr = oi->connected->destination->u.prefix4.s_addr;
+      mask.s_addr = 0xffffffff;
+      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+    }
+  else
+    {
+       /* Option 2:  We need to include link to a stub
+	 network regardless of the state of the neighbor */
+      masklen2ip (oi->address->prefixlen, &mask);
+      id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
+      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+    }
+  links++;
+
+  return links;
+}
+
+/* Describe Broadcast Link. */
+int
+lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
+{
+  struct ospf_neighbor *dr;
+  struct in_addr id, mask;
+
+  /* Describe Type 3 Link. */
+  if (oi->state == ISM_Waiting)
+    {
+      masklen2ip (oi->address->prefixlen, &mask);
+      id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
+      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+      return 1;
+    }
+
+  dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi));
+  /* Describe Type 2 link. */
+  if (dr && (dr->state == NSM_Full ||
+	     IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) &&
+      ospf_nbr_count (oi->nbrs, NSM_Full) > 0)
+    {
+      link_info_set (s, DR (oi), oi->address->u.prefix4,
+		     LSA_LINK_TYPE_TRANSIT, 0, oi->output_cost);
+    }
+  /* Describe type 3 link. */
+  else
+    {
+      masklen2ip (oi->address->prefixlen, &mask);
+      id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
+      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+    }
+  return 1;
+}
+
+int
+lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi)
+{
+  struct in_addr id, mask;
+
+  /* Describe Type 3 Link. */
+  if (oi->state != ISM_Loopback)
+    return 0;
+
+  mask.s_addr = 0xffffffff;
+  id.s_addr = oi->address->u.prefix4.s_addr;
+  link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+  return 1;
+}
+
+/* Describe Virtual Link. */
+int
+lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi)
+{
+  struct ospf_neighbor *nbr;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type1]: Set link type VL, state %d", oi->state);
+
+  if (oi->state == ISM_PointToPoint)
+    if ((nbr = ospf_nbr_lookup_ptop (oi->nbrs, ospf_top->router_id)))
+      if (nbr->state == NSM_Full)
+	{
+	  link_info_set (s, nbr->router_id, oi->address->u.prefix4,
+			 LSA_LINK_TYPE_VIRTUALLINK, 0, oi->output_cost);
+	  return 1;
+	}
+
+  return 0;
+}
+
+#define lsa_link_nbma_set(S,O)  lsa_link_broadcast_set (S, O)
+
+/* Set router-LSA link information. */
+int
+router_lsa_link_set (struct stream *s, struct ospf_area *area)
+{
+  listnode node;
+  int links = 0;
+
+  for (node = listhead (area->oiflist); node; node = nextnode (node))
+    {
+      struct ospf_interface *oi = node->data;
+      struct interface *ifp = oi->ifp;
+
+      /* Check interface is up, OSPF is enable. */
+      if (if_is_up (ifp))
+	{
+	  if (oi->state != ISM_Down)
+	    {
+	      /* Describe each link. */
+	      switch (oi->type)
+		{
+		case OSPF_IFTYPE_POINTOPOINT:
+		  links += lsa_link_ptop_set (s, oi);
+		  break;
+		case OSPF_IFTYPE_BROADCAST:
+		  links += lsa_link_broadcast_set (s, oi);
+		  break;
+		case OSPF_IFTYPE_NBMA:
+		  links += lsa_link_nbma_set (s, oi);
+		  break;
+		case OSPF_IFTYPE_POINTOMULTIPOINT:
+		  /* Not supproted yet. */
+		  break;
+		case OSPF_IFTYPE_VIRTUALLINK:
+		  links += lsa_link_virtuallink_set (s, oi);
+		  break;
+		case OSPF_IFTYPE_LOOPBACK:
+		  links += lsa_link_loopback_set (s, oi); 
+		}
+	    }
+	}
+    }
+
+  return links;
+}
+
+/* Set router-LSA body. */
+void
+ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area)
+{
+  unsigned long putp;
+  u_int16_t cnt;
+
+  /* Set flags. */
+  stream_putc (s, router_lsa_flags (area));
+
+  /* Set Zero fields. */
+  stream_putc (s, 0);
+
+  /* Keep pointer to # links. */
+  putp = s->putp;
+
+  /* Forward word */
+  stream_putw(s, 0);
+
+  /* Set all link information. */
+  cnt = router_lsa_link_set (s, area);
+
+  /* Set # of links here. */
+  stream_putw_at (s, putp, cnt);
+}
+
+/* Create new router-LSA. */
+struct ospf_lsa *
+ospf_router_lsa_new (struct ospf_area *area)
+{
+  struct stream *s;
+  struct lsa_header *lsah;
+  struct ospf_lsa *new;
+  int length;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type1]: Create router-LSA instance");
+
+  /* Create a stream for LSA. */
+  s = stream_new (OSPF_MAX_LSA_SIZE);
+  lsah = (struct lsa_header *) STREAM_DATA (s);
+
+#ifdef HAVE_NSSA
+  /* Set LSA common header fields. */
+  lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_NSSA_GET (area),
+		  OSPF_ROUTER_LSA, ospf_top->router_id);
+#else /* ! HAVE_NSSA */
+  /* Set LSA common header fields. */
+  lsa_header_set (s, LSA_OPTIONS_GET (area),
+		  OSPF_ROUTER_LSA, ospf_top->router_id);
+#endif /* HAVE_NSSA */
+
+  /* Set router-LSA body fields. */
+  ospf_router_lsa_body_set (s, area);
+
+  /* Set length. */
+  length = stream_get_endp (s);
+  lsah->length = htons (length);
+
+  /* Now, create OSPF LSA instance. */
+  new = ospf_lsa_new ();
+  new->area = area;
+  SET_FLAG (new->flags, OSPF_LSA_SELF);
+
+  /* Copy LSA data to store, discard stream. */
+  new->data = ospf_lsa_data_new (length);
+  memcpy (new->data, lsah, length);
+  stream_free (s);
+
+  return new;
+}
+
+/* Originate Router-LSA. */
+struct ospf_lsa *
+ospf_router_lsa_originate (struct ospf_area *area)
+{
+  struct ospf_lsa *new;
+
+  /* Create new router-LSA instance. */
+  new = ospf_router_lsa_new (area);
+
+  /* Sanity check. */
+  if (new->data->adv_router.s_addr == 0)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("LSA[Type1]: AdvRouter is 0, discard");
+      ospf_lsa_discard (new);
+      return NULL;
+    }
+
+  /* Install LSA to LSDB. */
+  new = ospf_lsa_install (NULL, new);
+
+  /* Update LSA origination count. */
+  ospf_top->lsa_originate_count++;
+
+  /* Flooding new LSA through area. */
+  ospf_flood_through_area (area, NULL, new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: Originate router-LSA %p",
+		 new->data->type, inet_ntoa (new->data->id), new);
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return new;
+}
+
+/* Refresh router-LSA. */
+struct ospf_lsa *
+ospf_router_lsa_refresh (struct ospf_lsa *lsa)
+{
+  struct ospf_area *area = lsa->area;
+  struct ospf_lsa *new;
+
+  /* Sanity check. */
+  assert (lsa->data);
+
+  /* Delete LSA from neighbor retransmit-list. */
+  ospf_ls_retransmit_delete_nbr_all (area, lsa);
+
+  /* Create new router-LSA instance. */
+  new = ospf_router_lsa_new (area);
+  new->data->ls_seqnum = lsa_seqnum_increment (lsa);
+
+  ospf_lsa_install (NULL, new);
+
+  /* Flood LSA through area. */
+  ospf_flood_through_area (area, NULL, new);
+
+  /* Debug logging. */
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: router-LSA refresh",
+		 new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return NULL;
+}
+
+int
+ospf_router_lsa_timer (struct thread *t)
+{
+  struct ospf_area *area;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[router-LSA]: (router-LSA Refresh expire)");
+
+  area = THREAD_ARG (t);
+  area->t_router_lsa_self = NULL;
+
+  /* Now refresh router-LSA. */
+  if (area->router_lsa_self)
+    ospf_router_lsa_refresh (area->router_lsa_self);
+  /* Newly originate router-LSA. */
+  else
+    ospf_router_lsa_originate (area);
+
+  return 0;
+}
+
+void
+ospf_router_lsa_timer_add (struct ospf_area *area)
+{
+  /* Keep area's self-originated router-LSA. */
+  struct ospf_lsa *lsa = area->router_lsa_self;
+
+  /* Cancel previously scheduled router-LSA timer. */
+  if (area->t_router_lsa_self)
+    if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+      zlog_info ("LSA[Type1]: Cancel previous router-LSA timer");
+
+  OSPF_TIMER_OFF (area->t_router_lsa_self);
+
+  /* If router-LSA is originated previously, check the interval time. */
+  if (lsa)
+    {
+      int delay;
+      if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
+        {
+	  OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
+			      ospf_router_lsa_timer, delay);
+	  return;
+        }
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type1]: Scheduling router-LSA origination right away");
+
+  /* Immediately refresh router-LSA. */
+  OSPF_AREA_TIMER_ON (area->t_router_lsa_self, ospf_router_lsa_timer, 0);
+}
+
+int
+ospf_router_lsa_update_timer (struct thread *t)
+{
+  listnode node;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("Timer[router-LSA Update]: (timer expire)");
+
+  ospf_top->t_router_lsa_update = NULL;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      struct ospf_area *area = getdata (node);
+      struct ospf_lsa *lsa = area->router_lsa_self;
+      struct router_lsa *rl;
+      char *area_str;
+
+      /* Keep Area ID string. */
+      area_str = AREA_NAME (area);
+
+      /* If LSA not exist in this Area, originate new. */
+      if (lsa == NULL)
+        {
+	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+	    zlog_info("LSA[Type1]: Create router-LSA for Area %s", area_str);
+
+	  ospf_router_lsa_originate (area);
+        }
+      /* If router-ID is changed, Link ID must change.
+	 First flush old LSA, then originate new. */
+      else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf_top->router_id))
+	{
+	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+	    zlog_info("LSA[Type%d:%s]: Refresh router-LSA for Area %s",
+		      lsa->data->type, inet_ntoa (lsa->data->id), area_str);
+	  ospf_lsa_flush_area (lsa, area);
+	  ospf_lsa_unlock (area->router_lsa_self);
+	  area->router_lsa_self = NULL;
+
+	  /* Refresh router-LSA, (not install) and flood through area. */
+	  ospf_router_lsa_timer_add (area);
+	}
+      else
+	{
+	  rl = (struct router_lsa *) lsa->data;
+	  /* Refresh router-LSA, (not install) and flood through area. */
+	  if (rl->flags != ospf_top->flags)
+	    ospf_router_lsa_timer_add (area);
+	}
+    }
+
+  return 0;
+}
+
+
+/* network-LSA related functions. */
+/* Originate Network-LSA. */
+void
+ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi)
+{
+  struct in_addr mask;
+  struct route_node *rn;
+  struct ospf_neighbor *nbr;
+
+  masklen2ip (oi->address->prefixlen, &mask);
+  stream_put_ipv4 (s, mask.s_addr);
+
+  /* The network-LSA lists those routers that are fully adjacent to
+    the Designated Router; each fully adjacent router is identified by
+    its OSPF Router ID.  The Designated Router includes itself in this
+    list. RFC2328, Section 12.4.2 */
+
+  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+    if ((nbr = rn->info) != NULL)
+      if (nbr->state == NSM_Full || nbr == oi->nbr_self)
+	stream_put_ipv4 (s, nbr->router_id.s_addr);
+}
+
+struct ospf_lsa *
+ospf_network_lsa_new (struct ospf_interface *oi)
+{
+  struct stream *s;
+  struct ospf_lsa *new;
+  struct lsa_header *lsah;
+  int length;
+
+  /* If there are no neighbours on this network (the net is stub),
+     the router does not originate network-LSA (see RFC 12.4.2) */
+  if (oi->full_nbrs == 0)
+    return NULL;
+  
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type2]: Create network-LSA instance");
+
+  /* Create new stream for LSA. */
+  s = stream_new (OSPF_MAX_LSA_SIZE);
+  lsah = (struct lsa_header *) STREAM_DATA (s);
+
+  lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)),
+		  OSPF_NETWORK_LSA, DR (oi));
+
+  /* Set network-LSA body fields. */
+  ospf_network_lsa_body_set (s, oi);
+
+  /* Set length. */
+  length = stream_get_endp (s);
+  lsah->length = htons (length);
+
+  /* Create OSPF LSA instance. */
+  new = ospf_lsa_new ();
+  new->area = oi->area;
+  SET_FLAG (new->flags, OSPF_LSA_SELF);
+
+  /* Copy LSA to store. */
+  new->data = ospf_lsa_data_new (length);
+  memcpy (new->data, lsah, length);
+  stream_free (s);
+
+  return new;
+}
+
+/* Originate network-LSA. */
+struct ospf_lsa *
+ospf_network_lsa_originate (struct ospf_interface *oi)
+{
+  struct ospf_lsa *new;
+
+  /* Create new network-LSA instance. */
+  new = ospf_network_lsa_new (oi);
+  if (new == NULL)
+    return NULL;
+
+  /* Install LSA to LSDB. */
+  new = ospf_lsa_install (oi, new);
+
+  /* Update LSA origination count. */
+  ospf_top->lsa_originate_count++;
+
+  /* Flooding new LSA through area. */
+  ospf_flood_through_area (oi->area, NULL, new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: Originate network-LSA %p",
+		 new->data->type, inet_ntoa (new->data->id), new);
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return new;
+}
+
+int
+ospf_network_lsa_refresh (struct ospf_lsa *lsa, struct ospf_interface *oi)
+{
+  struct ospf_area *area = lsa->area;
+  struct ospf_lsa *new;
+
+  assert (lsa->data);
+
+  /* Delete LSA from neighbor retransmit-list. */
+  ospf_ls_retransmit_delete_nbr_all (area, lsa);
+
+  /* Create new network-LSA instance. */
+  new = ospf_network_lsa_new (oi);
+  if (new == NULL)
+    return -1;
+  new->data->ls_seqnum = lsa_seqnum_increment (lsa);
+
+  ospf_lsa_install (oi, new);
+
+  /* Flood LSA through aera. */
+  ospf_flood_through_area (area, NULL, new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: network-LSA refresh",
+		 new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return 0;
+}
+
+int
+ospf_network_lsa_refresh_timer (struct thread *t)
+{
+  struct ospf_interface *oi;
+
+  oi = THREAD_ARG (t);
+  oi->t_network_lsa_self = NULL;
+
+  if (oi->network_lsa_self)
+    /* Now refresh network-LSA. */
+    ospf_network_lsa_refresh (oi->network_lsa_self, oi);
+  else
+    /* Newly create network-LSA. */
+    ospf_network_lsa_originate (oi);
+
+  return 0;
+}
+
+void
+ospf_network_lsa_timer_add (struct ospf_interface *oi)
+{
+  /* Keep interface's self-originated network-LSA. */
+  struct ospf_lsa *lsa = oi->network_lsa_self;
+
+  /* Cancel previously schedules network-LSA timer. */
+  if (oi->t_network_lsa_self)
+    if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+      zlog_info ("LSA[Type2]: Cancel previous network-LSA timer");
+  OSPF_TIMER_OFF (oi->t_network_lsa_self);
+
+  /* If network-LSA is originated previously, check the interval time. */
+  if (lsa)
+    {
+      int delay;
+      if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
+        {
+          oi->t_network_lsa_self =
+            thread_add_timer (master, ospf_network_lsa_refresh_timer,
+			      oi, delay);
+          return;
+        }
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("Scheduling network-LSA origination right away");
+
+  /* Immediately refresh network-LSA. */
+  oi->t_network_lsa_self =
+    thread_add_event (master, ospf_network_lsa_refresh_timer, oi, 0);
+}
+
+
+void
+stream_put_ospf_metric (struct stream *s, u_int32_t metric_value)
+{
+  u_int32_t metric;
+  char *mp;
+
+  /* Put 0 metric. TOS metric is not supported. */
+  metric = htonl (metric_value);
+  mp = (char *) &metric;
+  mp++;
+  stream_put (s, mp, 3);
+}
+
+/* summary-LSA related functions. */
+void
+ospf_summary_lsa_body_set (struct stream *s, struct prefix *p,
+			   u_int32_t metric)
+{
+  struct in_addr mask;
+
+  masklen2ip (p->prefixlen, &mask);
+
+  /* Put Network Mask. */
+  stream_put_ipv4 (s, mask.s_addr);
+
+  /* Set # TOS. */
+  stream_putc (s, (u_char) 0);
+
+  /* Set metric. */
+  stream_put_ospf_metric (s, metric);
+}
+
+struct ospf_lsa *
+ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p,
+		      u_int32_t metric, struct in_addr id)
+{
+  struct stream *s;
+  struct ospf_lsa *new;
+  struct lsa_header *lsah;
+  int length;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type3]: Create summary-LSA instance");
+
+  /* Create new stream for LSA. */
+  s = stream_new (OSPF_MAX_LSA_SIZE);
+  lsah = (struct lsa_header *) STREAM_DATA (s);
+
+  lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA, id);
+
+  /* Set summary-LSA body fields. */
+  ospf_summary_lsa_body_set (s, p, metric);
+
+  /* Set length. */
+  length = stream_get_endp (s);
+  lsah->length = htons (length);
+
+  /* Create OSPF LSA instance. */
+  new = ospf_lsa_new ();
+  new->area = area;
+  SET_FLAG (new->flags, OSPF_LSA_SELF);
+
+  /* Copy LSA to store. */
+  new->data = ospf_lsa_data_new (length);
+  memcpy (new->data, lsah, length);
+  stream_free (s);
+
+  return new;
+}
+
+/* Originate Summary-LSA. */
+struct ospf_lsa *
+ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, 
+			    struct ospf_area *area)
+{
+  struct ospf_lsa *new;
+  struct in_addr id;
+  
+  id = ospf_lsa_unique_id (area->lsdb, OSPF_SUMMARY_LSA, p);
+
+  /* Create new summary-LSA instance. */
+  new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id);
+
+  /* Instlal LSA to LSDB. */
+  new = ospf_lsa_install (NULL, new);
+
+  /* Update LSA origination count. */
+  ospf_top->lsa_originate_count++;
+
+  /* Flooding new LSA through area. */
+  ospf_flood_through_area (area, NULL, new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: Originate summary-LSA %p",
+		 new->data->type, inet_ntoa (new->data->id), new);
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return new;
+}
+
+struct ospf_lsa*
+ospf_summary_lsa_refresh (struct ospf_lsa *lsa)
+{
+  struct ospf_lsa *new;
+  struct summary_lsa *sl;
+  struct prefix p;
+  
+  /* Sanity check. */
+  assert (lsa->data);
+
+  sl = (struct summary_lsa *)lsa->data;
+  p.prefixlen = ip_masklen (sl->mask);
+  new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
+			      sl->header.id);
+
+  new->data->ls_seqnum = lsa_seqnum_increment (lsa);
+  
+  /* Re-calculate checksum. */
+  ospf_lsa_checksum (new->data);
+
+  ospf_lsa_install (NULL, new);
+  
+  /* Flood LSA through AS. */
+  ospf_flood_through_area (new->area, NULL, new);
+
+  /* Debug logging. */
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: summary-LSA refresh",
+		 new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_header_dump (new->data);
+    }
+  
+  return new;
+}
+
+
+/* summary-ASBR-LSA related functions. */
+void
+ospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p,
+				u_int32_t metric)
+{
+  struct in_addr mask;
+
+  masklen2ip (p->prefixlen, &mask);
+
+  /* Put Network Mask. */
+  stream_put_ipv4 (s, mask.s_addr);
+
+  /* Set # TOS. */
+  stream_putc (s, (u_char) 0);
+
+  /* Set metric. */
+  stream_put_ospf_metric (s, metric);
+}
+
+struct ospf_lsa *
+ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p,
+			   u_int32_t metric, struct in_addr id)
+{
+  struct stream *s;
+  struct ospf_lsa *new;
+  struct lsa_header *lsah;
+  int length;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type3]: Create summary-LSA instance");
+
+  /* Create new stream for LSA. */
+  s = stream_new (OSPF_MAX_LSA_SIZE);
+  lsah = (struct lsa_header *) STREAM_DATA (s);
+
+  lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA, id);
+
+  /* Set summary-LSA body fields. */
+  ospf_summary_asbr_lsa_body_set (s, p, metric);
+
+  /* Set length. */
+  length = stream_get_endp (s);
+  lsah->length = htons (length);
+
+  /* Create OSPF LSA instance. */
+  new = ospf_lsa_new ();
+  new->area = area;
+  SET_FLAG (new->flags, OSPF_LSA_SELF);
+
+  /* Copy LSA to store. */
+  new->data = ospf_lsa_data_new (length);
+  memcpy (new->data, lsah, length);
+  stream_free (s);
+
+  return new;
+}
+
+/* Originate summary-ASBR-LSA. */
+struct ospf_lsa *
+ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, 
+				 struct ospf_area *area)
+{
+  struct ospf_lsa *new;
+  struct in_addr id;
+  
+  id = ospf_lsa_unique_id (area->lsdb, OSPF_ASBR_SUMMARY_LSA, p);
+
+  /* Create new summary-LSA instance. */
+  new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id);
+
+  /* Install LSA to LSDB. */
+  new = ospf_lsa_install (NULL, new);
+  
+  /* Update LSA origination count. */
+  ospf_top->lsa_originate_count++;
+
+  /* Flooding new LSA through area. */
+  ospf_flood_through_area (area, NULL, new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p",
+		 new->data->type, inet_ntoa (new->data->id), new);
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return new;
+}
+
+struct ospf_lsa*
+ospf_summary_asbr_lsa_refresh (struct ospf_lsa *lsa)
+{
+  struct ospf_lsa *new;
+  struct summary_lsa *sl;
+  struct prefix p;
+
+  /* Sanity check. */
+  assert (lsa->data);
+
+  sl = (struct summary_lsa *)lsa->data;
+  p.prefixlen = ip_masklen (sl->mask);
+  new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
+				   sl->header.id);
+  
+  new->data->ls_seqnum = lsa_seqnum_increment (lsa);
+  
+  /* Re-calculate checksum. */
+  ospf_lsa_checksum (new->data);
+
+  ospf_lsa_install (NULL, new);
+  
+  /* Flood LSA through area. */
+  ospf_flood_through_area (new->area, NULL, new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: summary-ASBR-LSA refresh",
+		 new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return new;
+}
+
+/* AS-external-LSA related functions. */
+
+/* Get nexthop for AS-external-LSAs.  Return nexthop if its interface
+   is connected, else 0*/
+struct in_addr
+ospf_external_lsa_nexthop_get (struct in_addr nexthop)
+{
+  struct in_addr fwd;
+  struct prefix nh;
+  /* struct route_node *rn; */
+  listnode n1;
+
+  fwd.s_addr = 0;
+
+  if (!nexthop.s_addr)
+    return fwd;
+
+  /* Check whether nexthop is covered by OSPF network. */
+  nh.family = AF_INET;
+  nh.u.prefix4 = nexthop;
+  nh.prefixlen = IPV4_MAX_BITLEN;
+
+  for (n1 = listhead (ospf_top->oiflist); n1; nextnode (n1))
+    {
+      struct ospf_interface *oi = getdata (n1);
+
+      if (if_is_up (oi->ifp))
+	if (oi->address->family == AF_INET)
+	  if (prefix_match (oi->address, &nh))
+	    return nexthop;
+    }
+
+  return fwd;
+}
+
+#ifdef HAVE_NSSA
+/* NSSA-external-LSA related functions. */
+
+/* Get 1st IP connection for Forward Addr */
+          
+struct in_addr
+ospf_get_ip_from_ifp (struct ospf_interface *oi)
+{
+  struct in_addr fwd;
+
+  fwd.s_addr = 0;
+
+  if (if_is_up (oi->ifp))
+    return oi->address->u.prefix4;
+  
+  return fwd;
+}
+
+/* Get 1st IP connection for Forward Addr */
+struct in_addr
+ospf_get_nssa_ip (void)
+{
+  struct in_addr fwd;
+  listnode n1;
+
+  fwd.s_addr = 0;
+
+
+  for (n1 = listhead (ospf_top->oiflist); n1; nextnode (n1))
+    {
+      struct ospf_interface *oi = getdata (n1);
+
+      if (if_is_up (oi->ifp))
+	if (oi->area->external_routing == OSPF_AREA_NSSA)
+	  if (oi->address && oi->address->family == AF_INET)
+	    return (oi->address->u.prefix4 );
+    }
+
+  return fwd;
+}
+#endif /* HAVE_NSSA */
+
+#define DEFAULT_DEFAULT_METRIC	             20
+#define DEFAULT_DEFAULT_ORIGINATE_METRIC     10
+#define DEFAULT_DEFAULT_ALWAYS_METRIC	      1
+
+#define DEFAULT_METRIC_TYPE		     EXTERNAL_METRIC_TYPE_2
+
+int
+metric_type (u_char src)
+{
+  return (ospf_top->dmetric[src].type < 0 ?
+	  DEFAULT_METRIC_TYPE : ospf_top->dmetric[src].type);
+}
+
+int
+metric_value (u_char src)
+{
+  if (ospf_top->dmetric[src].value < 0)
+    {
+      if (src == DEFAULT_ROUTE)
+	{
+	  if (ospf_top->default_originate == DEFAULT_ORIGINATE_ZEBRA)
+	    return DEFAULT_DEFAULT_ORIGINATE_METRIC;
+	  else
+	    return DEFAULT_DEFAULT_ALWAYS_METRIC;
+	}
+      else if (ospf_top->default_metric < 0)
+	return DEFAULT_DEFAULT_METRIC;
+      else
+	return ospf_top->default_metric;
+    }
+
+  return ospf_top->dmetric[src].value;
+}
+
+/* Set AS-external-LSA body. */
+void
+ospf_external_lsa_body_set (struct stream *s, struct external_info *ei)
+{
+  struct prefix_ipv4 *p = &ei->p;
+  struct in_addr mask, fwd_addr;
+  u_int32_t mvalue;
+  int mtype;
+  int type;
+
+  /* Put Network Mask. */
+  masklen2ip (p->prefixlen, &mask);
+  stream_put_ipv4 (s, mask.s_addr);
+
+  /* If prefix is default, specify DEFAULT_ROUTE. */
+  type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
+  
+  mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ?
+    ROUTEMAP_METRIC_TYPE (ei) : metric_type (type);
+
+  mvalue = (ROUTEMAP_METRIC (ei) != -1) ?
+    ROUTEMAP_METRIC (ei) : metric_value (type);
+
+  /* Put type of external metric. */
+  stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0));
+
+  /* Put 0 metric. TOS metric is not supported. */
+  stream_put_ospf_metric (s, mvalue);
+  
+  /* Get forwarding address to nexthop if on the Connection List, else 0. */
+  fwd_addr = ospf_external_lsa_nexthop_get (ei->nexthop);
+
+  /* Put forwarding address. */
+  stream_put_ipv4 (s, fwd_addr.s_addr);
+  
+  /* Put route tag -- This value should be introduced from configuration. */
+  stream_putl (s, 0);
+}
+
+/* Create new external-LSA. */
+struct ospf_lsa *
+ospf_external_lsa_new (struct external_info *ei, struct in_addr *old_id)
+{
+  struct stream *s;
+  struct lsa_header *lsah;
+  struct ospf_lsa *new;
+  struct in_addr id;
+  int length;
+
+  if (ei == NULL)
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+	zlog_warn ("LSA[Type5]: External info is NULL, could not originated");
+      return NULL;
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type5]: Originate AS-external-LSA instance");
+
+  /* If old Link State ID is specified, refresh LSA with same ID. */
+  if (old_id)
+    id = *old_id;
+  /* Get Link State with unique ID. */
+  else
+    {
+      id = ospf_lsa_unique_id (ospf_top->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p);
+      if (id.s_addr == 0xffffffff)
+	{
+	  /* Maybe Link State ID not available. */
+	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+	    zlog_info ("LSA[Type5]: Link ID not available, can't originate");
+	  return NULL;
+	}
+    }
+
+  /* Create new stream for LSA. */
+  s = stream_new (OSPF_MAX_LSA_SIZE);
+  lsah = (struct lsa_header *) STREAM_DATA (s);
+
+  /* Set LSA common header fields. */
+  lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA, id);
+
+  /* Set AS-external-LSA body fields. */
+  ospf_external_lsa_body_set (s, ei);
+
+  /* Set length. */
+  length = stream_get_endp (s);
+  lsah->length = htons (length);
+
+  /* Now, create OSPF LSA instance. */
+  new = ospf_lsa_new ();
+  new->area = NULL;
+  SET_FLAG (new->flags, OSPF_LSA_SELF|OSPF_LSA_APPROVED);
+
+  /* Copy LSA data to store, discard stream. */
+  new->data = ospf_lsa_data_new (length);
+  memcpy (new->data, lsah, length);
+  stream_free (s);
+
+  return new;
+}
+
+#ifdef HAVE_NSSA
+/* Set AS-external-LSA body test. */
+void
+ospf_external_lsa_body_test (struct stream *s)
+{
+  struct in_addr mask, fwd_addr;
+  u_int32_t mvalue = 0;
+  /* int mtype;
+     int type; */
+
+  mask.s_addr = 0;
+  fwd_addr.s_addr = 0;
+
+  /* Put Network Mask. */
+  /* masklen2ip (p->prefixlen, &mask); */
+  stream_put_ipv4 (s, mask.s_addr);
+
+  /* If prefix is default, specify DEFAULT_ROUTE. */
+  /* type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
+  
+  mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ?
+  ROUTEMAP_METRIC_TYPE (ei) : metric_type (type);
+
+  mvalue = (ROUTEMAP_METRIC (ei) != -1) ?
+  ROUTEMAP_METRIC (ei) : metric_value (type); */
+
+  /* Put type of external metric. */
+  stream_putc (s,  0);
+
+  /* Put 0 metric. TOS metric is not supported. */
+  stream_put_ospf_metric (s, mvalue);
+  
+ 
+  /*  fwd_addr = ospf_top->router_id; */
+       
+  /* OLD == ospf_external_lsa_nexthop_get (ei->nexthop); */
+
+  /* Put forwarding address. */
+  /* stream_put_ipv4 (s, fwd_addr.s_addr); */
+  stream_put_ipv4 (s, ospf_top->router_id.s_addr);
+  
+  /* Put route tag -- This value should be introduced from configuration. */
+  stream_putl (s, 0);
+}
+
+/* As Type-7 */
+void
+ospf_install_flood_nssa (struct ospf_lsa *lsa, struct external_info *ei)
+{
+  struct ospf_lsa *new2;
+  struct as_external_lsa *extlsa;
+
+  /* NSSA Originate or Refresh (If anyNSSA)
+
+  LSA is self-originated. And just installed as Type-5.
+  Additionally, install as Type-7 LSDB for every attached NSSA.
+
+  P-Bit controls which ABR performs translation to outside world; If
+  we are an ABR....do not set the P-bit, because we send the Type-5,
+  not as the ABR Translator, but as the ASBR owner within the AS!
+
+  If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set.  The
+  elected ABR Translator will see the P-bit, Translate, and re-flood.
+
+  Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to
+  Type-5's to non-NSSA Areas.  (it will also attempt a re-install) */
+
+  /* make lsa duplicate, lock=1 */
+  new2 = ospf_lsa_dup(lsa);
+
+  /* make type-7 */
+  new2->data->type  = OSPF_AS_NSSA_LSA;
+
+  /* set P-bit if not ABR */
+  if (! OSPF_IS_ABR)
+    {
+      SET_FLAG(new2->data->options, OSPF_OPTION_NP);
+
+      /* set non-zero FWD ADDR 
+
+      draft-ietf-ospf-nssa-update-09.txt
+
+      if the network between the NSSA AS boundary router and the
+      adjacent AS is advertised into OSPF as an internal OSPF route, 
+      the forwarding address should be the next op address as is cu
+      currently done with type-5 LSAs.  If the intervening network is 
+      not adversited into OSPF as an internal OSPF route and the 
+      type-7 LSA's P-bit is set a forwarding address should be 
+      selected from one of the router's active OSPF inteface addresses
+      which belong to the NSSA.  If no such addresses exist, then
+      no type-7 LSA's with the P-bit set should originate from this
+      router.   */
+
+      extlsa = (struct as_external_lsa *)(lsa->data);
+
+      if (extlsa->e[0].fwd_addr.s_addr == 0) 
+	extlsa->e[0].fwd_addr = ospf_get_nssa_ip(); /* this NSSA area in ifp */
+
+      if (IS_DEBUG_OSPF_NSSA)
+	if (extlsa->e[0].fwd_addr.s_addr == 0) 
+	  {
+	    zlog_info ("LSA[Type-7]: Could not build FWD-ADDR");
+	    ospf_lsa_discard(new2);
+	    return;
+	  }
+    }
+
+  /* Re-calculate checksum. */
+  ospf_lsa_checksum (new2->data);
+
+  /* install also as Type-7 */
+  ospf_lsa_install (NULL, new2);   /* Remove Old, Lock New = 2 */
+
+  /* will send each copy, lock=2+n */
+  ospf_flood_through_as (NULL, new2); /* all attached NSSA's, no AS/STUBs */
+
+  /* last send, lock=2 LSA is now permanent in Type-7 LSDB */
+  /* It has the same ID as it's Type-5 Counter-Part */
+ 
+}
+#endif /* HAVE_NSSA */
+
+int
+is_prefix_default (struct prefix_ipv4 *p)
+{
+  struct prefix_ipv4 q;
+
+  q.family = AF_INET;
+  q.prefix.s_addr = 0;
+  q.prefixlen = 0;
+
+  return prefix_same ((struct prefix *) p, (struct prefix *) &q);
+}
+
+/* Originate an AS-external-LSA, install and flood. */
+struct ospf_lsa *
+ospf_external_lsa_originate (struct external_info *ei)
+{
+  struct ospf_lsa *new;
+
+  /* Added for NSSA project....
+
+       External LSAs are originated in ASBRs as usual, but for NSSA systems.
+     there is the global Type-5 LSDB and a Type-7 LSDB installed for
+     every area.  The Type-7's are flooded to every IR and every ABR; We
+     install the Type-5 LSDB so that the normal "refresh" code operates
+     as usual, and flag them as not used during ASE calculations.  The
+     Type-7 LSDB is used for calculations.  Each Type-7 has a Forwarding
+     Address of non-zero.
+
+     If an ABR is the elected NSSA translator, following SPF and during
+     the ABR task it will translate all the scanned Type-7's, with P-bit
+     ON and not-self generated, and translate to Type-5's throughout the
+     non-NSSA/STUB AS.
+
+     A difference in operation depends whether this ASBR is an ABR
+     or not.  If not an ABR, the P-bit is ON, to indicate that any
+     elected NSSA-ABR can perform its translation.
+
+     If an ABR, the P-bit is OFF;  No ABR will perform translation and
+     this ASBR will flood the Type-5 LSA as usual.
+
+     For the case where this ASBR is not an ABR, the ASE calculations
+     are based on the Type-5 LSDB;  The Type-7 LSDB exists just to
+     demonstrate to the user that there are LSA's that belong to any
+     attached NSSA.
+
+     Finally, it just so happens that when the ABR is translating every
+     Type-7 into Type-5, it installs it into the Type-5 LSDB as an
+     approved Type-5 (translated from Type-7);  at the end of translation
+     if any Translated Type-5's remain unapproved, then they must be
+     flushed from the AS.
+
+     */
+  
+  /* Check the AS-external-LSA should be originated. */
+  if (!ospf_redistribute_check (ei, NULL))
+    return NULL;
+  
+  /* Create new AS-external-LSA instance. */
+  if ((new = ospf_external_lsa_new (ei, NULL)) == NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("LSA[Type5:%s]: Could not originate AS-external-LSA",
+		   inet_ntoa (ei->p.prefix));
+      return NULL;
+    }
+
+  /* Install newly created LSA into Type-5 LSDB, lock = 1. */
+  ospf_lsa_install (NULL, new);
+
+  /* Update LSA origination count. */
+  ospf_top->lsa_originate_count++;
+
+  /* Flooding new LSA. only to AS (non-NSSA/STUB) */
+  ospf_flood_through_as (NULL, new);
+
+#ifdef HAVE_NSSA
+  /* If there is any attached NSSA, do special handling */
+  if (ospf_top->anyNSSA)
+    ospf_install_flood_nssa (new, ei); /* Install/Flood Type-7 to all NSSAs */
+#endif /* HAVE_NSSA */
+
+  /* Debug logging. */
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: Originate AS-external-LSA %p",
+		 new->data->type, inet_ntoa (new->data->id), new);
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return new;
+}
+
+/* Originate AS-external-LSA from external info with initial flag. */
+int
+ospf_external_lsa_originate_timer (struct thread *t)
+{
+  struct route_node *rn;
+  struct external_info *ei;
+  struct route_table *rt;
+  int type;
+
+  ospf_top->t_external_lsa = NULL;
+  type = THREAD_VAL (t);
+
+  /* Originate As-external-LSA from all type of distribute source. */
+  if ((rt = EXTERNAL_INFO (type)))
+    for (rn = route_top (rt); rn; rn = route_next (rn))
+      if ((ei = rn->info) != NULL)
+	if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p))
+	  if (!ospf_external_lsa_originate (ei))
+	    zlog_warn ("LSA: AS-external-LSA was not originated.");
+  
+  return 0;
+}
+
+struct external_info *
+ospf_default_external_info ()
+{
+  int type;
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+  
+  p.family = AF_INET;
+  p.prefix.s_addr = 0;
+  p.prefixlen = 0;
+
+  /* First, lookup redistributed default route. */
+  for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
+    if (EXTERNAL_INFO (type) && type != ZEBRA_ROUTE_OSPF)
+      {
+	rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p);
+	if (rn != NULL)
+	  {
+	    route_unlock_node (rn);
+	    assert (rn->info);
+	    if (ospf_redistribute_check (rn->info, NULL))
+	      return rn->info;
+	  }
+      }
+
+  return NULL;
+}
+
+int
+ospf_default_originate_timer (struct thread *t)
+{
+  int *origin;
+  struct prefix_ipv4 p;
+  struct in_addr nexthop;
+  struct external_info *ei;
+  
+  /* Get originate flags. */
+  origin = THREAD_ARG (t);
+
+  p.family = AF_INET;
+  p.prefix.s_addr = 0;
+  p.prefixlen = 0;
+
+  if (*origin == DEFAULT_ORIGINATE_ALWAYS)
+    {
+      /* If there is no default route via redistribute,
+	 then originate AS-external-LSA with nexthop 0 (self). */
+      nexthop.s_addr = 0;
+      ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop);
+    }
+
+  if ((ei = ospf_default_external_info ()))
+    ospf_external_lsa_originate (ei);
+  
+  return 0;
+}
+
+/* Flush an AS-external-LSA from LSDB and routing domain. */
+void
+ospf_external_lsa_flush (u_char type, struct prefix_ipv4 *p,
+			 unsigned int ifindex, struct in_addr nexthop)
+{
+  struct ospf_lsa *lsa;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+    zlog_info ("LSA: Flushing AS-external-LSA %s/%d",
+	       inet_ntoa (p->prefix), p->prefixlen);
+
+  /* First lookup LSA from LSDB. */
+  if (!(lsa = ospf_external_info_find_lsa (p)))
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+	zlog_warn ("LSA: There is no such AS-external-LSA %s/%d in LSDB",
+		   inet_ntoa (p->prefix), p->prefixlen);
+      return;
+    }
+
+  /* Sweep LSA from Link State Retransmit List. */
+  ospf_ls_retransmit_delete_nbr_all (NULL, lsa);
+
+  /* There must be no self-originated LSA in rtrs_external. */
+#if 0
+  /* Remove External route from Zebra. */
+  ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop);
+#endif
+
+  if (!IS_LSA_MAXAGE (lsa))
+    {
+      /* Unregister LSA from Refresh queue. */
+      ospf_refresher_unregister_lsa (ospf_top, lsa);
+
+      /* Flush AS-external-LSA through AS. */
+      ospf_flush_through_as (lsa);
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+    zlog_info ("ospf_external_lsa_flush(): stop");
+}
+
+void
+ospf_external_lsa_refresh_default ()
+{
+  struct prefix_ipv4 p;
+  struct external_info *ei;
+  struct ospf_lsa *lsa;
+
+  p.family = AF_INET;
+  p.prefixlen = 0;
+  p.prefix.s_addr = 0;
+
+  ei = ospf_default_external_info ();
+  lsa = ospf_external_info_find_lsa (&p);
+
+  if (ei)
+    {
+      if (lsa)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", lsa);
+	  ospf_external_lsa_refresh (lsa, ei, LSA_REFRESH_FORCE);
+	}
+      else
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
+	  ospf_external_lsa_originate (ei);
+	}
+    }
+  else
+    {
+      if (lsa)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
+	  ospf_lsa_flush_as (lsa);
+	}
+    }
+}
+
+void
+ospf_external_lsa_refresh_type (u_char type, int force)
+{
+  struct route_node *rn;
+  struct external_info *ei;
+
+  if (type != DEFAULT_ROUTE)
+    if (EXTERNAL_INFO(type))
+      /* Refresh each redistributed AS-external-LSAs. */
+      for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn))
+	if ((ei = rn->info))
+	  if (!is_prefix_default (&ei->p))
+	    {
+	      struct ospf_lsa *lsa;
+
+	      if ((lsa = ospf_external_info_find_lsa (&ei->p)))
+		ospf_external_lsa_refresh (lsa, ei, force);
+	      else
+		ospf_external_lsa_originate (ei);
+	    }
+}
+
+/* Refresh AS-external-LSA. */
+void
+ospf_external_lsa_refresh (struct ospf_lsa *lsa,
+			   struct external_info *ei, int force)
+{
+  struct ospf_lsa *new;
+  int changed;
+  
+  /* Check the AS-external-LSA should be originated. */
+  if (!ospf_redistribute_check (ei, &changed))
+    {
+      ospf_external_lsa_flush (ei->type, &ei->p, ei->ifindex, ei->nexthop);
+      return;
+    }
+
+  if (!changed && !force)
+    return;
+
+  /* Delete LSA from neighbor retransmit-list. */
+  ospf_ls_retransmit_delete_nbr_all (NULL, lsa);
+
+  /* Unregister AS-external-LSA from refresh-list. */
+  ospf_refresher_unregister_lsa (ospf_top, lsa);
+
+  new = ospf_external_lsa_new (ei, &lsa->data->id);
+  
+  if (new == NULL)
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+	zlog_warn ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type,
+		   inet_ntoa (lsa->data->id));
+      return;
+    }
+  
+  new->data->ls_seqnum = lsa_seqnum_increment (lsa);
+
+  /* Record timestamp. */
+  gettimeofday (&new->tv_orig, NULL);
+
+  /* Re-calculate checksum. */
+  ospf_lsa_checksum (new->data);
+
+  ospf_lsa_install (NULL, new);	/* As type-5. */
+
+  /* Flood LSA through AS. */
+  ospf_flood_through_as (NULL, new);
+
+#ifdef HAVE_NSSA
+  /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
+  if (ospf_top->anyNSSA)
+    ospf_install_flood_nssa (new, ei); /* Install/Flood per new rules */
+#endif /* HAVE_NSSA */
+
+  /* Register slef-originated LSA to refresh queue. */
+  ospf_refresher_register_lsa (ospf_top, new);
+
+  /* Debug logging. */
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: AS-external-LSA refresh",
+		 new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_header_dump (new->data);
+    }
+
+  return;
+}
+
+
+/* LSA installation functions. */
+
+/* Install router-LSA to an area. */
+struct ospf_lsa *
+ospf_router_lsa_install (struct ospf_lsa *new, int rt_recalc)
+{
+  struct ospf_area *area = new->area;
+
+  /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
+     The entire routing table must be recalculated, starting with
+     the shortest path calculations for each area (not just the
+     area whose link-state database has changed). 
+  */
+  if (rt_recalc)
+    ospf_spf_calculate_schedule();
+
+  if (IS_LSA_SELF (new))
+    {
+      /* Set router-LSA refresh timer. */
+      OSPF_TIMER_OFF (area->t_router_lsa_self);
+      OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
+			  ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME);
+      
+      /* Set self-originated router-LSA. */
+      ospf_lsa_unlock (area->router_lsa_self);
+      area->router_lsa_self = ospf_lsa_lock (new);
+
+      if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
+	zlog_info("LSA[Type%d]: ID %s is self-originated",
+		  new->data->type, inet_ntoa (new->data->id));
+    }
+
+  return new;
+}
+
+#define OSPF_INTERFACE_TIMER_ON(T,F,V) \
+	if (!(T)) \
+	  (T) = thread_add_timer (master, (F), oi, (V))
+
+/* Install network-LSA to an area. */
+struct ospf_lsa *
+ospf_network_lsa_install (struct ospf_interface *oi, 
+			  struct ospf_lsa *new,
+			  int rt_recalc)
+{
+
+  /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
+     The entire routing table must be recalculated, starting with
+     the shortest path calculations for each area (not just the
+     area whose link-state database has changed). 
+  */
+  if (rt_recalc)
+    ospf_spf_calculate_schedule();
+
+  /* We supposed that when LSA is originated by us, we pass the int
+     for which it was originated. If LSA was received by flooding,
+     the RECEIVED flag is set, so we do not link the LSA to the int. */
+  if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
+    {
+      /* Set LSRefresh timer. */
+      OSPF_TIMER_OFF (oi->t_network_lsa_self);
+
+      OSPF_INTERFACE_TIMER_ON (oi->t_network_lsa_self,
+			       ospf_network_lsa_refresh_timer,
+			       OSPF_LS_REFRESH_TIME);
+
+      ospf_lsa_unlock (oi->network_lsa_self);
+      oi->network_lsa_self = ospf_lsa_lock (new);
+    }
+
+  return new;
+}
+
+/* Install summary-LSA to an area. */
+struct ospf_lsa *
+ospf_summary_lsa_install (struct ospf_lsa *new, int rt_recalc)
+{
+
+  if (rt_recalc && !IS_LSA_SELF (new))
+    {
+      /* RFC 2328 Section 13.2 Summary-LSAs
+	 The best route to the destination described by the summary-
+	 LSA must be recalculated (see Section 16.5).  If this
+	 destination is an AS boundary router, it may also be
+	 necessary to re-examine all the AS-external-LSAs.
+      */
+
+#if 0
+      /* This doesn't exist yet... */
+      ospf_summary_incremental_update(new); */
+#else /* #if 0 */
+      ospf_spf_calculate_schedule();
+#endif /* #if 0 */
+ 
+      if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
+	zlog_info ("ospf_summary_lsa_install(): SPF scheduled");
+    }
+
+  if (IS_LSA_SELF (new))
+    ospf_refresher_register_lsa (ospf_top, new);
+
+  return new;
+}
+
+/* Install ASBR-summary-LSA to an area. */
+struct ospf_lsa *
+ospf_summary_asbr_lsa_install (struct ospf_lsa *new, int rt_recalc)
+{
+  if (rt_recalc && !IS_LSA_SELF (new))
+    {
+      /* RFC 2328 Section 13.2 Summary-LSAs
+	 The best route to the destination described by the summary-
+	 LSA must be recalculated (see Section 16.5).  If this
+	 destination is an AS boundary router, it may also be
+	 necessary to re-examine all the AS-external-LSAs.
+      */
+#if 0
+      /* These don't exist yet... */
+      ospf_summary_incremental_update(new);
+      /* Isn't this done by the above call? 
+	 - RFC 2328 Section 16.5 implies it should be */
+      /* ospf_ase_calculate_schedule(); */
+#else  /* #if 0 */
+      ospf_spf_calculate_schedule();
+#endif /* #if 0 */
+    }
+
+  /* register LSA to refresh-list. */
+  if (IS_LSA_SELF (new))
+    ospf_refresher_register_lsa (ospf_top, new);
+
+  return new;
+}
+
+/* Install AS-external-LSA. */
+struct ospf_lsa *
+ospf_external_lsa_install (struct ospf_lsa *new, int rt_recalc)
+{
+  ospf_ase_register_external_lsa (new, ospf_top);
+  /* If LSA is not self-originated, calculate an external route. */
+  if (rt_recalc)
+    {
+      /* RFC 2328 Section 13.2 AS-external-LSAs
+            The best route to the destination described by the AS-
+            external-LSA must be recalculated (see Section 16.6).
+      */
+
+      if (!IS_LSA_SELF (new))
+	ospf_ase_incremental_update (new, ospf_top);
+    }
+
+  /* Register self-originated LSA to refresh queue. */
+  if (IS_LSA_SELF (new))
+    ospf_refresher_register_lsa (ospf_top, new);
+
+  return new;
+}
+
+void
+ospf_discard_from_db (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
+{
+  struct ospf_lsa *old;
+  
+  old = ospf_lsdb_lookup (lsdb, lsa);
+
+  if (!old)
+    return;
+
+  if (old->refresh_list >= 0)
+    ospf_refresher_unregister_lsa (ospf_top, old);
+
+  ospf_ls_retransmit_delete_nbr_all (old->area, old);
+
+  switch (old->data->type)
+    {
+    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      ospf_ase_unregister_external_lsa (old, ospf_top);
+      break;
+    default:
+      break;
+    }
+
+  ospf_lsa_maxage_delete (old);
+  ospf_lsa_discard (old);
+}
+
+/* callback for foreach_lsa */
+int
+ospf_lsa_discard_callback (struct ospf_lsa *lsa, void *p, int i)
+{
+#ifdef HAVE_NSSA
+  /* Removed: Stay away from any Local Translated Type-7 LSAs */
+  /* if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+     return 0; */
+#endif /* HAVE_NSSA */
+  ospf_discard_from_db ((struct ospf_lsdb *)p, lsa);
+  return 0;
+}
+
+struct ospf_lsa *
+ospf_lsa_install (struct ospf_interface *oi, struct ospf_lsa *lsa)
+{
+  struct ospf_lsa *new = NULL;
+  struct ospf_lsa *old = NULL;
+  struct ospf_lsdb *lsdb = NULL;
+  int rt_recalc;
+
+  /* Set LSDB. */
+  switch (lsa->data->type)
+    {
+    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      lsdb = ospf_top->lsdb;
+      break;
+    default:
+      lsdb = lsa->area->lsdb;
+      break;
+    }
+
+#ifdef HAVE_NSSA
+  if (IS_DEBUG_OSPF_NSSA)
+    {
+      zlog_info ("LSA[Installing]: Type-%d ", lsa->data->type);
+
+      if  (lsa->data->type == OSPF_AS_NSSA_LSA )
+	zlog_info ("NSSA LSA AREA = %s", inet_ntoa (lsa->area->area_id));
+    }
+#endif /* HAVE_NSSA */
+
+  assert (lsdb);
+
+  /*  RFC 2328 13.2.  Installing LSAs in the database
+
+        Installing a new LSA in the database, either as the result of
+        flooding or a newly self-originated LSA, may cause the OSPF
+        routing table structure to be recalculated.  The contents of the
+        new LSA should be compared to the old instance, if present.  If
+        there is no difference, there is no need to recalculate the
+        routing table. When comparing an LSA to its previous instance,
+        the following are all considered to be differences in contents:
+
+            o   The LSA's Options field has changed.
+
+            o   One of the LSA instances has LS age set to MaxAge, and
+                the other does not.
+
+            o   The length field in the LSA header has changed.
+
+            o   The body of the LSA (i.e., anything outside the 20-byte
+                LSA header) has changed. Note that this excludes changes
+                in LS Sequence Number and LS Checksum.
+
+  */
+  /* Look up old LSA and determine if any SPF calculation or incremental
+     update is needed */
+  old = ospf_lsdb_lookup (lsdb, lsa);
+
+  /* Do comparision and record if recalc needed. */
+  rt_recalc = 0;
+  if (  old == NULL || ospf_lsa_different(old, lsa))
+    rt_recalc = 1;
+
+  /* discard old LSA from LSDB */
+  if (old != NULL)
+    ospf_discard_from_db (lsdb, lsa);
+
+  /* Insert LSA to LSDB. */
+  ospf_lsdb_add (lsdb, lsa);
+  lsa->lsdb = lsdb;
+
+  /* Calculate Checksum if self-originated?. */
+  if (IS_LSA_SELF (lsa))
+    ospf_lsa_checksum (lsa->data);
+
+  /* Do LSA specific installation process. */
+  switch (lsa->data->type)
+    {
+    case OSPF_ROUTER_LSA:
+      new = ospf_router_lsa_install (lsa, rt_recalc);
+      break;
+    case OSPF_NETWORK_LSA:
+      assert (oi);
+      new = ospf_network_lsa_install (oi, lsa, rt_recalc);
+      break;
+    case OSPF_SUMMARY_LSA:
+      new = ospf_summary_lsa_install (lsa, rt_recalc);
+      break;
+    case OSPF_ASBR_SUMMARY_LSA:
+      new = ospf_summary_asbr_lsa_install (lsa, rt_recalc);
+      break;
+    case OSPF_AS_EXTERNAL_LSA:
+      new = ospf_external_lsa_install (lsa, rt_recalc);
+      break;
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+    case OSPF_OPAQUE_AS_LSA:
+      new = ospf_opaque_lsa_install (lsa, rt_recalc);
+      break;
+#endif /* HAVE_OPAQUE_LSA */
+    default: /* NSSA, or type-6,8,9....nothing special */
+#ifdef HAVE_NSSA
+      new = ospf_external_lsa_install (lsa, rt_recalc);
+#endif /* HAVE_NSSA */
+      break;
+    }
+
+  if (new == NULL)
+    return new;  /* Installation failed, cannot proceed further -- endo. */
+
+  /* Debug logs. */
+  if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
+    {
+      char area_str[INET_ADDRSTRLEN];
+
+      switch (lsa->data->type)
+        {
+        case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+        case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+          zlog_info ("LSA[%s]: Install %s",
+                 dump_lsa_key (new),
+                 LOOKUP (ospf_lsa_type_msg, new->data->type));
+          break;
+        default:
+	  strcpy (area_str, inet_ntoa (new->area->area_id));
+          zlog_info ("LSA[%s]: Install %s to Area %s",
+                 dump_lsa_key (new),
+                 LOOKUP (ospf_lsa_type_msg, new->data->type), area_str);
+          break;
+        }
+    }
+
+  /* If received LSA' ls_age is MaxAge, set LSA on MaxAge LSA list. */
+  if (IS_LSA_MAXAGE (new) && !IS_LSA_SELF (new))
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+	zlog_info ("LSA[Type%d:%s]: Install LSA, MaxAge",
+		   new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_maxage (lsa);
+    }
+
+  return new;
+}
+
+
+int
+ospf_check_nbr_status ()
+{
+  listnode node;
+
+  for (node = listhead (ospf_top->oiflist); node; node = nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+
+      if (ospf_if_is_enable (oi))
+	for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+          if ((nbr = rn->info) != NULL)
+	    if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading)
+	      {
+		route_unlock_node (rn);
+		return 0;
+	      }
+    }
+
+  return 1;
+}
+
+
+#ifdef ORIGINAL_CODING
+/* This function flood the maxaged LSA to DR. */
+void
+ospf_maxage_flood (struct ospf_lsa *lsa)
+{
+  switch (lsa->data->type)
+    {
+    case OSPF_ROUTER_LSA:
+    case OSPF_NETWORK_LSA:
+    case OSPF_SUMMARY_LSA:
+    case OSPF_ASBR_SUMMARY_LSA:
+#ifdef HAVE_NSSA
+    case OSPF_AS_NSSA_LSA:
+#endif /* HAVE_NSSA */
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      ospf_flood_through_area (lsa->area, NULL, lsa);
+      break;
+    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      ospf_flood_through_as (NULL, lsa);
+      break;
+    default:
+      break;
+    }
+}
+#endif /* ORIGINAL_CODING */
+
+int
+ospf_maxage_lsa_remover (struct thread *thread)
+{
+  listnode node;
+  listnode next;
+  int reschedule = 0;
+
+  ospf_top->t_maxage = NULL;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+    zlog_info ("LSA[MaxAge]: remover Start");
+
+  reschedule = !ospf_check_nbr_status ();
+
+  if (!reschedule)
+    for (node = listhead (ospf_top->maxage_lsa); node; node = next)
+      {
+        struct ospf_lsa *lsa = getdata (node);
+        next = node->next;
+
+        if (lsa->retransmit_counter > 0)
+          {
+            reschedule = 1;
+            continue;
+          }
+
+        /* Remove LSA from the LSDB */
+        if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF))
+          if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+            zlog_info ("LSA[Type%d:%s]: This LSA is self-originated: ",
+                       lsa->data->type, inet_ntoa (lsa->data->id));
+
+        if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+          zlog_info ("LSA[Type%d:%s]: MaxAge LSA removed from list",
+                     lsa->data->type, inet_ntoa (lsa->data->id));
+
+	/* Flood max age LSA. */
+#ifdef ORIGINAL_CODING
+	ospf_maxage_flood (lsa);
+#else /* ORIGINAL_CODING */
+        ospf_flood_through (NULL, lsa);
+#endif /* ORIGINAL_CODING */
+
+	/* Remove from lsdb. */
+        ospf_discard_from_db (lsa->lsdb, lsa);
+        ospf_lsdb_delete (lsa->lsdb, lsa);
+      }
+
+  /*    A MaxAge LSA must be removed immediately from the router's link
+        state database as soon as both a) it is no longer contained on any
+        neighbor Link state retransmission lists and b) none of the router's
+        neighbors are in states Exchange or Loading. */
+  if (reschedule)
+    OSPF_SCHEDULE_MAXAGE (ospf_top->t_maxage, ospf_maxage_lsa_remover);
+
+  return 0;
+}
+
+int
+ospf_lsa_maxage_exist (struct ospf_lsa *new)
+{
+  listnode node;
+
+  for (node = listhead (ospf_top->maxage_lsa); node; nextnode (node))
+    if (((struct ospf_lsa *) node->data) == new)
+      return 1;
+
+  return 0;
+}
+
+void
+ospf_lsa_maxage_delete (struct ospf_lsa *lsa)
+{
+  listnode n;
+
+  if ((n = listnode_lookup (ospf_top->maxage_lsa, lsa)))
+    {
+      list_delete_node (ospf_top->maxage_lsa, n);
+      ospf_lsa_unlock (lsa);
+    }
+}
+
+void
+ospf_lsa_maxage (struct ospf_lsa *lsa)
+{
+  /* When we saw a MaxAge LSA flooded to us, we put it on the list
+     and schedule the MaxAge LSA remover. */
+  if (ospf_lsa_maxage_exist (lsa))
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+	zlog_info ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list",
+		   lsa->data->type, inet_ntoa (lsa->data->id), lsa);
+      return;
+    }
+
+  listnode_add (ospf_top->maxage_lsa, ospf_lsa_lock (lsa));
+
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+    zlog_info ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa));
+
+  OSPF_SCHEDULE_MAXAGE (ospf_top->t_maxage, ospf_maxage_lsa_remover);
+}
+
+int
+ospf_lsa_maxage_walker_remover (struct ospf_lsa *lsa, void *p_arg, int int_arg)
+{
+#ifdef HAVE_NSSA
+  /* Stay away from any Local Translated Type-7 LSAs */
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+    return 0;
+#endif /* HAVE_NSSA */
+
+  if (IS_LSA_MAXAGE (lsa))
+    /* Self-originated LSAs should NOT time-out instead,
+       they're flushed and submitted to the max_age list explicitly. */
+    if (!ospf_lsa_is_self_originated (lsa))
+      {
+	if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+	  zlog_info("LSA[%s]: is MaxAge", dump_lsa_key (lsa));
+
+        switch (lsa->data->type)
+          {
+          case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+          case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+	    ospf_ase_incremental_update (lsa, ospf_top);
+            break;
+          default:
+	    ospf_spf_calculate_schedule ();
+            break;
+          }
+
+	ospf_lsa_maxage (lsa);
+      }
+
+  return 0;
+}
+
+/* Periodical check of MaxAge LSA. */
+int
+ospf_lsa_maxage_walker (struct thread *t)
+{
+  listnode node;
+
+  ospf_top->t_maxage_walker = NULL;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      struct ospf_area *area = node->data;
+
+      foreach_lsa (ROUTER_LSDB (area), NULL, 0,
+		   ospf_lsa_maxage_walker_remover);
+      foreach_lsa (NETWORK_LSDB (area), NULL, 0,
+		   ospf_lsa_maxage_walker_remover);
+      foreach_lsa (SUMMARY_LSDB (area), NULL, 0,
+		   ospf_lsa_maxage_walker_remover);
+      foreach_lsa (ASBR_SUMMARY_LSDB (area), NULL, 0,
+		   ospf_lsa_maxage_walker_remover);
+#ifdef HAVE_OPAQUE_LSA
+      foreach_lsa (OPAQUE_LINK_LSDB (area), NULL, 0,
+		   ospf_lsa_maxage_walker_remover);
+      foreach_lsa (OPAQUE_AREA_LSDB (area), NULL, 0,
+		   ospf_lsa_maxage_walker_remover);
+#endif /* HAVE_OPAQUE_LSA */
+    }
+
+  /* for AS-eternal-LSAs. */
+  if (ospf_top->lsdb)
+    foreach_lsa (EXTERNAL_LSDB (ospf_top), NULL, 0,
+		 ospf_lsa_maxage_walker_remover);
+
+#ifdef HAVE_OPAQUE_LSA
+  if (ospf_top->lsdb)
+    foreach_lsa (OPAQUE_AS_LSDB (ospf_top), NULL, 0,
+		 ospf_lsa_maxage_walker_remover);
+#endif /* HAVE_OPAQUE_LSA */
+
+  ospf_top->t_maxage_walker = 
+    thread_add_timer (master, ospf_lsa_maxage_walker, NULL,
+                      OSPF_LSA_MAXAGE_CHECK_INTERVAL);
+  return 0;
+}
+
+int
+find_summary (struct ospf_lsa *lsa, void * v, int i)
+{
+  struct prefix_ipv4 *p, pr;
+
+  if ((p = (struct prefix_ipv4 *) v) != NULL)
+    if (lsa != NULL)
+      /* We're looking for self-originated one */
+      if (ospf_lsa_is_self_originated (lsa))
+	{
+	  struct summary_lsa *sl = (struct summary_lsa *) lsa->data;
+
+	  pr.family = AF_INET;
+	  pr.prefix = sl->header.id;
+	  pr.prefixlen = ip_masklen (sl->mask);
+	  apply_mask_ipv4 (&pr);
+
+	  if (prefix_same ((struct prefix*) &pr, (struct prefix*) p))
+	    return 1;
+	}
+
+  return 0;
+}
+
+int
+find_asbr_summary (struct ospf_lsa *lsa, void * v, int i)
+{
+  struct prefix_ipv4 *p;
+
+  if ((p = (struct prefix_ipv4 *) v) != NULL)
+    if (lsa != NULL)
+      /* We're looking for self-originated one */
+      if (ospf_lsa_is_self_originated (lsa))
+	{
+	  struct summary_lsa *sl = (struct summary_lsa *) lsa->data;
+
+	  if (IPV4_ADDR_SAME (&p->prefix, &sl->header.id))
+	    return 1;
+	}
+
+  return 0;
+}
+
+struct ospf_lsa *
+ospf_lsa_lookup (struct ospf_area *area, u_int32_t type,
+                 struct in_addr id, struct in_addr adv_router)
+{
+  switch (type)
+    {
+    case OSPF_ROUTER_LSA:
+    case OSPF_NETWORK_LSA:
+    case OSPF_SUMMARY_LSA:
+    case OSPF_ASBR_SUMMARY_LSA:
+#ifdef HAVE_NSSA
+    case OSPF_AS_NSSA_LSA:
+#endif /* HAVE_NSSA */
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router);
+      break;
+    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      return ospf_lsdb_lookup_by_id (ospf_top->lsdb, type, id, adv_router);
+      break;
+    default:
+      break;
+    }
+
+  return NULL;
+}
+
+struct ospf_lsa *
+ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type, 
+                       struct in_addr id)
+{
+  struct ospf_lsa *lsa;
+  struct route_node *rn;
+
+  switch (type)
+    {
+    case OSPF_ROUTER_LSA:
+      return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
+      break;
+    case OSPF_NETWORK_LSA:
+      for (rn = route_top (NETWORK_LSDB (area)); rn; rn = route_next (rn))
+	if ((lsa = rn->info))
+	  if (IPV4_ADDR_SAME (&lsa->data->id, &id))
+	    {
+	      route_unlock_node (rn);
+	      return lsa;
+	    }
+      break;
+    case OSPF_SUMMARY_LSA:
+    case OSPF_ASBR_SUMMARY_LSA:
+      /* Currently not used. */
+      assert (1);
+      return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
+      break;
+    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+    case OSPF_OPAQUE_AS_LSA:
+      /* Currently not used. */
+      break;
+#endif /* HAVE_OPAQUE_LSA */
+    default:
+      break;
+    }
+
+  return NULL;
+}
+
+struct ospf_lsa *
+ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah)
+{
+  struct ospf_lsa *match;
+
+#ifdef HAVE_OPAQUE_LSA
+  /*
+   * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11)
+   * is redefined to have two subfields; opaque-type and opaque-id.
+   * However, it is harmless to treat the two sub fields together, as if
+   * they two were forming a unique LSA-ID.
+   */
+#endif /* HAVE_OPAQUE_LSA */
+
+  match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router);
+
+  if (match == NULL)
+    if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
+      zlog_info ("LSA[Type%d:%s]: Lookup by header, NO MATCH",
+		 lsah->type, inet_ntoa (lsah->id));
+
+  return match;
+}
+
+/* return +n, l1 is more recent.
+   return -n, l2 is more recent.
+   return 0, l1 and l2 is identical. */
+int
+ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2)
+{
+  int r;
+  int x, y;
+
+  if (l1 == NULL && l2 == NULL)
+    return 0;
+  if (l1 == NULL)
+    return -1;
+  if (l2 == NULL)
+    return 1;
+
+  /* compare LS sequence number. */
+  x = (int) ntohl (l1->data->ls_seqnum);
+  y = (int) ntohl (l2->data->ls_seqnum);
+  if (x > y)
+    return 1;
+  if (x < y)
+    return -1;
+
+  /* compare LS checksum. */
+  r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum);
+  if (r)
+    return r;
+
+  /* compare LS age. */
+  if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
+    return 1;
+  else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2))
+    return -1;
+
+  /* compare LS age with MaxAgeDiff. */
+  if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF)
+    return -1;
+  else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF)
+    return 1;
+
+  /* LSAs are identical. */
+  return 0;
+}
+
+/* If two LSAs are different, return 1, otherwise return 0. */
+int
+ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2)
+{
+  char *p1, *p2;
+  assert (l1);
+  assert (l2);
+  assert (l1->data);
+  assert (l2->data);
+
+  if (l1->data->options != l2->data->options)
+    return 1;
+
+  if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
+    return 1;
+
+  if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1))
+    return 1;
+
+  if (l1->data->length != l2->data->length)
+    return 1;
+
+  if (l1->data->length ==  0)
+    return 1;
+
+  assert (l1->data->length > OSPF_LSA_HEADER_SIZE);
+
+  p1 = (char *) l1->data;
+  p2 = (char *) l2->data;
+
+  if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
+              ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0)
+    return 1;
+
+  return 0;
+}
+
+#ifdef ORIGINAL_CODING
+void
+ospf_lsa_flush_self_originated (struct ospf_neighbor *nbr,
+                                struct ospf_lsa *self,
+                                struct ospf_lsa *new)
+{
+  u_int32_t seqnum;
+
+  /* Adjust LS Sequence Number. */
+  seqnum = ntohl (new->data->ls_seqnum) + 1;
+  self->data->ls_seqnum = htonl (seqnum);
+
+  /* Recalculate LSA checksum. */
+  ospf_lsa_checksum (self->data);
+
+  /* Reflooding LSA. */
+  /*  RFC2328  Section 13.3
+	    On non-broadcast networks, separate	Link State Update
+	    packets must be sent, as unicasts, to each adjacent	neighbor
+	    (i.e., those in state Exchange or greater).	 The destination
+	    IP addresses for these packets are the neighbors' IP
+	    addresses.   */
+  if (nbr->oi->type == OSPF_IFTYPE_NBMA)
+    {
+      struct route_node *rn;
+      struct ospf_neighbor *onbr;
+
+      for (rn = route_top (nbr->oi->nbrs); rn; rn = route_next (rn))
+	if ((onbr = rn->info) != NULL)
+	  if (onbr != nbr->oi->nbr_self && onbr->status >= NSM_Exchange)
+	    ospf_ls_upd_send_lsa (onbr, self, OSPF_SEND_PACKET_DIRECT);
+    }
+  else
+  ospf_ls_upd_send_lsa (nbr, self, OSPF_SEND_PACKET_INDIRECT);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type%d:%s]: Flush self-originated LSA",
+	       self->data->type, inet_ntoa (self->data->id));
+}
+#else /* ORIGINAL_CODING */
+static int
+ospf_lsa_flush_schedule (struct ospf_lsa *lsa, void *v, int i)
+{
+  if (lsa == NULL || !IS_LSA_SELF (lsa))
+    return 0;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
+
+  /* Force given lsa's age to MaxAge. */
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+
+  switch (lsa->data->type)
+    {
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+    case OSPF_OPAQUE_AS_LSA:
+      ospf_opaque_lsa_refresh (lsa);
+      break;
+#endif /* HAVE_OPAQUE_LSA */
+    default:
+      ospf_lsa_maxage (lsa);
+      break;
+    }
+
+  return 0;
+}
+
+void
+ospf_flush_self_originated_lsas_now (struct ospf *top)
+{
+  listnode n1, n2;
+  struct ospf_area *area;
+  struct ospf_interface *oi;
+  struct ospf_lsa *lsa;
+  int need_to_flush_ase = 0;
+
+  for (n1 = listhead (top->areas); n1; nextnode (n1))
+    {
+      if ((area = getdata (n1)) == NULL)
+        continue;
+
+      if ((lsa = area->router_lsa_self) != NULL)
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
+
+          ospf_lsa_flush_area (lsa, area);
+          ospf_lsa_unlock (area->router_lsa_self);
+          area->router_lsa_self = NULL;
+          OSPF_TIMER_OFF (area->t_router_lsa_self);
+        }
+
+      for (n2 = listhead (area->oiflist); n2; nextnode (n2))
+        {
+          if ((oi = getdata (n2)) == NULL)
+            continue;
+
+          if ((lsa = oi->network_lsa_self) != NULL
+          &&   oi->state == ISM_DR
+          &&   oi->full_nbrs > 0)
+            {
+              if (IS_DEBUG_OSPF_EVENT)
+                zlog_info ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
+
+              ospf_lsa_flush_area (oi->network_lsa_self, area);
+              ospf_lsa_unlock (oi->network_lsa_self);
+              oi->network_lsa_self = NULL;
+              OSPF_TIMER_OFF (oi->t_network_lsa_self);
+            }
+
+          if (oi->type != OSPF_IFTYPE_VIRTUALLINK
+          &&  area->external_routing == OSPF_AREA_DEFAULT)
+            need_to_flush_ase = 1;
+        }
+
+      foreach_lsa (SUMMARY_LSDB (area), NULL, 0, ospf_lsa_flush_schedule);
+      foreach_lsa (ASBR_SUMMARY_LSDB (area), NULL, 0, ospf_lsa_flush_schedule);
+#ifdef HAVE_OPAQUE_LSA
+      foreach_lsa (OPAQUE_LINK_LSDB (area),
+                   NULL, 0, ospf_lsa_flush_schedule);
+      foreach_lsa (OPAQUE_AREA_LSDB (area),
+                   NULL, 0, ospf_lsa_flush_schedule);
+#endif /* HAVE_OPAQUE_LSA */
+    }
+
+  if (need_to_flush_ase)
+    {
+        foreach_lsa (EXTERNAL_LSDB (top), NULL, 0, ospf_lsa_flush_schedule);
+#ifdef HAVE_OPAQUE_LSA
+        foreach_lsa (OPAQUE_AS_LSDB (top),
+                     NULL, 0, ospf_lsa_flush_schedule);
+#endif /* HAVE_OPAQUE_LSA */
+    }
+
+  /*
+   * Make sure that the MaxAge LSA remover is executed immediately,
+   * without conflicting to other threads.
+   */
+  if (top->t_maxage != NULL)
+    {
+      OSPF_TIMER_OFF (top->t_maxage);
+      thread_execute (master, ospf_maxage_lsa_remover, top, 0);
+    }
+
+  return;
+}
+#endif /* ORIGINAL_CODING */
+
+/* If there is self-originated LSA, then return 1, otherwise return 0. */
+/* An interface-independent version of ospf_lsa_is_self_originated */
+int 
+ospf_lsa_is_self_originated (struct ospf_lsa *lsa)
+{
+  listnode node;
+
+  /* This LSA is already checked. */
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED))
+    return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
+
+  /* Make sure LSA is self-checked. */
+  SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED);
+
+  /* AdvRouter and Router ID is the same. */
+  if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf_top->router_id))
+    SET_FLAG (lsa->flags, OSPF_LSA_SELF);
+
+  /* LSA is router-LSA. */
+  else if (lsa->data->type == OSPF_ROUTER_LSA &&
+      IPV4_ADDR_SAME (&lsa->data->id, &ospf_top->router_id))
+    SET_FLAG (lsa->flags, OSPF_LSA_SELF);
+
+  /* LSA is network-LSA.  Compare Link ID with all interfaces. */
+  else if (lsa->data->type == OSPF_NETWORK_LSA)
+    for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+      {
+	struct ospf_interface *oi = getdata (node);
+
+	/* Ignore virtual link. */
+        if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
+	  if (oi->address->family == AF_INET)
+	    if (IPV4_ADDR_SAME (&lsa->data->id, &oi->address->u.prefix4))
+	      {
+		/* to make it easier later */
+		SET_FLAG (lsa->flags, OSPF_LSA_SELF);
+		return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
+	      }
+      }
+
+  return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
+}
+
+/* Get unique Link State ID. */
+struct in_addr
+ospf_lsa_unique_id (struct ospf_lsdb *lsdb, u_char type, struct prefix_ipv4 *p)
+{
+  struct ospf_lsa *lsa;
+  struct in_addr mask, id;
+
+  id = p->prefix;
+
+  /* Check existence of LSA instance. */
+  lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, ospf_top->router_id);
+  if (lsa)
+    {
+      struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
+      if (ip_masklen (al->mask) == p->prefixlen)
+	{
+	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+	    zlog_warn ("ospf_lsa_unique_id(): "
+		       "Can't get Link State ID for %s/%d",
+		       inet_ntoa (p->prefix), p->prefixlen);
+	  /*	  id.s_addr = 0; */
+	  id.s_addr = 0xffffffff;
+	  return id;
+	}
+      /* Masklen differs, then apply wildcard mask to Link State ID. */
+      else
+	{
+	  masklen2ip (p->prefixlen, &mask);
+
+	  id.s_addr = p->prefix.s_addr | (~mask.s_addr);
+	  lsa = ospf_lsdb_lookup_by_id (ospf_top->lsdb, type,
+				       id, ospf_top->router_id);
+	  if (lsa)
+	    {
+	      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+		zlog_warn ("ospf_lsa_unique_id(): "
+			   "Can't get Link State ID for %s/%d",
+			   inet_ntoa (p->prefix), p->prefixlen);
+	      /* 	      id.s_addr = 0; */
+	      id.s_addr = 0xffffffff;
+	      return id;
+	    }
+	}
+    }
+
+  return id;
+}
+
+
+#define LSA_ACTION_ORIGN_RTR  1
+#define LSA_ACTION_ORIGN_NET  2
+#define LSA_ACTION_FLOOD_AREA 3
+#define LSA_ACTION_FLOOD_AS   4
+#define LSA_ACTION_FLUSH_AREA 5
+#define LSA_ACTION_FLUSH_AS   6
+
+struct lsa_action
+{
+  u_char action;
+  struct ospf_area *area;
+  struct ospf_interface *oi; 
+  struct ospf_lsa *lsa;
+};
+
+int
+ospf_lsa_action (struct thread *t)
+{
+  struct lsa_action *data;
+
+  data = THREAD_ARG (t);
+
+  if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
+    zlog_info ("LSA[Action]: Performing scheduled LSA action: %d",
+	       data->action);
+
+  switch (data->action)
+    {
+    case LSA_ACTION_ORIGN_RTR:
+      ospf_router_lsa_refresh (data->area->router_lsa_self);
+      break;
+    case LSA_ACTION_ORIGN_NET:
+      ospf_network_lsa_originate (data->oi);
+      break;
+    case LSA_ACTION_FLOOD_AREA:
+      ospf_flood_through_area (data->area, NULL, data->lsa);
+      break;
+    case LSA_ACTION_FLOOD_AS:
+      ospf_flood_through_as (NULL, data->lsa);
+      break;
+    case LSA_ACTION_FLUSH_AREA:
+      ospf_lsa_flush_area (data->lsa, data->area);
+      break;
+    case LSA_ACTION_FLUSH_AS:
+      ospf_lsa_flush_as (data->lsa);
+      break;
+    }
+
+  ospf_lsa_unlock (data->lsa);
+  XFREE (MTYPE_OSPF_MESSAGE, data);
+  return 0;
+}
+
+void
+ospf_schedule_lsa_flood_area (struct ospf_area *area, struct ospf_lsa *lsa)
+{
+  struct lsa_action *data;
+
+  data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
+  memset (data, 0, sizeof (struct lsa_action));
+
+  data->action = LSA_ACTION_FLOOD_AREA;
+  data->area = area;
+  data->lsa  = ospf_lsa_lock (lsa);
+
+  thread_add_event (master, ospf_lsa_action, data, 0);
+}
+
+void
+ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa)
+{
+  struct lsa_action *data;
+
+  data = XMALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
+  memset (data, 0, sizeof (struct lsa_action));
+
+  data->action = LSA_ACTION_FLUSH_AREA;
+  data->area = area;
+  data->lsa  = ospf_lsa_lock (lsa);
+
+  thread_add_event (master, ospf_lsa_action, data, 0);
+}
+
+
+/* LSA Refreshment functions. */
+void
+ospf_lsa_refresh (struct ospf_lsa *lsa)
+{
+  struct external_info *ei;
+  assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
+
+  switch (lsa->data->type)
+    {
+      /* Router and Network LSAs are processed differently. */
+    case OSPF_ROUTER_LSA:
+    case OSPF_NETWORK_LSA: 
+      break;
+    case OSPF_SUMMARY_LSA:
+      ospf_summary_lsa_refresh (lsa);
+      break;
+    case OSPF_ASBR_SUMMARY_LSA:
+      ospf_summary_asbr_lsa_refresh (lsa);
+      break;
+    case OSPF_AS_EXTERNAL_LSA:
+      ei = ospf_external_info_check (lsa);
+      if (ei)
+	ospf_external_lsa_refresh (lsa, ei, LSA_REFRESH_FORCE);
+      else
+	ospf_lsa_flush_as (lsa);
+      break;
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+    case OSPF_OPAQUE_AS_LSA:
+      ospf_opaque_lsa_refresh (lsa);
+      break;
+    default:
+      break;
+#endif /* HAVE_OPAQUE_LSA */
+    }
+}
+
+void
+ospf_refresher_register_lsa (struct ospf *top, struct ospf_lsa *lsa)
+{
+  u_int16_t index, current_index;
+  
+  assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
+
+  if (lsa->refresh_list < 0)
+    {
+      int delay;
+
+      if (LS_AGE (lsa) == 0 &&
+	  ntohl (lsa->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER)
+	/* Randomize first update by  OSPF_LS_REFRESH_SHIFT factor */ 
+	delay = OSPF_LS_REFRESH_SHIFT + (random () % OSPF_LS_REFRESH_TIME);
+      else
+	/* Randomize another updates by +-OSPF_LS_REFRESH_JITTER factor */
+	delay = OSPF_LS_REFRESH_TIME - LS_AGE (lsa) - OSPF_LS_REFRESH_JITTER
+	  + (random () % (2*OSPF_LS_REFRESH_JITTER)); 
+
+      if (delay < 0)
+	delay = 0;
+
+      current_index = top->lsa_refresh_queue.index +
+	(time (NULL) - top->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
+      
+      index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY)
+	% (OSPF_LSA_REFRESHER_SLOTS);
+
+      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+	zlog_info ("LSA[Refresh]: lsa with age %d added to index %d",
+		   LS_AGE (lsa), index);
+      if (!top->lsa_refresh_queue.qs[index])
+	top->lsa_refresh_queue.qs[index] = list_new ();
+      listnode_add (top->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa));
+      lsa->refresh_list = index;
+    }
+}
+
+void
+ospf_refresher_unregister_lsa (struct ospf *top, struct ospf_lsa *lsa)
+{
+  assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
+  if (lsa->refresh_list >= 0)
+    {
+      list refresh_list = top->lsa_refresh_queue.qs[lsa->refresh_list];
+      listnode_delete (refresh_list, lsa);
+      if (!listcount (refresh_list))
+	{
+	  list_free (refresh_list);
+	  top->lsa_refresh_queue.qs[lsa->refresh_list] = NULL;
+	}
+      ospf_lsa_unlock (lsa);
+      lsa->refresh_list = -1;
+    }
+}
+
+int
+ospf_lsa_refresh_walker (struct thread *t)
+{
+  list refresh_list;
+  listnode node;
+  struct ospf *top = THREAD_ARG (t);
+  int i;
+  list lsa_to_refresh = list_new ();
+
+  if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+    zlog_info ("LSA[Refresh]:ospf_lsa_refresh_walker(): start");
+
+  
+  i = top->lsa_refresh_queue.index;
+  
+  top->lsa_refresh_queue.index =
+    (top->lsa_refresh_queue.index +
+     (time (NULL) - top->lsa_refresher_started) / OSPF_LSA_REFRESHER_GRANULARITY)
+    % OSPF_LSA_REFRESHER_SLOTS;
+
+  if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+    zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d",
+	       top->lsa_refresh_queue.index);
+
+  for (;i != top->lsa_refresh_queue.index;
+       i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS)
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+	zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh index %d", i);
+
+      refresh_list = top->lsa_refresh_queue.qs [i];
+      
+      top->lsa_refresh_queue.qs [i] = NULL;
+      
+      if (refresh_list)
+	{
+	  for (node = listhead (refresh_list); node;)
+	    {
+	      listnode next;
+	      struct ospf_lsa *lsa = getdata (node);
+	      next = node->next;
+	      
+	      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+		zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p", lsa);
+	      
+	      list_delete_node (refresh_list, node);
+	      ospf_lsa_unlock (lsa);
+	      lsa->refresh_list = -1;
+	      listnode_add (lsa_to_refresh, lsa);
+	      node = next;
+	    }
+	  list_free (refresh_list);
+	}
+    }
+
+  top->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
+					   top, top->lsa_refresh_interval);
+  top->lsa_refresher_started = time (NULL);
+
+  for (node = listhead (lsa_to_refresh); node; nextnode (node))
+    ospf_lsa_refresh (getdata (node));
+  
+  list_delete (lsa_to_refresh);
+  
+  if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
+    zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): end");
+  
+  return 0;
+}
+
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
new file mode 100644
index 0000000..02fbe70
--- /dev/null
+++ b/ospfd/ospf_lsa.h
@@ -0,0 +1,326 @@
+/*
+ * OSPF Link State Advertisement
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_LSA_H
+#define _ZEBRA_OSPF_LSA_H
+
+/* OSPF LSA Range definition. */
+#define OSPF_MIN_LSA		1  /* begin range here */
+#if defined (HAVE_OPAQUE_LSA)
+#define OSPF_MAX_LSA           12
+#elif defined (HAVE_NSSA)
+#define OSPF_MAX_LSA		8
+#else
+#define OSPF_MAX_LSA		6
+#endif
+
+/* OSPF LSA Type definition. */
+#define OSPF_UNKNOWN_LSA	      0
+#define OSPF_ROUTER_LSA               1
+#define OSPF_NETWORK_LSA              2
+#define OSPF_SUMMARY_LSA              3
+#define OSPF_ASBR_SUMMARY_LSA         4
+#define OSPF_AS_EXTERNAL_LSA          5
+#define OSPF_GROUP_MEMBER_LSA	      6  /* Not supported. */
+#define OSPF_AS_NSSA_LSA	              7
+#define OSPF_EXTERNAL_ATTRIBUTES_LSA  8  /* Not supported. */
+#define OSPF_OPAQUE_LINK_LSA	      9
+#define OSPF_OPAQUE_AREA_LSA	     10
+#define OSPF_OPAQUE_AS_LSA	     11
+
+#define OSPF_LSA_HEADER_SIZE	20
+#define OSPF_MAX_LSA_SIZE	1500
+
+/* AS-external-LSA refresh method. */
+#define LSA_REFRESH_IF_CHANGED	0
+#define LSA_REFRESH_FORCE	1
+
+/* OSPF LSA header. */
+struct lsa_header
+{
+  u_int16_t ls_age;
+  u_char options;
+  u_char type;
+  struct in_addr id;
+  struct in_addr adv_router;
+  int ls_seqnum;
+  u_int16_t checksum;
+  u_int16_t length;
+};
+
+/* OSPF LSA. */
+struct ospf_lsa
+{
+  /* LSA origination flag. */
+  u_char flags;
+#define OSPF_LSA_SELF		  0x01
+#define OSPF_LSA_SELF_CHECKED	  0x02
+#define OSPF_LSA_RECEIVED	  0x04
+#define OSPF_LSA_APPROVED	  0x08
+#define OSPF_LSA_DISCARD	  0x10
+#ifdef HAVE_NSSA
+#define OSPF_LSA_LOCAL_XLT	  0x20
+#endif /* HAVE_NSSA */
+
+  /* LSA data. */
+  struct lsa_header *data;
+
+  /* Received time stamp. */
+  struct timeval tv_recv;
+
+  /* Last time it was originated */
+  struct timeval tv_orig;
+
+  /* All of reference count, also lock to remove. */
+  int lock;
+
+  /* References to this LSA in neighbor retransmission lists*/
+  int retransmit_counter;
+
+  /* Area the LSA belongs to, may be NULL if AS-external-LSA. */
+  struct ospf_area *area;
+
+  /* Parent LSDB. */
+  struct ospf_lsdb *lsdb;
+
+  /* Related Route. */
+  void *route;
+
+  /* Refreshement List or Queue */
+  int refresh_list;
+
+#ifdef HAVE_OPAQUE_LSA
+  /* For Type-9 Opaque-LSAs, reference to ospf-interface is required. */
+  struct ospf_interface *oi;
+#endif /* HAVE_OPAQUE_LSA */
+};
+
+/* OSPF LSA Link Type. */
+#define LSA_LINK_TYPE_POINTOPOINT      1
+#define LSA_LINK_TYPE_TRANSIT          2
+#define LSA_LINK_TYPE_STUB             3
+#define LSA_LINK_TYPE_VIRTUALLINK      4
+
+/* OSPF Router LSA Flag. */
+#define ROUTER_LSA_BORDER	       0x01 /* The router is an ABR */
+#define ROUTER_LSA_EXTERNAL	       0x02 /* The router is an ASBR */
+#define ROUTER_LSA_VIRTUAL	       0x04 /* The router has a VL in this area */
+#define ROUTER_LSA_NT		       0x10 /* NSSA-specific flag */
+#define ROUTER_LSA_SHORTCUT	       0x20 /* Shortcut-ABR specific flag */
+
+#define IS_ROUTER_LSA_VIRTUAL(x)       ((x)->flags & ROUTER_LSA_VIRTUAL)
+#define IS_ROUTER_LSA_EXTERNAL(x)      ((x)->flags & ROUTER_LSA_EXTERNAL)
+#define IS_ROUTER_LSA_BORDER(x)	       ((x)->flags & ROUTER_LSA_BORDER)
+#define IS_ROUTER_LSA_SHORTCUT(x)      ((x)->flags & ROUTER_LSA_SHORTCUT)
+
+/* OSPF Router-LSA Link information. */
+struct router_lsa_link
+{
+  struct in_addr link_id;
+  struct in_addr link_data;
+  struct
+  {
+    u_char type;
+    u_char tos_count;
+    u_int16_t metric;
+  } m[1];
+};
+
+/* OSPF Router-LSAs structure. */
+struct router_lsa
+{
+  struct lsa_header header;
+  u_char flags;
+  u_char zero;
+  u_int16_t links;
+  struct
+  {
+    struct in_addr link_id;
+    struct in_addr link_data;
+    u_char type;
+    u_char tos;
+    u_int16_t metric;
+  } link[1];
+};
+
+/* OSPF Network-LSAs structure. */
+struct network_lsa
+{
+  struct lsa_header header;
+  struct in_addr mask;
+  struct in_addr routers[1];
+};
+
+/* OSPF Summary-LSAs structure. */
+struct summary_lsa
+{
+  struct lsa_header header;
+  struct in_addr mask;
+  u_char tos;
+  u_char metric[3];
+};
+
+/* OSPF AS-external-LSAs structure. */
+struct as_external_lsa
+{
+  struct lsa_header header;
+  struct in_addr mask;
+  struct
+  {
+    u_char tos;
+    u_char metric[3];
+    struct in_addr fwd_addr;
+    u_int32_t route_tag;
+  } e[1];
+};
+
+#ifdef HAVE_OPAQUE_LSA
+#include "ospfd/ospf_opaque.h"
+#endif /* HAVE_OPAQUE_LSA */
+
+/* Macros. */
+#define GET_METRIC(x) get_metric(x)
+#define IS_EXTERNAL_METRIC(x)   ((x) & 0x80)
+
+#define GET_AGE(x)     (ntohs ((x)->data->ls_age) + time (NULL) - (x)->tv_recv)
+#define LS_AGE(x)      (OSPF_LSA_MAXAGE < get_age(x) ? \
+                                           OSPF_LSA_MAXAGE : get_age(x))
+#define IS_LSA_SELF(L)          (CHECK_FLAG ((L)->flags, OSPF_LSA_SELF))
+#define IS_LSA_MAXAGE(L)        (LS_AGE ((L)) == OSPF_LSA_MAXAGE)
+
+#define OSPF_SUMMARY_LSA_SELF_FIND_BY_PREFIX(A,P) \
+        foreach_lsa (SUMMARY_LSDB ((A)), \
+                     (struct prefix_ipv4 *) (P), 0, find_summary)
+
+#define OSPF_SUMMARY_ASBR_LSA_SELF_FIND_BY_PREFIX(A,P) \
+        foreach_lsa (ASBR_SUMMARY_LSDB ((A)), \
+                     (struct prefix_ipv4 *) (P), 0, find_asbr_summary)
+
+#define OSPF_LSA_UPDATE_DELAY		2
+
+#define OSPF_LSA_UPDATE_TIMER_ON(T,F) \
+      if (!(T)) \
+        (T) = thread_add_timer (master, (F), 0, 2)
+
+struct ospf_route;
+struct ospf_lsdb;
+
+/* Prototypes. */
+struct timeval tv_adjust (struct timeval);
+int tv_ceil (struct timeval);
+int tv_floor (struct timeval);
+struct timeval int2tv (int);
+struct timeval tv_add (struct timeval, struct timeval);
+struct timeval tv_sub (struct timeval, struct timeval);
+int tv_cmp (struct timeval, struct timeval);
+
+int get_age (struct ospf_lsa *);
+u_int16_t ospf_lsa_checksum (struct lsa_header *);
+
+struct stream;
+const char *dump_lsa_key (struct ospf_lsa *lsa);
+u_int32_t lsa_seqnum_increment (struct ospf_lsa *lsa);
+void lsa_header_set (struct stream *s, u_char options, u_char type, struct in_addr id);
+struct ospf_neighbor *ospf_nbr_lookup_ptop (struct route_table *nbrs, struct in_addr router_id);
+
+/* Prototype for LSA primitive. */
+struct ospf_lsa *ospf_lsa_new ();
+struct ospf_lsa *ospf_lsa_dup ();
+void ospf_lsa_free (struct ospf_lsa *lsa);
+struct ospf_lsa *ospf_lsa_lock (struct ospf_lsa *);
+void ospf_lsa_unlock (struct ospf_lsa *);
+void ospf_lsa_discard (struct ospf_lsa *);
+
+struct lsa_header *ospf_lsa_data_new (size_t);
+struct lsa_header *ospf_lsa_data_dup (struct lsa_header *);
+void ospf_lsa_data_free (struct lsa_header *);
+
+/* Prototype for various LSAs */
+struct ospf_lsa *ospf_router_lsa_originate (struct ospf_area *);
+int ospf_router_lsa_update_timer (struct thread *);
+void ospf_router_lsa_timer_add (struct ospf_area *);
+
+int ospf_network_lsa_refresh (struct ospf_lsa *, struct ospf_interface *);
+void ospf_network_lsa_timer_add (struct ospf_interface *);
+
+struct ospf_lsa *ospf_summary_lsa_originate (struct prefix_ipv4 *, u_int32_t,
+					     struct ospf_area *);
+struct ospf_lsa *ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *,
+						  u_int32_t,
+						  struct ospf_area *);
+struct ospf_lsa *ospf_summary_lsa_refresh (struct ospf_lsa *);
+struct ospf_lsa *ospf_summary_asbr_lsa_refresh (struct ospf_lsa *);
+
+struct ospf_lsa *ospf_lsa_install (struct ospf_interface *, struct ospf_lsa *);
+
+void ospf_external_lsa_flush (u_char, struct prefix_ipv4 *,
+			      unsigned int, struct in_addr);
+
+struct in_addr ospf_get_ip_from_ifp (struct ospf_interface *oi);
+
+struct ospf_lsa *ospf_external_lsa_originate (struct external_info *);
+int ospf_external_lsa_originate_timer (struct thread *);
+struct ospf_lsa *ospf_lsa_lookup (struct ospf_area *, u_int32_t,
+				  struct in_addr, struct in_addr);
+struct ospf_lsa *ospf_lsa_lookup_by_id (struct ospf_area *,u_int32_t, struct in_addr);
+struct ospf_lsa *ospf_lsa_lookup_by_header (struct ospf_area *,
+					    struct lsa_header *);
+int ospf_lsa_more_recent (struct ospf_lsa *, struct ospf_lsa *);
+int ospf_lsa_different (struct ospf_lsa *, struct ospf_lsa *);
+void ospf_flush_self_originated_lsas_now (struct ospf *top);
+
+int ospf_lsa_is_self_originated (struct ospf_lsa *);
+
+int find_summary (struct ospf_lsa *, void *, int);
+int find_asbr_summary (struct ospf_lsa *, void *, int);
+
+void ospf_lsa_maxage (struct ospf_lsa *);
+u_int32_t get_metric (u_char *);
+
+int ospf_lsa_maxage_walker (struct thread *);
+
+void ospf_external_lsa_refresh_default (void);
+
+void ospf_external_lsa_refresh_type (u_char, int);
+void ospf_external_lsa_refresh (struct ospf_lsa *, struct external_info *ei,
+				int force);
+struct in_addr ospf_lsa_unique_id (struct ospf_lsdb *, u_char,
+				   struct prefix_ipv4 *);
+void ospf_schedule_lsa_flood_area (struct ospf_area *, struct ospf_lsa *);
+void ospf_schedule_lsa_flush_area (struct ospf_area *, struct ospf_lsa *);
+
+void ospf_refresher_register_lsa (struct ospf *, struct ospf_lsa *);
+void ospf_refresher_unregister_lsa (struct ospf *, struct ospf_lsa *);
+int ospf_lsa_refresh_walker (struct thread *);
+
+void ospf_lsa_init ();
+
+void ospf_lsa_maxage_delete (struct ospf_lsa *);
+
+void ospf_discard_from_db (struct ospf_lsdb *, struct ospf_lsa*);
+int ospf_lsa_discard_callback (struct ospf_lsa *, void *, int);
+int is_prefix_default (struct prefix_ipv4 *);
+
+int metric_type (u_char);
+int metric_value (u_char);
+
+#endif /* _ZEBRA_OSPF_LSA_H */
diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c
new file mode 100644
index 0000000..46d8d70
--- /dev/null
+++ b/ospfd/ospf_lsdb.c
@@ -0,0 +1,299 @@
+/*
+ * OSPF LSDB support.
+ * Copyright (C) 1999, 2000 Alex Zinin, Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "table.h"
+#include "memory.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+
+struct ospf_lsdb *
+ospf_lsdb_new ()
+{
+  struct ospf_lsdb *new;
+
+  new = XCALLOC (MTYPE_OSPF_LSDB, sizeof (struct ospf_lsdb));
+  ospf_lsdb_init (new);
+
+  return new;
+}
+
+void
+ospf_lsdb_init (struct ospf_lsdb *lsdb)
+{
+  int i;
+  
+  for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+    lsdb->type[i].db = route_table_init ();
+}
+
+void
+ospf_lsdb_free (struct ospf_lsdb *lsdb)
+{
+  ospf_lsdb_cleanup (lsdb);
+  XFREE (MTYPE_OSPF_LSDB, lsdb);
+}
+
+void
+ospf_lsdb_cleanup (struct ospf_lsdb *lsdb)
+{
+  int i;
+  assert (lsdb);
+  assert (lsdb->total == 0);
+
+  ospf_lsdb_delete_all (lsdb);
+  
+  for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+    route_table_finish (lsdb->type[i].db);
+}
+
+void
+lsdb_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa)
+{
+  memset (lp, 0, sizeof (struct prefix_ls));
+  lp->family = 0;
+  lp->prefixlen = 64;
+  lp->id = lsa->data->id;
+  lp->adv_router = lsa->data->adv_router;
+}
+
+/* Add new LSA to lsdb. */
+void
+ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
+{
+  struct route_table *table;
+  struct prefix_ls lp;
+  struct route_node *rn;
+
+  table = lsdb->type[lsa->data->type].db;
+  lsdb_prefix_set (&lp, lsa);
+  rn = route_node_get (table, (struct prefix *)&lp);
+  if (!rn->info)
+    {
+      if (IS_LSA_SELF (lsa))
+	lsdb->type[lsa->data->type].count_self++;
+      lsdb->type[lsa->data->type].count++;
+      lsdb->total++;
+    }
+  else
+    {
+      if (rn->info == lsa)
+	return;
+      
+      ospf_lsa_unlock (rn->info);
+      route_unlock_node (rn);
+    }
+
+#ifdef MONITOR_LSDB_CHANGE
+  if (lsdb->new_lsa_hook != NULL)
+    (* lsdb->new_lsa_hook)(lsa);
+#endif /* MONITOR_LSDB_CHANGE */
+  rn->info = ospf_lsa_lock (lsa);
+}
+
+void
+ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
+{
+  struct route_table *table;
+  struct prefix_ls lp;
+  struct route_node *rn;
+
+  table = lsdb->type[lsa->data->type].db;
+  lsdb_prefix_set (&lp, lsa);
+  rn = route_node_lookup (table, (struct prefix *) &lp);
+  if (rn)
+    if (rn->info == lsa)
+      {
+	if (IS_LSA_SELF (lsa))
+	  lsdb->type[lsa->data->type].count_self--;
+	lsdb->type[lsa->data->type].count--;
+	lsdb->total--;
+	rn->info = NULL;
+	route_unlock_node (rn);
+	route_unlock_node (rn);
+#ifdef MONITOR_LSDB_CHANGE
+        if (lsdb->del_lsa_hook != NULL)
+          (* lsdb->del_lsa_hook)(lsa);
+#endif /* MONITOR_LSDB_CHANGE */
+	ospf_lsa_unlock (lsa);
+	return;
+      }
+}
+
+void
+ospf_lsdb_delete_all (struct ospf_lsdb *lsdb)
+{
+  struct route_table *table;
+  struct route_node *rn;
+  struct ospf_lsa *lsa;
+  int i;
+
+  for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+    {
+      table = lsdb->type[i].db;
+      for (rn = route_top (table); rn; rn = route_next (rn))
+	if ((lsa = (rn->info)) != NULL)
+	  {
+	    if (IS_LSA_SELF (lsa))
+	      lsdb->type[i].count_self--;
+	    lsdb->type[i].count--;
+	    lsdb->total--;
+	    rn->info = NULL;
+	    route_unlock_node (rn);
+#ifdef MONITOR_LSDB_CHANGE
+            if (lsdb->del_lsa_hook != NULL)
+              (* lsdb->del_lsa_hook)(lsa);
+#endif /* MONITOR_LSDB_CHANGE */
+	    ospf_lsa_unlock (lsa);
+	  }
+    }
+}
+
+struct ospf_lsa *
+ospf_lsdb_lookup (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
+{
+  struct route_table *table;
+  struct prefix_ls lp;
+  struct route_node *rn;
+  struct ospf_lsa *find;
+
+  table = lsdb->type[lsa->data->type].db;
+  lsdb_prefix_set (&lp, lsa);
+  rn = route_node_lookup (table, (struct prefix *) &lp);
+  if (rn)
+    {
+      find = rn->info;
+      route_unlock_node (rn);
+      return find;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+ospf_lsdb_lookup_by_id (struct ospf_lsdb *lsdb, u_char type,
+		       struct in_addr id, struct in_addr adv_router)
+{
+  struct route_table *table;
+  struct prefix_ls lp;
+  struct route_node *rn;
+  struct ospf_lsa *find;
+
+  table = lsdb->type[type].db;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = id;
+  lp.adv_router = adv_router;
+
+  rn = route_node_lookup (table, (struct prefix *) &lp);
+  if (rn)
+    {
+      find = rn->info;
+      route_unlock_node (rn);
+      return find;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *lsdb, u_char type,
+			    struct in_addr id, struct in_addr adv_router,
+			    int first)
+{
+  struct route_table *table;
+  struct prefix_ls lp;
+  struct route_node *rn;
+  struct ospf_lsa *find;
+
+  table = lsdb->type[type].db;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = id;
+  lp.adv_router = adv_router;
+
+  if (first)
+      rn = route_top (table);
+  else
+    {
+      rn = route_node_get (table, (struct prefix *) &lp);
+      rn = route_next (rn);
+    }
+
+  for (; rn; rn = route_next (rn))
+    if (rn->info)
+      break;
+
+  if (rn && rn->info)
+    {
+      find = rn->info;
+      route_unlock_node (rn);
+      return find;
+    }
+  return NULL;
+}
+
+unsigned long
+ospf_lsdb_count_all (struct ospf_lsdb *lsdb)
+{
+  return lsdb->total;
+}
+
+unsigned long
+ospf_lsdb_count (struct ospf_lsdb *lsdb, int type)
+{
+  return lsdb->type[type].count;
+}
+
+unsigned long
+ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type)
+{
+  return lsdb->type[type].count_self;
+}
+
+unsigned long
+ospf_lsdb_isempty (struct ospf_lsdb *lsdb)
+{
+  return (lsdb->total == 0);
+}
+
+struct ospf_lsa *
+foreach_lsa (struct route_table *table, void *p_arg, int int_arg, 
+	     int (*callback) (struct ospf_lsa *, void *, int))
+{
+  struct route_node *rn;
+  struct ospf_lsa *lsa;
+
+  for (rn = route_top (table); rn; rn = route_next (rn))
+    if ((lsa = rn->info) != NULL)
+      if (callback (lsa, p_arg, int_arg))
+	return lsa;
+
+  return NULL;
+}
diff --git a/ospfd/ospf_lsdb.h b/ospfd/ospf_lsdb.h
new file mode 100644
index 0000000..34344b3
--- /dev/null
+++ b/ospfd/ospf_lsdb.h
@@ -0,0 +1,83 @@
+/*
+ * OSPF LSDB support.
+ * Copyright (C) 1999, 2000 Alex Zinin, Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_LSDB_H
+#define _ZEBRA_OSPF_LSDB_H
+
+/* OSPF LSDB structure. */
+struct ospf_lsdb
+{
+  struct
+  {
+    unsigned long count;
+    unsigned long count_self;
+    struct route_table *db;
+  } type[OSPF_MAX_LSA];
+  unsigned long total;
+#define MONITOR_LSDB_CHANGE 1 /* XXX */
+#ifdef MONITOR_LSDB_CHANGE
+  /* Hooks for callback functions to catch every add/del event. */
+  int (* new_lsa_hook)(struct ospf_lsa *);
+  int (* del_lsa_hook)(struct ospf_lsa *);
+#endif /* MONITOR_LSDB_CHANGE */
+};
+
+/* Macros. */
+#define LSDB_LOOP(T,N,L) \
+  for ((N) = route_top ((T)); ((N)); ((N)) = route_next ((N))) \
+    if (((L) = (N)->info))
+
+#define ROUTER_LSDB(A)       ((A)->lsdb->type[OSPF_ROUTER_LSA].db)
+#define NETWORK_LSDB(A)	     ((A)->lsdb->type[OSPF_NETWORK_LSA].db)
+#define SUMMARY_LSDB(A)      ((A)->lsdb->type[OSPF_SUMMARY_LSA].db)
+#define ASBR_SUMMARY_LSDB(A) ((A)->lsdb->type[OSPF_ASBR_SUMMARY_LSA].db)
+#define EXTERNAL_LSDB(O)     ((O)->lsdb->type[OSPF_AS_EXTERNAL_LSA].db)
+#define NSSA_LSDB(A)         ((A)->lsdb->type[OSPF_AS_NSSA_LSA].db)
+#define OPAQUE_LINK_LSDB(A)  ((A)->lsdb->type[OSPF_OPAQUE_LINK_LSA].db)
+#define OPAQUE_AREA_LSDB(A)  ((A)->lsdb->type[OSPF_OPAQUE_AREA_LSA].db)
+#define OPAQUE_AS_LSDB(O)    ((O)->lsdb->type[OSPF_OPAQUE_AS_LSA].db)
+
+#define AREA_LSDB(A,T)       ((A)->lsdb->type[(T)].db)
+#define AS_LSDB(O,T)         ((O)->lsdb->type[(T)].db)
+
+/* OSPF LSDB related functions. */
+struct ospf_lsdb *ospf_lsdb_new ();
+void ospf_lsdb_init (struct ospf_lsdb *);
+void ospf_lsdb_free (struct ospf_lsdb *);
+void ospf_lsdb_cleanup (struct ospf_lsdb *);
+void ospf_lsdb_add (struct ospf_lsdb *, struct ospf_lsa *);
+void ospf_lsdb_delete (struct ospf_lsdb *, struct ospf_lsa *);
+void ospf_lsdb_delete_all (struct ospf_lsdb *);
+struct ospf_lsa *ospf_lsdb_lookup (struct ospf_lsdb *, struct ospf_lsa *);
+struct ospf_lsa *ospf_lsdb_lookup_by_id (struct ospf_lsdb *, u_char,
+					struct in_addr, struct in_addr);
+struct ospf_lsa *ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *, u_char,
+					     struct in_addr, struct in_addr,
+					     int);
+unsigned long ospf_lsdb_count_all (struct ospf_lsdb *);
+unsigned long ospf_lsdb_count (struct ospf_lsdb *, int);
+unsigned long ospf_lsdb_count_self (struct ospf_lsdb *, int);
+unsigned long ospf_lsdb_isempty (struct ospf_lsdb *);
+struct ospf_lsa *foreach_lsa (struct route_table *, void *, int,
+	              int (*callback) (struct ospf_lsa *, void *, int));
+
+#endif /* _ZEBRA_OSPF_LSDB_H */
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
new file mode 100644
index 0000000..82960b2
--- /dev/null
+++ b/ospfd/ospf_main.c
@@ -0,0 +1,293 @@
+/*
+ * OSPFd main routine.
+ *   Copyright (C) 1998, 99 Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "version.h"
+#include "getopt.h"
+#include "thread.h"
+#include "prefix.h"
+#include "linklist.h"
+#include "if.h"
+#include "vector.h"
+#include "vty.h"
+#include "command.h"
+#include "filter.h"
+#include "plist.h"
+#include "stream.h"
+#include "log.h"
+#include "memory.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_vty.h"
+
+/* Configuration filename and directory. */
+char config_current[] = OSPF_DEFAULT_CONFIG;
+char config_default[] = SYSCONFDIR OSPF_DEFAULT_CONFIG;
+
+/* OSPFd options. */
+struct option longopts[] = 
+{
+  { "daemon",      no_argument,       NULL, 'd'},
+  { "config_file", required_argument, NULL, 'f'},
+  { "pid_file",    required_argument, NULL, 'i'},
+  { "log_mode",    no_argument,       NULL, 'l'},
+  { "help",        no_argument,       NULL, 'h'},
+  { "vty_addr",    required_argument, NULL, 'A'},
+  { "vty_port",    required_argument, NULL, 'P'},
+  { "version",     no_argument,       NULL, 'v'},
+  { 0 }
+};
+
+/* OSPFd program name */
+
+/* Master of threads. */
+struct thread_master *master;
+
+/* Process ID saved for use by init system */
+char *pid_file = PATH_OSPFD_PID;
+
+/* Help information display. */
+static void
+usage (char *progname, int status)
+{
+  if (status != 0)
+    fprintf (stderr, "Try `%s --help' for more information.\n", progname);
+  else
+    {    
+      printf ("Usage : %s [OPTION...]\n\
+Daemon which manages OSPF.\n\n\
+-d, --daemon       Runs in daemon mode\n\
+-f, --config_file  Set configuration file name\n\
+-i, --pid_file     Set process identifier file name\n\
+-A, --vty_addr     Set vty's bind address\n\
+-P, --vty_port     Set vty's port number\n\
+-v, --version      Print program version\n\
+-h, --help         Display this help and exit\n\
+\n\
+Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+    }
+  exit (status);
+}
+
+/* SIGHUP handler. */
+void 
+sighup (int sig)
+{
+  zlog (NULL, LOG_INFO, "SIGHUP received");
+}
+
+/* SIGINT handler. */
+void
+sigint (int sig)
+{
+  zlog (NULL, LOG_INFO, "Terminating on signal");
+
+  ospf_terminate ();
+
+  exit (0);
+}
+
+/* SIGUSR1 handler. */
+void
+sigusr1 (int sig)
+{
+  zlog_rotate (NULL);
+}
+
+/* Signal wrapper. */
+RETSIGTYPE *
+signal_set (int signo, void (*func)(int))
+{
+  int ret;
+  struct sigaction sig;
+  struct sigaction osig;
+
+  sig.sa_handler = func;
+  sigemptyset (&sig.sa_mask);
+  sig.sa_flags = 0;
+#ifdef SA_RESTART
+  sig.sa_flags |= SA_RESTART;
+#endif /* SA_RESTART */
+
+  ret = sigaction (signo, &sig, &osig);
+
+  if (ret < 0) 
+    return (SIG_ERR);
+  else
+    return (osig.sa_handler);
+}
+
+/* Initialization of signal handles. */
+void
+signal_init ()
+{
+  signal_set (SIGHUP, sighup);
+  signal_set (SIGINT, sigint);
+  signal_set (SIGTERM, sigint);
+  signal_set (SIGPIPE, SIG_IGN);
+#ifdef SIGTSTP
+  signal_set (SIGTSTP, SIG_IGN);
+#endif
+#ifdef SIGTTIN
+  signal_set (SIGTTIN, SIG_IGN);
+#endif
+#ifdef SIGTTOU
+  signal_set (SIGTTOU, SIG_IGN);
+#endif
+  signal_set (SIGUSR1, sigusr1);
+}
+
+/* OSPFd main routine. */
+int
+main (int argc, char **argv)
+{
+  char *p;
+  char *vty_addr = NULL;
+  int vty_port = 0;
+  int daemon_mode = 0;
+  char *config_file = NULL;
+  char *progname;
+  struct thread thread;
+
+  /* Set umask before anything for security */
+  umask (0027);
+
+  /* get program name */
+  progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
+
+  /* Invoked by a priviledged user? -- endo. */
+  if (getuid () != 0)
+    {
+      errno = EPERM;
+      perror (progname);
+      exit (1);
+    }
+
+  zlog_default = openzlog (progname, ZLOG_NOLOG, ZLOG_OSPF,
+			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+
+  while (1) 
+    {
+      int opt;
+
+      opt = getopt_long (argc, argv, "dlf:hA:P:v", longopts, 0);
+    
+      if (opt == EOF)
+	break;
+
+      switch (opt) 
+	{
+	case 0:
+	  break;
+	case 'd':
+	  daemon_mode = 1;
+	  break;
+	case 'f':
+	  config_file = optarg;
+	  break;
+	case 'A':
+	  vty_addr = optarg;
+	  break;
+        case 'i':
+          pid_file = optarg;
+          break;
+	case 'P':
+	  vty_port = atoi (optarg);
+	  break;
+	case 'v':
+	  print_version (progname);
+	  exit (0);
+	  break;
+	case 'h':
+	  usage (progname, 0);
+	  break;
+	default:
+	  usage (progname, 1);
+	  break;
+	}
+    }
+
+  /* Initializations. */
+  master = thread_master_create ();
+
+  /* Library inits. */
+  signal_init ();
+  cmd_init (1);
+  debug_init ();
+  vty_init ();
+  memory_init ();
+
+  access_list_init ();
+  prefix_list_init ();
+
+  /* OSPFd inits. */
+  ospf_init ();
+  ospf_if_init ();
+  ospf_zebra_init ();
+
+  /* OSPF vty inits. */
+  ospf_vty_init ();
+  ospf_vty_show_init ();
+
+  ospf_route_map_init ();
+#ifdef HAVE_SNMP
+  ospf_snmp_init ();
+#endif /* HAVE_SNMP */
+#ifdef HAVE_OPAQUE_LSA
+  ospf_opaque_init ();
+#endif /* HAVE_OPAQUE_LSA */
+  
+  sort_node ();
+
+  /* Get configuration file. */
+  vty_read_config (config_file, config_current, config_default);
+
+  /* Change to the daemon program. */
+  if (daemon_mode)
+    daemon (0, 0);
+
+  /* Process id file create. */
+  pid_output (pid_file);
+
+  /* Create VTY socket */
+  vty_serv_sock (vty_addr,
+		 vty_port ? vty_port : OSPF_VTY_PORT, OSPF_VTYSH_PATH);
+
+  /* Print banner. */
+  zlog (NULL, LOG_INFO, "OSPFd (%s) starts", ZEBRA_VERSION);
+
+  /* Fetch next active thread. */
+  while (thread_fetch (master, &thread))
+    thread_call (&thread);
+
+  /* Not reached. */
+  exit (0);
+}
+
diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h
new file mode 100644
index 0000000..f7b1874
--- /dev/null
+++ b/ospfd/ospf_neighbor.h
@@ -0,0 +1,106 @@
+/*
+ * OSPF Neighbor functions.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ * 
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_NEIGHBOR_H
+#define _ZEBRA_OSPF_NEIGHBOR_H
+
+/* Neighbor Data Structure */
+struct ospf_neighbor
+{
+  /* This neighbor's parent ospf interface. */
+  struct ospf_interface *oi;
+
+  /* OSPF neighbor Information */
+  u_char state;				/* NSM status. */
+  u_char dd_flags;			/* DD bit flags. */
+  u_int32_t dd_seqnum;			/* DD Sequence Number. */
+
+  /* Neighbor Information from Hello. */
+  struct prefix address;		/* Neighbor Interface Address. */
+
+  struct in_addr src;			/* Src address. */
+  struct in_addr router_id;		/* Router ID. */
+  u_char options;			/* Options. */
+  int priority;				/* Router Priority. */
+  struct in_addr d_router;		/* Designated Router. */
+  struct in_addr bd_router;		/* Backup Designated Router. */
+
+  /* Last sent Database Description packet. */
+  struct ospf_packet *last_send;
+  /* Timestemp when last Database Description packet was sent */
+  struct timeval last_send_ts;
+
+  /* Last received Databse Description packet. */
+  struct
+  {
+    u_char options;
+    u_char flags;
+    u_int32_t dd_seqnum;
+  } last_recv;
+
+  /* LSA data. */
+  struct ospf_lsdb ls_rxmt;
+  struct ospf_lsdb db_sum;
+  struct ospf_lsdb ls_req;
+  struct ospf_lsa *ls_req_last;
+
+  u_int32_t crypt_seqnum;           /* Cryptographic Sequence Number. */
+
+  /* Timer values. */
+  u_int32_t v_inactivity;
+  u_int32_t v_db_desc;
+  u_int32_t v_ls_req;
+  u_int32_t v_ls_upd;
+
+  /* Threads. */
+  struct thread *t_inactivity;
+  struct thread *t_db_desc;
+  struct thread *t_ls_req;
+  struct thread *t_ls_upd;
+  struct thread *t_hello_reply;
+
+  /* Statistics Field */
+  u_int32_t state_change;
+  struct ospf_nbr_nbma *nbr_nbma;
+};
+
+/* Macros. */
+#define NBR_IS_DR(n)	IPV4_ADDR_SAME (&n->address.u.prefix4, &n->d_router)
+#define NBR_IS_BDR(n)   IPV4_ADDR_SAME (&n->address.u.prefix4, &n->bd_router)
+
+/* Prototypes. */
+struct ospf_neighbor *ospf_nbr_new (struct ospf_interface *);
+void ospf_nbr_free (struct ospf_neighbor *);
+void ospf_nbr_delete (struct ospf_neighbor *);
+int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int);
+void ospf_nbr_add_self (struct ospf_interface *);
+int ospf_nbr_count (struct route_table *, int);
+#ifdef HAVE_OPAQUE_LSA
+int ospf_opaque_capable_nbr_count (struct route_table *nbrs, int status);
+#endif /* HAVE_OPAQUE_LSA */
+struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct route_table *,
+					       struct in_addr *);
+struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct route_table *,
+						   struct in_addr *);
+void ospf_renegotiate_optional_capabilities (struct ospf *top);
+
+#endif /* _ZEBRA_OSPF_NEIGHBOR_H */
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c
new file mode 100644
index 0000000..56ec864
--- /dev/null
+++ b/ospfd/ospf_network.c
@@ -0,0 +1,192 @@
+/*
+ * OSPF network related functions
+ *   Copyright (C) 1999 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "sockunion.h"
+#include "log.h"
+#include "sockopt.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_network.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_packet.h"
+
+/* Join to the OSPF ALL SPF ROUTERS multicast group. */
+int
+ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
+			   unsigned int ifindex)
+{
+  int ret;
+  
+  ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
+                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
+                                   ifindex);
+  if (ret < 0)
+    zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (AllSPFRouters): %s",
+               strerror (errno));
+  else
+    zlog_info ("interface %s join AllSPFRouters Multicast group.",
+	       inet_ntoa (p->u.prefix4));
+
+  return ret;
+}
+
+int
+ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p,
+			    unsigned int ifindex)
+{
+  int ret;
+
+  ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
+                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
+                                   ifindex);
+  if (ret < 0)
+    zlog_warn("can't setsockopt IP_DROP_MEMBERSHIP (AllSPFRouters): %s",
+	      strerror (errno));
+  else
+    zlog_info ("interface %s leave AllSPFRouters Multicast group.",
+	       inet_ntoa (p->u.prefix4));
+
+  return ret;
+}
+
+/* Join to the OSPF ALL Designated ROUTERS multicast group. */
+int
+ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
+			 ifindex)
+{
+  int ret;
+
+  ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
+                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
+                                   ifindex);
+  if (ret < 0)
+    zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (AllDRouters): %s",
+               strerror (errno));
+  else
+    zlog_info ("interface %s join AllDRouters Multicast group.",
+	       inet_ntoa (p->u.prefix4));
+
+  return ret;
+}
+
+int
+ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int
+			  ifindex)
+{
+  int ret;
+
+  ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
+                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
+                                   ifindex);
+  if (ret < 0)
+    zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (AllDRouters): %s",
+	       strerror (errno));
+  else
+    zlog_info ("interface %s leave AllDRouters Multicast group.",
+	       inet_ntoa (p->u.prefix4));
+
+  return ret;
+}
+
+int
+ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex)
+{
+  u_char val;
+  int ret, len;
+  
+  val = 0;
+  len = sizeof (val);
+  
+  /* Prevent receiving self-origined multicast packets. */
+  ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, len);
+  if (ret < 0)
+    zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0): %s", strerror (errno));
+  
+  /* Explicitly set multicast ttl to 1 -- endo. */
+  val = 1;
+  ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);
+  if (ret < 0)
+    zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1): %s", strerror (errno));
+
+  ret = setsockopt_multicast_ipv4 (top->fd, IP_MULTICAST_IF,
+                                   p->u.prefix4, 0, ifindex);
+  if (ret < 0)
+    zlog_warn ("can't setsockopt IP_MULTICAST_IF: %s", strerror (errno));
+
+  return ret;
+}
+
+int
+ospf_sock_init (void)
+{
+  int ospf_sock;
+  int ret, tos, hincl = 1;
+
+  ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
+  if (ospf_sock < 0)
+    {
+      zlog_warn ("ospf_read_sock_init: socket: %s", strerror (errno));
+      return -1;
+    }
+
+  /* Set precedence field. */
+#ifdef IPTOS_PREC_INTERNETCONTROL
+  tos = IPTOS_PREC_INTERNETCONTROL;
+  ret = setsockopt (ospf_sock, IPPROTO_IP, IP_TOS,
+		    (char *) &tos, sizeof (int));
+  if (ret < 0)
+    {
+      zlog_warn ("can't set sockopt IP_TOS %d to socket %d", tos, ospf_sock);
+      close (ospf_sock);	/* Prevent sd leak. */
+      return ret;
+    }
+#endif /* IPTOS_PREC_INTERNETCONTROL */
+
+  /* we will include IP header with packet */
+  ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl));
+  if (ret < 0)
+    zlog_warn ("Can't set IP_HDRINCL option");
+
+#if defined (IP_PKTINFO)
+  ret = setsockopt (ospf_sock, IPPROTO_IP, IP_PKTINFO, &hincl, sizeof (hincl));
+   if (ret < 0)
+    zlog_warn ("Can't set IP_PKTINFO option");
+#elif defined (IP_RECVIF)
+  ret = setsockopt (ospf_sock, IPPROTO_IP, IP_RECVIF, &hincl, sizeof (hincl));
+   if (ret < 0)
+    zlog_warn ("Can't set IP_RECVIF option");
+#else
+#warning "cannot be able to receive link information on this OS"
+#endif
+ 
+  return ospf_sock;
+}
diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h
new file mode 100644
index 0000000..52a25fd
--- /dev/null
+++ b/ospfd/ospf_network.h
@@ -0,0 +1,34 @@
+/*
+ * OSPF network related functions.
+ *   Copyright (C) 1999 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_NETWORK_H
+#define _ZEBRA_OSPF_NETWORK_H
+
+/* Prototypes. */
+int ospf_if_add_allspfrouters (struct ospf *, struct prefix *, unsigned int);
+int ospf_if_drop_allspfrouters (struct ospf *, struct prefix *, unsigned int);
+int ospf_if_add_alldrouters (struct ospf *, struct prefix *, unsigned int);
+int ospf_if_drop_alldrouters (struct ospf *, struct prefix *, unsigned int);
+int ospf_if_ipmulticast (struct ospf *, struct prefix *, unsigned int);
+int ospf_sock_init (void);
+
+#endif /* _ZEBRA_OSPF_NETWORK_H */
diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h
new file mode 100644
index 0000000..3d25730
--- /dev/null
+++ b/ospfd/ospf_nsm.h
@@ -0,0 +1,91 @@
+/*
+ * OSPF version 2  Neighbor State Machine
+ *   From RFC2328 [OSPF Version 2]
+ *   Copyright (C) 1999 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_NSM_H
+#define _ZEBRA_OSPF_NSM_H
+
+/* OSPF Neighbor State Machine State. */
+#define NSM_DependUpon          0
+#define NSM_Down		1
+#define NSM_Attempt		2
+#define NSM_Init		3
+#define NSM_TwoWay		4
+#define NSM_ExStart		5
+#define NSM_Exchange		6
+#define NSM_Loading		7
+#define NSM_Full		8
+#define OSPF_NSM_STATE_MAX      9
+
+/* OSPF Neighbor State Machine Event. */
+#define NSM_NoEvent	        0
+#define NSM_HelloReceived	1
+#define NSM_Start		2
+#define NSM_TwoWayReceived	3
+#define NSM_NegotiationDone	4
+#define NSM_ExchangeDone	5
+#define NSM_BadLSReq		6
+#define NSM_LoadingDone		7
+#define NSM_AdjOK		8
+#define NSM_SeqNumberMismatch	9
+#define NSM_OneWayReceived     10
+#define NSM_KillNbr	       11
+#define NSM_InactivityTimer    12
+#define NSM_LLDown	       13
+#define OSPF_NSM_EVENT_MAX     14
+
+/* Macro for OSPF NSM timer turn on. */
+#define OSPF_NSM_TIMER_ON(T,F,V) \
+      do { \
+        if (!(T)) \
+          (T) = thread_add_timer (master, (F), nbr, (V)); \
+      } while (0)
+
+/* Macro for OSPF NSM timer turn off. */
+#define OSPF_NSM_TIMER_OFF(X) \
+      do { \
+        if (X) \
+          { \
+            thread_cancel (X); \
+            (X) = NULL; \
+          } \
+      } while (0)
+
+/* Macro for OSPF NSM schedule event. */
+#define OSPF_NSM_EVENT_SCHEDULE(N,E) \
+      thread_add_event (master, ospf_nsm_event, (N), (E))
+
+/* Macro for OSPF NSM execute event. */
+#define OSPF_NSM_EVENT_EXECUTE(N,E) \
+      thread_execute (master, ospf_nsm_event, (N), (E))
+
+/* Prototypes. */
+int ospf_nsm_event (struct thread *);
+void nsm_change_state (struct ospf_neighbor *, int);
+void ospf_check_nbr_loading (struct ospf_neighbor *);
+int ospf_db_summary_isempty (struct ospf_neighbor *);
+int ospf_db_summary_count (struct ospf_neighbor *);
+void ospf_db_summary_clear (struct ospf_neighbor *);
+/* void ospf_db_summary_delete_all (struct ospf_neighbor *); */
+
+#endif /* _ZEBRA_OSPF_NSM_H */
+
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
new file mode 100644
index 0000000..67c6608
--- /dev/null
+++ b/ospfd/ospf_opaque.c
@@ -0,0 +1,2392 @@
+/*
+ * This is an implementation of rfc2370.
+ * Copyright (C) 2001 KDD R&D Laboratories, Inc.
+ * http://www.kddlabs.co.jp/
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+/***** MTYPE definitions are not reflected to "memory.h" yet. *****/
+#define MTYPE_OSPF_OPAQUE_FUNCTAB	0
+#define MTYPE_OPAQUE_INFO_PER_TYPE	0
+#define MTYPE_OPAQUE_INFO_PER_ID	0
+
+#include <zebra.h>
+#ifdef HAVE_OPAQUE_LSA
+
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "memory.h"
+#include "command.h"
+#include "vty.h"
+#include "stream.h"
+#include "log.h"
+#include "thread.h"
+#include "hash.h"
+#include "sockunion.h"		/* for inet_aton() */
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ase.h"
+#include "ospfd/ospf_zebra.h"
+
+/*------------------------------------------------------------------------*
+ * Followings are initialize/terminate functions for Opaque-LSAs handling.
+ *------------------------------------------------------------------------*/
+
+#ifdef HAVE_OSPF_TE
+#include "ospfd/ospf_te.h"
+#endif /* HAVE_OSPF_TE */
+
+static void ospf_opaque_register_vty (void);
+static void ospf_opaque_funclist_init (void);
+static void ospf_opaque_funclist_term (void);
+static void free_opaque_info_per_type (void *val);
+static void free_opaque_info_per_id (void *val);
+static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa);
+static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa);
+
+void
+ospf_opaque_init (void)
+{
+  ospf_opaque_register_vty ();
+  ospf_opaque_funclist_init ();
+
+#ifdef HAVE_OSPF_TE
+  if (ospf_mpls_te_init () != 0)
+    exit (1);
+#endif /* HAVE_OSPF_TE */
+
+  return;
+}
+
+void
+ospf_opaque_term (void)
+{
+#ifdef HAVE_OSPF_TE
+  ospf_mpls_te_term ();
+#endif /* HAVE_OSPF_TE */
+
+  ospf_opaque_funclist_term ();
+  return;
+}
+
+int
+ospf_opaque_type9_lsa_init (struct ospf_interface *oi)
+{
+  if (oi->opaque_lsa_self != NULL)
+    list_delete (oi->opaque_lsa_self);
+
+  oi->opaque_lsa_self = list_new ();
+  oi->opaque_lsa_self->del = free_opaque_info_per_type;
+  oi->t_opaque_lsa_self = NULL;
+  return 0;
+}
+
+void
+ospf_opaque_type9_lsa_term (struct ospf_interface *oi)
+{
+  OSPF_TIMER_OFF (oi->t_opaque_lsa_self);
+  if (oi->opaque_lsa_self != NULL)
+    list_delete (oi->opaque_lsa_self);
+  oi->opaque_lsa_self = NULL;
+  return;
+}
+
+int
+ospf_opaque_type10_lsa_init (struct ospf_area *area)
+{
+  if (area->opaque_lsa_self != NULL)
+    list_delete (area->opaque_lsa_self);
+
+  area->opaque_lsa_self = list_new ();
+  area->opaque_lsa_self->del = free_opaque_info_per_type;
+  area->t_opaque_lsa_self = NULL;
+
+#ifdef MONITOR_LSDB_CHANGE
+  area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
+  area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
+#endif /* MONITOR_LSDB_CHANGE */
+  return 0;
+}
+
+void
+ospf_opaque_type10_lsa_term (struct ospf_area *area)
+{
+#ifdef MONITOR_LSDB_CHANGE
+  area->lsdb->new_lsa_hook = 
+  area->lsdb->del_lsa_hook = NULL;
+#endif /* MONITOR_LSDB_CHANGE */
+
+  OSPF_TIMER_OFF (area->t_opaque_lsa_self);
+  if (area->opaque_lsa_self != NULL)
+    list_delete (area->opaque_lsa_self);
+  area->opaque_lsa_self = NULL;
+  return;
+}
+
+int
+ospf_opaque_type11_lsa_init (struct ospf *top)
+{
+  if (top->opaque_lsa_self != NULL)
+    list_delete (top->opaque_lsa_self);
+
+  top->opaque_lsa_self = list_new ();
+  top->opaque_lsa_self->del = free_opaque_info_per_type;
+  top->t_opaque_lsa_self = NULL;
+
+#ifdef MONITOR_LSDB_CHANGE
+  top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook;
+  top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook;
+#endif /* MONITOR_LSDB_CHANGE */
+  return 0;
+}
+
+void
+ospf_opaque_type11_lsa_term (struct ospf *top)
+{
+#ifdef MONITOR_LSDB_CHANGE
+  top->lsdb->new_lsa_hook = 
+  top->lsdb->del_lsa_hook = NULL;
+#endif /* MONITOR_LSDB_CHANGE */
+
+  OSPF_TIMER_OFF (top->t_opaque_lsa_self);
+  if (top->opaque_lsa_self != NULL)
+    list_delete (top->opaque_lsa_self);
+  top->opaque_lsa_self = NULL;
+  return;
+}
+
+static const char *
+ospf_opaque_type_name (u_char opaque_type)
+{
+  const char *name = "Unknown";
+
+  switch (opaque_type)
+    {
+    case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */
+      name = "Wildcard";
+      break;
+    case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA:
+      name = "Traffic Engineering LSA";
+      break;
+    case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC:
+      name = "Sycamore optical topology description";
+      break;
+    case OPAQUE_TYPE_GRACE_LSA:
+      name = "Grace-LSA";
+      break;
+    default:
+      if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type))
+        name = "Unassigned";
+      else if (OPAQUE_TYPE_RANGE_RESERVED (opaque_type))
+        name = "Private/Experimental";
+      break;
+    }
+  return name;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are management functions to store user specified callbacks.
+ *------------------------------------------------------------------------*/
+
+struct opaque_info_per_type; /* Forward declaration. */
+
+struct ospf_opaque_functab
+{
+  u_char opaque_type;
+  struct opaque_info_per_type *oipt;
+
+  int (* new_if_hook)(struct interface *ifp);
+  int (* del_if_hook)(struct interface *ifp);
+  void (* ism_change_hook)(struct ospf_interface *oi, int old_status);
+  void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status);
+  void (* config_write_router)(struct vty *vty);
+  void (* config_write_if    )(struct vty *vty, struct interface *ifp);
+  void (* config_write_debug )(struct vty *vty);
+  void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa);
+  int  (* lsa_originator)(void *arg);
+  void (* lsa_refresher )(struct ospf_lsa *lsa);
+  int (* new_lsa_hook)(struct ospf_lsa *lsa);
+  int (* del_lsa_hook)(struct ospf_lsa *lsa);
+};
+
+static list ospf_opaque_type9_funclist;
+static list ospf_opaque_type10_funclist;
+static list ospf_opaque_type11_funclist;
+
+static void
+ospf_opaque_del_functab (void *val)
+{
+  XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val);
+  return;
+}
+
+static void
+ospf_opaque_funclist_init (void)
+{
+  list funclist;
+
+  funclist = ospf_opaque_type9_funclist  = list_new ();
+  funclist->del = ospf_opaque_del_functab;
+
+  funclist = ospf_opaque_type10_funclist = list_new ();
+  funclist->del = ospf_opaque_del_functab;
+
+  funclist = ospf_opaque_type11_funclist = list_new ();
+  funclist->del = ospf_opaque_del_functab;
+  return;
+}
+
+static void
+ospf_opaque_funclist_term (void)
+{
+  list funclist;
+
+  funclist = ospf_opaque_type9_funclist;
+  list_delete (funclist);
+
+  funclist = ospf_opaque_type10_funclist;
+  list_delete (funclist);
+
+  funclist = ospf_opaque_type11_funclist;
+  list_delete (funclist);
+  return;
+}
+
+static list
+ospf_get_opaque_funclist (u_char lsa_type)
+{
+  list funclist = NULL;
+
+  switch (lsa_type)
+    {
+    case OSPF_OPAQUE_LINK_LSA:
+      funclist = ospf_opaque_type9_funclist;
+      break;
+    case OSPF_OPAQUE_AREA_LSA:
+      funclist = ospf_opaque_type10_funclist;
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      funclist = ospf_opaque_type11_funclist;
+      break;
+    default:
+      zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type);
+      break;
+    }
+  return funclist;
+}
+
+int
+ospf_register_opaque_functab (
+  u_char lsa_type,
+  u_char opaque_type,
+  int (* new_if_hook)(struct interface *ifp),
+  int (* del_if_hook)(struct interface *ifp),
+  void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
+  void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
+  void (* config_write_router)(struct vty *vty),
+  void (* config_write_if    )(struct vty *vty, struct interface *ifp),
+  void (* config_write_debug )(struct vty *vty),
+  void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa),
+  int  (* lsa_originator)(void *arg),
+  void (* lsa_refresher )(struct ospf_lsa *lsa),
+  int (* new_lsa_hook)(struct ospf_lsa *lsa),
+  int (* del_lsa_hook)(struct ospf_lsa *lsa))
+{
+  list funclist;
+  struct ospf_opaque_functab *new;
+  int rc = -1;
+
+  if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL)
+    {
+      zlog_warn ("ospf_register_opaque_functab: Cannot get funclist for Type-%u LSAs?", lsa_type);
+      goto out;
+    }
+  else
+    {
+      listnode node;
+      struct ospf_opaque_functab *functab;
+
+      for (node = listhead (funclist); node; nextnode (node))
+        if ((functab = getdata (node)) != NULL)
+          if (functab->opaque_type == opaque_type)
+            {
+              zlog_warn ("ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
+              goto out;
+            }
+    }
+
+  if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB,
+		      sizeof (struct ospf_opaque_functab))) == NULL)
+    {
+      zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s", strerror (errno));
+      goto out;
+    }
+
+  new->opaque_type    = opaque_type;
+  new->oipt           = NULL;
+  new->new_if_hook    = new_if_hook;
+  new->del_if_hook    = del_if_hook;
+  new->ism_change_hook     = ism_change_hook;
+  new->nsm_change_hook     = nsm_change_hook;
+  new->config_write_router = config_write_router;
+  new->config_write_if     = config_write_if;
+  new->config_write_debug  = config_write_debug;
+  new->show_opaque_info    = show_opaque_info;
+  new->lsa_originator = lsa_originator;
+  new->lsa_refresher  = lsa_refresher;
+  new->new_lsa_hook   = new_lsa_hook;
+  new->del_lsa_hook   = del_lsa_hook;
+
+  listnode_add (funclist, new);
+  rc = 0;
+
+out:
+  return rc;
+}
+
+void
+ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type)
+{
+  list funclist;
+  listnode node;
+  struct ospf_opaque_functab *functab;
+
+  if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL)
+    for (node = listhead (funclist); node; nextnode (node))
+      {
+        if ((functab = getdata (node)) != NULL
+        &&   functab->opaque_type == opaque_type)
+          {
+            /* Cleanup internal control information, if it still remains. */
+            if (functab->oipt != NULL)
+              free_opaque_info_per_type (functab->oipt);
+
+            /* Dequeue listnode entry from the list. */
+            listnode_delete (funclist, functab);
+
+            /* Avoid misjudgement in the next lookup. */
+            if (listcount (funclist) == 0)
+              funclist->head = funclist->tail = NULL;
+
+            XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab);
+            goto out;
+	  }
+      }
+out:
+  return;
+}
+
+static struct ospf_opaque_functab *
+ospf_opaque_functab_lookup (struct ospf_lsa *lsa)
+{
+  list funclist;
+  listnode node;
+  struct ospf_opaque_functab *functab;
+  u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
+
+  if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL)
+    for (node = listhead (funclist); node; nextnode (node))
+      if ((functab = getdata (node)) != NULL)
+        if (functab->opaque_type == key)
+          return functab;
+
+  return NULL;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are management functions for self-originated LSA entries.
+ *------------------------------------------------------------------------*/
+
+/*
+ * Opaque-LSA control information per opaque-type.
+ * Single Opaque-Type may have multiple instances; each of them will be
+ * identified by their opaque-id.
+ */
+struct opaque_info_per_type
+{
+  u_char opaque_type;
+
+  enum { PROC_NORMAL, PROC_SUSPEND } status;
+
+  /*
+   * Thread for (re-)origination scheduling for this opaque-type.
+   *
+   * Initial origination of Opaque-LSAs is controlled by generic
+   * Opaque-LSA handling module so that same opaque-type entries are
+   * called all at once when certain conditions are met.
+   * However, there might be cases that some Opaque-LSA clients need
+   * to (re-)originate their own Opaque-LSAs out-of-sync with others.
+   * This thread is prepared for that specific purpose.
+   */
+  struct thread *t_opaque_lsa_self;
+
+  /*
+   * Backpointer to an "owner" which is opaque-type dependent.
+   *   type-9:  struct ospf_interface
+   *   type-10: struct ospf_area
+   *   type-11: struct ospf
+   */
+  void *owner;
+
+  /* Collection of callback functions for this opaque-type. */
+  struct ospf_opaque_functab *functab;
+
+  /* List of Opaque-LSA control informations per opaque-id. */
+  list id_list;
+};
+
+/* Opaque-LSA control information per opaque-id. */
+struct opaque_info_per_id
+{
+  u_int32_t opaque_id;
+
+  /* Thread for refresh/flush scheduling for this opaque-type/id. */
+  struct thread *t_opaque_lsa_self;
+
+  /* Backpointer to Opaque-LSA control information per opaque-type. */
+  struct opaque_info_per_type *opqctl_type;
+
+  /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */
+  struct ospf_lsa *lsa;
+};
+
+static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new);
+static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa);
+static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new);
+static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa);
+static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new);
+
+
+static struct opaque_info_per_type *
+register_opaque_info_per_type (struct ospf_opaque_functab *functab,
+                               struct ospf_lsa *new)
+{
+  struct ospf *top;
+  struct opaque_info_per_type *oipt;
+
+  if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE,
+		       sizeof (struct opaque_info_per_type))) == NULL)
+    {
+      zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", strerror (errno));
+      goto out;
+    }
+
+  switch (new->data->type)
+    {
+    case OSPF_OPAQUE_LINK_LSA:
+      oipt->owner = new->oi;
+      listnode_add (new->oi->opaque_lsa_self, oipt);
+      break;
+    case OSPF_OPAQUE_AREA_LSA:
+      oipt->owner = new->area;
+      listnode_add (new->area->opaque_lsa_self, oipt);
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      top = ospf_top;
+      if (new->area != NULL && (top = new->area->top) == NULL)
+        {
+          free_opaque_info_per_type ((void *) oipt);
+          oipt = NULL;
+          goto out; /* This case may not exist. */
+        }
+      oipt->owner = top;
+      listnode_add (top->opaque_lsa_self, oipt);
+      break;
+    default:
+      free_opaque_info_per_type ((void *) oipt);
+      oipt = NULL;
+      goto out; /* This case may not exist. */
+    }
+
+  oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr));
+  oipt->status = PROC_NORMAL;
+  oipt->t_opaque_lsa_self = NULL;
+  oipt->functab = functab;
+  functab->oipt = oipt;
+  oipt->id_list = list_new ();
+  oipt->id_list->del = free_opaque_info_per_id;
+
+out:
+  return oipt;
+}
+
+static void
+free_opaque_info_per_type (void *val)
+{
+  struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val;
+  struct opaque_info_per_id *oipi;
+  struct ospf_lsa *lsa;
+  listnode node;
+
+  /* Control information per opaque-id may still exist. */
+  for (node = listhead (oipt->id_list); node; nextnode (node))
+    {
+      if ((oipi = getdata (node)) == NULL)
+        continue;
+      if ((lsa = oipi->lsa) == NULL)
+        continue;
+      if (IS_LSA_MAXAGE (lsa))
+        continue;
+      ospf_opaque_lsa_flush_schedule (lsa);
+    }
+
+  OSPF_TIMER_OFF (oipt->t_opaque_lsa_self);
+  list_delete (oipt->id_list);
+  XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt);
+  return;
+}
+
+static struct opaque_info_per_type *
+lookup_opaque_info_by_type (struct ospf_lsa *lsa)
+{
+  struct ospf *top;
+  struct ospf_area *area;
+  struct ospf_interface *oi;
+  list listtop = NULL;
+  listnode node;
+  struct opaque_info_per_type *oipt = NULL;
+  u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr));
+
+  switch (lsa->data->type)
+    {
+    case OSPF_OPAQUE_LINK_LSA:
+      if ((oi = lsa->oi) != NULL)
+        listtop = oi->opaque_lsa_self;
+      else
+        zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?");
+      break;
+    case OSPF_OPAQUE_AREA_LSA:
+      if ((area = lsa->area) != NULL)
+        listtop = area->opaque_lsa_self;
+      else
+        zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?");
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      top = ospf_top;
+      if ((area = lsa->area) != NULL && (top = area->top) == NULL)
+        {
+          zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?");
+          break; /* Unlikely to happen. */
+        }
+      listtop = top->opaque_lsa_self;
+      break;
+    default:
+      zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type);
+      break;
+    }
+
+  if (listtop != NULL)
+    for (node = listhead (listtop); node; nextnode (node))
+      if ((oipt = getdata (node)) != NULL)
+        if (oipt->opaque_type == key)
+          return oipt;
+
+  return NULL;
+}
+
+static struct opaque_info_per_id *
+register_opaque_info_per_id (struct opaque_info_per_type *oipt,
+                             struct ospf_lsa *new)
+{
+  struct opaque_info_per_id *oipi;
+
+  if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID,
+		       sizeof (struct opaque_info_per_id))) == NULL)
+    {
+      zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", strerror (errno));
+      goto out;
+    }
+  oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr));
+  oipi->t_opaque_lsa_self = NULL;
+  oipi->opqctl_type = oipt;
+  oipi->lsa = ospf_lsa_lock (new);
+
+  listnode_add (oipt->id_list, oipi);
+
+out:
+  return oipi;
+}
+
+static void
+free_opaque_info_per_id (void *val)
+{
+  struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val;
+
+  OSPF_TIMER_OFF (oipi->t_opaque_lsa_self);
+  if (oipi->lsa != NULL)
+    ospf_lsa_unlock (oipi->lsa);
+  XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi);
+  return;
+}
+
+static struct opaque_info_per_id *
+lookup_opaque_info_by_id (struct opaque_info_per_type *oipt,
+                          struct ospf_lsa *lsa)
+{
+  listnode node;
+  struct opaque_info_per_id   *oipi;
+  u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
+
+  for (node = listhead (oipt->id_list); node; nextnode (node))
+    if ((oipi = getdata (node)) != NULL)
+      if (oipi->opaque_id == key)
+        return oipi;
+
+  return NULL;
+}
+
+static struct opaque_info_per_id *
+register_opaque_lsa (struct ospf_lsa *new)
+{
+  struct ospf_opaque_functab *functab;
+  struct opaque_info_per_type *oipt;
+  struct opaque_info_per_id *oipi = NULL;
+
+  if ((functab = ospf_opaque_functab_lookup (new)) == NULL)
+    goto out;
+
+  if ((oipt = lookup_opaque_info_by_type (new)) == NULL
+  &&  (oipt = register_opaque_info_per_type (functab, new)) == NULL)
+    goto out;
+
+  if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL)
+    goto out;
+
+out:
+  return oipi;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are (vty) configuration functions for Opaque-LSAs handling.
+ *------------------------------------------------------------------------*/
+
+DEFUN (capability_opaque,
+       capability_opaque_cmd,
+       "capability opaque",
+       "Enable specific OSPF feature\n"
+       "Opaque LSA\n")
+{
+  struct ospf *ospf = (struct ospf *) vty->index;
+
+  /* Turn on the "master switch" of opaque-lsa capability. */
+  if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Opaque capability: OFF -> ON");
+
+      SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
+      ospf_renegotiate_optional_capabilities (ospf);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (capability_opaque,
+       ospf_opaque_capable_cmd,
+       "ospf opaque-lsa",
+       "OSPF specific commands\n"
+       "Enable the Opaque-LSA capability (rfc2370)\n")
+
+DEFUN (no_capability_opaque,
+       no_capability_opaque_cmd,
+       "no capability opaque",
+       NO_STR
+       "Enable specific OSPF feature\n"
+       "Opaque LSA\n")
+{
+  struct ospf *ospf = (struct ospf *) vty->index;
+
+  /* Turn off the "master switch" of opaque-lsa capability. */
+  if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Opaque capability: ON -> OFF");
+
+      UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE);
+      ospf_renegotiate_optional_capabilities (ospf);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_capability_opaque,
+       no_ospf_opaque_capable_cmd,
+       "no ospf opaque-lsa",
+       NO_STR
+       "OSPF specific commands\n"
+       "Disable the Opaque-LSA capability (rfc2370)\n")
+
+static void
+ospf_opaque_register_vty (void)
+{
+  install_element (OSPF_NODE, &capability_opaque_cmd);
+  install_element (OSPF_NODE, &no_capability_opaque_cmd);
+  install_element (OSPF_NODE, &ospf_opaque_capable_cmd);
+  install_element (OSPF_NODE, &no_ospf_opaque_capable_cmd);
+  return;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are collection of user-registered function callers.
+ *------------------------------------------------------------------------*/
+
+static int
+opaque_lsa_new_if_callback (list funclist, struct interface *ifp)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+  int rc = -1;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->new_if_hook != NULL)
+        if ((* functab->new_if_hook)(ifp) != 0)
+          goto out;
+  rc = 0;
+out:
+  return rc;
+}
+
+static int
+opaque_lsa_del_if_callback (list funclist, struct interface *ifp)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+  int rc = -1;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->del_if_hook != NULL)
+        if ((* functab->del_if_hook)(ifp) != 0)
+          goto out;
+  rc = 0;
+out:
+  return rc;
+}
+
+static void
+opaque_lsa_ism_change_callback (list funclist,
+                                struct ospf_interface *oi, int old_status)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->ism_change_hook != NULL)
+        (* functab->ism_change_hook)(oi, old_status);
+  return;
+}
+
+static void
+opaque_lsa_nsm_change_callback (list funclist,
+                                struct ospf_neighbor *nbr, int old_status)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->nsm_change_hook != NULL)
+        (* functab->nsm_change_hook)(nbr, old_status);
+  return;
+}
+
+static void
+opaque_lsa_config_write_router_callback (list funclist, struct vty *vty)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->config_write_router != NULL)
+        (* functab->config_write_router)(vty);
+  return;
+}
+
+static void
+opaque_lsa_config_write_if_callback (list funclist,
+                                     struct vty *vty, struct interface *ifp)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->config_write_if != NULL)
+        (* functab->config_write_if)(vty, ifp);
+  return;
+}
+
+static void
+opaque_lsa_config_write_debug_callback (list funclist, struct vty *vty)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->config_write_debug != NULL)
+        (* functab->config_write_debug)(vty);
+  return;
+}
+
+static int
+opaque_lsa_originate_callback (list funclist, void *lsa_type_dependent)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+  int rc = -1;
+
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->lsa_originator != NULL)
+        if ((* functab->lsa_originator)(lsa_type_dependent) != 0)
+           goto out;
+  rc = 0;
+out:
+  return rc;
+}
+
+static int
+new_lsa_callback (list funclist, struct ospf_lsa *lsa)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+  int rc = -1;
+
+  /* This function handles ALL types of LSAs, not only opaque ones. */
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->new_lsa_hook != NULL)
+        if ((* functab->new_lsa_hook)(lsa) != 0)
+          goto out;
+  rc = 0;
+out:
+  return rc;
+}
+
+static int
+del_lsa_callback (list funclist, struct ospf_lsa *lsa)
+{
+  listnode node;
+  struct ospf_opaque_functab *functab;
+  int rc = -1;
+
+  /* This function handles ALL types of LSAs, not only opaque ones. */
+  for (node = listhead (funclist); node; nextnode (node))
+    if ((functab = getdata (node)) != NULL)
+      if (functab->del_lsa_hook != NULL)
+        if ((* functab->del_lsa_hook)(lsa) != 0)
+          goto out;
+  rc = 0;
+out:
+  return rc;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are glue functions to call Opaque-LSA specific processing.
+ *------------------------------------------------------------------------*/
+
+int
+ospf_opaque_new_if (struct interface *ifp)
+{
+  list funclist;
+  int rc = -1;
+
+  funclist = ospf_opaque_type9_funclist;
+  if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type10_funclist;
+  if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type11_funclist;
+  if (opaque_lsa_new_if_callback (funclist, ifp) != 0)
+    goto out;
+
+  rc = 0;
+out:
+  return rc;
+}
+
+int
+ospf_opaque_del_if (struct interface *ifp)
+{
+  list funclist;
+  int rc = -1;
+
+  funclist = ospf_opaque_type9_funclist;
+  if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type10_funclist;
+  if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type11_funclist;
+  if (opaque_lsa_del_if_callback (funclist, ifp) != 0)
+    goto out;
+
+  rc = 0;
+out:
+  return rc;
+}
+
+void
+ospf_opaque_ism_change (struct ospf_interface *oi, int old_status)
+{
+  list funclist;
+
+  funclist = ospf_opaque_type9_funclist;
+  opaque_lsa_ism_change_callback (funclist, oi, old_status);
+
+  funclist = ospf_opaque_type10_funclist;
+  opaque_lsa_ism_change_callback (funclist, oi, old_status);
+
+  funclist = ospf_opaque_type11_funclist;
+  opaque_lsa_ism_change_callback (funclist, oi, old_status);
+
+  return;
+}
+
+void
+ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state)
+{
+  struct ospf *top;
+  list funclist;
+
+  if ((top = oi_to_top (nbr->oi)) == NULL)
+    goto out;
+
+  if (old_state != NSM_Full && nbr->state == NSM_Full)
+    {
+      if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
+        {
+          if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
+            {
+              if (IS_DEBUG_OSPF_EVENT)
+                zlog_info ("Opaque-LSA: Now get operational!");
+
+              SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT);
+            }
+
+          ospf_opaque_lsa_originate_schedule (nbr->oi, NULL);
+        }
+    }
+  else
+  if (old_state == NSM_Full && nbr->state != NSM_Full)
+    {
+#ifdef NOTYET
+      /*
+       * If no more opaque-capable full-state neighbor remains in the
+       * flooding scope which corresponds to Opaque-LSA type, periodic
+       * LS flooding should be stopped.
+       */
+#endif /* NOTYET */
+      ;
+    }
+
+  funclist = ospf_opaque_type9_funclist;
+  opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
+
+  funclist = ospf_opaque_type10_funclist;
+  opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
+
+  funclist = ospf_opaque_type11_funclist;
+  opaque_lsa_nsm_change_callback (funclist, nbr, old_state);
+
+out:
+  return;
+}
+
+void
+ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf)
+{
+  list funclist;
+
+  if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE))
+    vty_out (vty, " capability opaque%s", VTY_NEWLINE);
+
+  funclist = ospf_opaque_type9_funclist;
+  opaque_lsa_config_write_router_callback (funclist, vty);
+
+  funclist = ospf_opaque_type10_funclist;
+  opaque_lsa_config_write_router_callback (funclist, vty);
+
+  funclist = ospf_opaque_type11_funclist;
+  opaque_lsa_config_write_router_callback (funclist, vty);
+
+  return;
+}
+
+void
+ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp)
+{
+  list funclist;
+
+  funclist = ospf_opaque_type9_funclist;
+  opaque_lsa_config_write_if_callback (funclist, vty, ifp);
+
+  funclist = ospf_opaque_type10_funclist;
+  opaque_lsa_config_write_if_callback (funclist, vty, ifp);
+
+  funclist = ospf_opaque_type11_funclist;
+  opaque_lsa_config_write_if_callback (funclist, vty, ifp);
+
+  return;
+}
+
+void
+ospf_opaque_config_write_debug (struct vty *vty)
+{
+  list funclist;
+
+  funclist = ospf_opaque_type9_funclist;
+  opaque_lsa_config_write_debug_callback (funclist, vty);
+
+  funclist = ospf_opaque_type10_funclist;
+  opaque_lsa_config_write_debug_callback (funclist, vty);
+
+  funclist = ospf_opaque_type11_funclist;
+  opaque_lsa_config_write_debug_callback (funclist, vty);
+
+  return;
+}
+
+void
+show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  struct lsa_header *lsah = (struct lsa_header *) lsa->data;
+  u_int32_t lsid = ntohl (lsah->id.s_addr);
+  u_char    opaque_type = GET_OPAQUE_TYPE (lsid);
+  u_int32_t opaque_id = GET_OPAQUE_ID (lsid);
+  struct ospf_opaque_functab *functab;
+
+  /* Switch output functionality by vty address. */
+  if (vty != NULL)
+    {
+      vty_out (vty, "  Opaque-Type %u (%s)%s", opaque_type, ospf_opaque_type_name (opaque_type), VTY_NEWLINE);
+      vty_out (vty, "  Opaque-ID   0x%x%s", opaque_id, VTY_NEWLINE);
+
+      vty_out (vty, "  Opaque-Info: %u octets of data%s%s",
+               ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
+               VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)",
+               VTY_NEWLINE);
+    }
+  else
+    {
+      zlog_info ("    Opaque-Type %u (%s)", opaque_type, ospf_opaque_type_name (opaque_type));
+      zlog_info ("    Opaque-ID   0x%x", opaque_id);
+
+      zlog_info ("    Opaque-Info: %u octets of data%s",
+               ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE,
+               VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)");
+    }
+
+  /* Call individual output functions. */
+  if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL)
+    if (functab->show_opaque_info != NULL)
+      (* functab->show_opaque_info)(vty, lsa);
+
+  return;
+}
+
+void
+ospf_opaque_lsa_dump (struct stream *s, u_int16_t length)
+{
+  struct ospf_lsa lsa;
+
+  lsa.data = (struct lsa_header *) STREAM_PNT (s);
+  show_opaque_info_detail (NULL, &lsa);
+  return;
+}
+
+static int
+ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa)
+{
+  list funclist;
+  int rc = -1;
+
+  /*
+   * Some Opaque-LSA user may want to monitor every LSA installation
+   * into the LSDB, regardless with target LSA type.
+   */
+  funclist = ospf_opaque_type9_funclist;
+  if (new_lsa_callback (funclist, lsa) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type10_funclist;
+  if (new_lsa_callback (funclist, lsa) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type11_funclist;
+  if (new_lsa_callback (funclist, lsa) != 0)
+    goto out;
+
+  rc = 0;
+out:
+  return rc;
+}
+
+static int
+ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa)
+{
+  list funclist;
+  int rc = -1;
+
+  /*
+   * Some Opaque-LSA user may want to monitor every LSA deletion
+   * from the LSDB, regardless with target LSA type.
+   */
+  funclist = ospf_opaque_type9_funclist;
+  if (del_lsa_callback (funclist, lsa) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type10_funclist;
+  if (del_lsa_callback (funclist, lsa) != 0)
+    goto out;
+
+  funclist = ospf_opaque_type11_funclist;
+  if (del_lsa_callback (funclist, lsa) != 0)
+    goto out;
+
+  rc = 0;
+out:
+  return rc;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are Opaque-LSA origination/refresh management functions.
+ *------------------------------------------------------------------------*/
+
+static int ospf_opaque_type9_lsa_originate (struct thread *t);
+static int ospf_opaque_type10_lsa_originate (struct thread *t);
+static int ospf_opaque_type11_lsa_originate (struct thread *t);
+static void ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg);
+
+void
+ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0)
+{
+  struct ospf *top;
+  struct ospf_area *area;
+  listnode node;
+  struct opaque_info_per_type *oipt;
+  int delay = 0;
+
+  if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL)
+    {
+      zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?");
+      goto out;
+    }
+
+  /* It may not a right time to schedule origination now. */
+  if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("ospf_opaque_lsa_originate_schedule: Not operational.");
+      goto out; /* This is not an error. */
+    }
+  if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("ospf_opaque_lsa_originate_schedule: Under blockade.");
+      goto out; /* This is not an error, too. */
+    }
+
+  if (delay0 != NULL)
+    delay = *delay0;
+
+  /*
+   * There might be some entries that have been waiting for triggering
+   * of per opaque-type re-origination get resumed.
+   */
+  ospf_opaque_lsa_reoriginate_resume (  oi->opaque_lsa_self, (void *)   oi);
+  ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area);
+  ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *)  top);
+
+  /*
+   * Now, schedule origination of all Opaque-LSAs per opaque-type.
+   */
+  if (! list_isempty (ospf_opaque_type9_funclist)
+  &&    list_isempty (oi->opaque_lsa_self)
+  &&    oi->t_opaque_lsa_self == NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Schedule Type-9 Opaque-LSA origination in %d sec later.", delay);
+      oi->t_opaque_lsa_self =
+	thread_add_timer (master, ospf_opaque_type9_lsa_originate, oi, delay);
+      delay += OSPF_MIN_LS_INTERVAL;
+    }
+
+  if (! list_isempty (ospf_opaque_type10_funclist)
+  &&    list_isempty (area->opaque_lsa_self)
+  &&    area->t_opaque_lsa_self == NULL)
+    {
+      /*
+       * One AREA may contain multiple OIs, but above 2nd and 3rd
+       * conditions prevent from scheduling the originate function
+       * again and again.
+       */
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Schedule Type-10 Opaque-LSA origination in %d sec later.", delay);
+      area->t_opaque_lsa_self =
+        thread_add_timer (master, ospf_opaque_type10_lsa_originate,
+                          area, delay);
+      delay += OSPF_MIN_LS_INTERVAL;
+    }
+
+  if (! list_isempty (ospf_opaque_type11_funclist)
+  &&    list_isempty (top->opaque_lsa_self)
+  &&    top->t_opaque_lsa_self == NULL)
+    {
+      /*
+       * One OSPF may contain multiple AREAs, but above 2nd and 3rd
+       * conditions prevent from scheduling the originate function
+       * again and again.
+       */
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Schedule Type-11 Opaque-LSA origination in %d sec later.", delay);
+      top->t_opaque_lsa_self =
+        thread_add_timer (master, ospf_opaque_type11_lsa_originate,
+                          top, delay);
+      delay += OSPF_MIN_LS_INTERVAL;
+    }
+
+  /*
+   * Following section treats a special situation that this node's
+   * opaque capability has changed as "ON -> OFF -> ON".
+   */
+  if (! list_isempty (ospf_opaque_type9_funclist)
+  &&  ! list_isempty (oi->opaque_lsa_self))
+    {
+      for (node = listhead (oi->opaque_lsa_self); node; nextnode (node))
+        {
+          if ((oipt = getdata (node))  == NULL /* Something wrong? */
+          ||   oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
+          ||   oipt->status == PROC_SUSPEND    /* Cannot originate now. */
+          ||  ! list_isempty (oipt->id_list))  /* Handler is already active. */
+              continue;
+
+          ospf_opaque_lsa_reoriginate_schedule ((void *) oi,
+            OSPF_OPAQUE_LINK_LSA, oipt->opaque_type);
+        }
+    }
+
+  if (! list_isempty (ospf_opaque_type10_funclist)
+  &&  ! list_isempty (area->opaque_lsa_self))
+    {
+      for (node = listhead (area->opaque_lsa_self); node; nextnode (node))
+        {
+          if ((oipt = getdata (node))  == NULL /* Something wrong? */
+          ||   oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
+          ||   oipt->status == PROC_SUSPEND    /* Cannot originate now. */
+          ||  ! list_isempty (oipt->id_list))  /* Handler is already active. */
+            continue;
+
+          ospf_opaque_lsa_reoriginate_schedule ((void *) area,
+            OSPF_OPAQUE_AREA_LSA, oipt->opaque_type);
+        }
+    }
+
+  if (! list_isempty (ospf_opaque_type11_funclist)
+  &&  ! list_isempty (top->opaque_lsa_self))
+    {
+      for (node = listhead (top->opaque_lsa_self); node; nextnode (node))
+        {
+          if ((oipt = getdata (node))  == NULL /* Something wrong? */
+          ||   oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */
+          ||   oipt->status == PROC_SUSPEND    /* Cannot originate now. */
+          ||  ! list_isempty (oipt->id_list))  /* Handler is already active. */
+            continue;
+
+          ospf_opaque_lsa_reoriginate_schedule ((void *) top,
+            OSPF_OPAQUE_AS_LSA, oipt->opaque_type);
+        }
+    }
+
+  if (delay0 != NULL)
+    *delay0 = delay;
+
+out:
+  return;
+}
+
+static int
+ospf_opaque_type9_lsa_originate (struct thread *t)
+{
+  struct ospf_interface *oi;
+  int rc;
+
+  oi = THREAD_ARG (t);
+  oi->t_opaque_lsa_self = NULL;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s",
+                IF_NAME (oi));
+
+  rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi);
+
+  return rc;
+}
+
+static int
+ospf_opaque_type10_lsa_originate (struct thread *t)
+{
+  struct ospf_area *area;
+  int rc;
+
+  area = THREAD_ARG (t);
+  area->t_opaque_lsa_self = NULL;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s",
+                inet_ntoa (area->area_id));
+
+  rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area);
+
+  return rc;
+}
+
+static int
+ospf_opaque_type11_lsa_originate (struct thread *t)
+{
+  struct ospf *top;
+  int rc;
+
+  top = THREAD_ARG (t);
+  top->t_opaque_lsa_self = NULL;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs");
+
+  rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top);
+
+  return rc;
+}
+
+static void
+ospf_opaque_lsa_reoriginate_resume (list listtop, void *arg)
+{
+  listnode node;
+  struct opaque_info_per_type *oipt;
+  struct ospf_opaque_functab *functab;
+
+  if (listtop == NULL)
+    goto out;
+
+  /*
+   * Pickup oipt entries those which in SUSPEND status, and give
+   * them a chance to start re-origination now.
+   */
+  for (node = listhead (listtop); node; nextnode (node))
+    {
+      if ((oipt = getdata (node)) == NULL
+      ||   oipt->status != PROC_SUSPEND)
+          continue;
+
+      oipt->status = PROC_NORMAL;
+
+      if ((functab = oipt->functab) == NULL
+      ||   functab->lsa_originator  == NULL)
+        continue;
+
+      if ((* functab->lsa_originator)(arg) != 0)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type);
+          continue;
+        }
+    }
+
+out:
+  return;
+}
+
+struct ospf_lsa *
+ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc)
+{
+  struct ospf_lsa *new = NULL;
+  struct opaque_info_per_type *oipt;
+  struct opaque_info_per_id *oipi;
+  struct ospf *top;
+
+  /* Don't take "rt_recalc" into consideration for now. *//* XXX */
+
+  if (! IS_LSA_SELF (lsa))
+    {
+      new = lsa; /* Don't touch this LSA. */
+      goto out;
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
+    zlog_info ("Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
+
+  /* Replace the existing lsa with the new one. */
+  if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL
+  &&  (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL)
+    {
+      ospf_lsa_unlock (oipi->lsa);
+      oipi->lsa = ospf_lsa_lock (lsa);
+    }
+  /* Register the new lsa entry and get its control info. */
+  else
+  if ((oipi = register_opaque_lsa (lsa)) == NULL)
+    {
+      zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?");
+      goto out;
+    }
+
+  /*
+   * Make use of a common mechanism (ospf_lsa_refresh_walker)
+   * for periodic refresh of self-originated Opaque-LSAs.
+   */
+  switch (lsa->data->type)
+    {
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+      if (lsa->area == NULL || (top = lsa->area->top) == NULL)
+        {
+          /* Above conditions must have passed. */
+          zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
+          goto out;
+        }
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      top = ospf_top;
+      if (lsa->area != NULL && (top = lsa->area->top) == NULL)
+        {
+          /* Above conditions must have passed. */
+          zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?");
+          goto out;
+        }
+      break;
+    default:
+      zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type);
+      goto out;
+    }
+
+  ospf_refresher_register_lsa (top, lsa);
+  new = lsa;
+
+out:
+  return new;
+}
+
+void
+ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
+{
+  struct ospf_opaque_functab *functab;
+
+  if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
+  ||   functab->lsa_refresher == NULL)
+    {
+      /*
+       * Though this LSA seems to have originated on this node, the
+       * handling module for this "lsa-type and opaque-type" was
+       * already deleted sometime ago.
+       * Anyway, this node still has a responsibility to flush this
+       * LSA from the routing domain.
+       */
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
+
+      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+      ospf_lsa_maxage (lsa);
+    }
+  else
+    (* functab->lsa_refresher)(lsa);
+
+  return;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are re-origination/refresh/flush operations of Opaque-LSAs,
+ * triggered by external interventions (vty session, signaling, etc).
+ *------------------------------------------------------------------------*/
+
+#define OSPF_OPAQUE_TIMER_ON(T,F,L,V) \
+      if (!(T)) \
+        (T) = thread_add_timer (master, (F), (L), (V))
+
+static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type);
+static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t);
+static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t);
+static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t);
+static int ospf_opaque_lsa_refresh_timer (struct thread *t);
+
+void
+ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
+                                      u_char lsa_type, u_char opaque_type)
+{
+  struct ospf *top;
+  struct ospf_area dummy, *area = NULL;
+  struct ospf_interface *oi = NULL;
+
+  struct ospf_lsa *lsa;
+  struct opaque_info_per_type *oipt;
+  int (* func)(struct thread *t) = NULL;
+  int delay;
+
+  switch (lsa_type)
+    {
+    case OSPF_OPAQUE_LINK_LSA:
+      if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
+	  goto out;
+        }
+      if ((top = oi_to_top (oi)) == NULL)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", IF_NAME (oi));
+          goto out;
+        }
+      if (! list_isempty (ospf_opaque_type9_funclist)
+      &&    list_isempty (oi->opaque_lsa_self)
+      &&    oi->t_opaque_lsa_self != NULL)
+        {
+          zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u): Common origination for OI(%s) has already started", opaque_type, IF_NAME (oi));
+          goto out;
+        }
+      func = ospf_opaque_type9_lsa_reoriginate_timer;
+      break;
+    case OSPF_OPAQUE_AREA_LSA:
+      if ((area = (struct ospf_area *) lsa_type_dependent) == NULL)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
+          goto out;
+        }
+      if ((top = area->top) == NULL)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: AREA(%s) -> TOP?", inet_ntoa (area->area_id));
+          goto out;
+        }
+      if (! list_isempty (ospf_opaque_type10_funclist)
+      &&    list_isempty (area->opaque_lsa_self)
+      &&    area->t_opaque_lsa_self != NULL)
+        {
+          zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u): Common origination for AREA(%s) has already started", opaque_type, inet_ntoa (area->area_id));
+          goto out;
+        }
+      func = ospf_opaque_type10_lsa_reoriginate_timer;
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      if ((top = (struct ospf *) lsa_type_dependent) == NULL)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
+	  goto out;
+        }
+      if (! list_isempty (ospf_opaque_type11_funclist)
+      &&    list_isempty (top->opaque_lsa_self)
+      &&    top->t_opaque_lsa_self != NULL)
+        {
+          zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u): Common origination has already started", opaque_type);
+          goto out;
+        }
+
+      /* Fake "area" to pass "ospf" to a lookup function later. */
+      dummy.top = top;
+      area = &dummy;
+
+      func = ospf_opaque_type11_lsa_reoriginate_timer;
+      break;
+    default:
+      zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)", lsa_type);
+      goto out;
+    }
+
+  /* It may not a right time to schedule reorigination now. */
+  if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Not operational.");
+      goto out; /* This is not an error. */
+    }
+  if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("ospf_opaque_lsa_reoriginate_schedule: Under blockade.");
+      goto out; /* This is not an error, too. */
+    }
+
+  /* Generate a dummy lsa to be passed for a lookup function. */
+  lsa = pseudo_lsa (oi, area, lsa_type, opaque_type);
+
+  if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL)
+    {
+      struct ospf_opaque_functab *functab;
+      if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
+          goto out;
+        }
+      if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL)
+        {
+          zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)", lsa_type, opaque_type);
+          goto out;
+        }
+    }
+
+  if (oipt->t_opaque_lsa_self != NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Type-%u Opaque-LSA has already scheduled to RE-ORIGINATE: [opaque-type=%u]", lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
+      goto out;
+    }
+
+  /*
+   * Different from initial origination time, in which various conditions
+   * (opaque capability, neighbor status etc) are assured by caller of
+   * the originating function "ospf_opaque_lsa_originate_schedule ()",
+   * it is highly possible that these conditions might not be satisfied
+   * at the time of re-origination function is to be called.
+   */
+  delay = OSPF_MIN_LS_INTERVAL; /* XXX */
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d sec later: [opaque-type=%u]", lsa_type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)));
+
+  OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay);
+
+out:
+  return;
+}
+
+static struct ospf_lsa *
+pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area,
+            u_char lsa_type, u_char opaque_type)
+{
+  static struct ospf_lsa lsa = { 0 };
+  static struct lsa_header lsah = { 0 };
+  u_int32_t tmp;
+
+  lsa.oi   = oi;
+  lsa.area = area;
+  lsa.data = &lsah;
+
+  lsah.type = lsa_type;
+  tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */
+  lsah.id.s_addr = htonl (tmp);
+
+  return &lsa;
+}
+
+static int
+ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t)
+{
+  struct opaque_info_per_type *oipt;
+  struct ospf_opaque_functab *functab;
+  struct ospf *top;
+  struct ospf_interface *oi;
+  int rc = -1;
+
+  oipt = THREAD_ARG (t);
+  oipt->t_opaque_lsa_self = NULL;
+
+  if ((functab = oipt->functab) == NULL
+  ||   functab->lsa_originator == NULL)
+    {
+      zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
+      goto out;
+    }
+
+  oi = (struct ospf_interface *) oipt->owner;
+  if ((top = oi_to_top (oi)) == NULL)
+    {
+      zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
+      goto out;
+    }
+
+  if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)
+  ||  ! ospf_if_is_enable (oi)
+  ||    ospf_opaque_capable_nbr_count (oi->nbrs, NSM_Full) == 0)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
+    
+      oipt->status = PROC_SUSPEND;
+      rc = 0;
+      goto out;
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi));
+
+  rc = (* functab->lsa_originator)(oi);
+out:
+  return rc;
+}
+
+static int
+ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t)
+{
+  struct opaque_info_per_type *oipt;
+  struct ospf_opaque_functab *functab;
+  listnode node;
+  struct ospf *top;
+  struct ospf_area *area;
+  struct ospf_interface *oi;
+  int n, rc = -1;
+
+  oipt = THREAD_ARG (t);
+  oipt->t_opaque_lsa_self = NULL;
+
+  if ((functab = oipt->functab) == NULL
+  ||   functab->lsa_originator == NULL)
+    {
+      zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
+      goto out;
+    }
+
+  area = (struct ospf_area *) oipt->owner;
+  if (area == NULL || (top = area->top) == NULL)
+    {
+      zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
+      goto out;
+    }
+
+  /* There must be at least one "opaque-capable, full-state" neighbor. */
+  n = 0;
+  for (node = listhead (area->oiflist); node; nextnode (node))
+    {
+      if ((oi = getdata (node)) == NULL)
+        continue;
+      if ((n = ospf_opaque_capable_nbr_count (oi->nbrs, NSM_Full)) > 0)
+        break;
+    }
+
+  if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Suspend re-origination of Type-10 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
+
+      oipt->status = PROC_SUSPEND;
+      rc = 0;
+      goto out;
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[Type10-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for Area %s", oipt->opaque_type, inet_ntoa (area->area_id));
+
+  rc = (* functab->lsa_originator)(area);
+out:
+  return rc;
+}
+
+static int
+ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t)
+{
+  struct opaque_info_per_type *oipt;
+  struct ospf_opaque_functab *functab;
+  struct ospf *top;
+  int rc = -1;
+
+  oipt = THREAD_ARG (t);
+  oipt->t_opaque_lsa_self = NULL;
+
+  if ((functab = oipt->functab) == NULL
+  ||   functab->lsa_originator == NULL)
+    {
+      zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
+      goto out;
+    }
+
+  if ((top = (struct ospf *) oipt->owner) == NULL)
+    {
+      zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
+      goto out;
+    }
+
+  if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type);
+    
+      oipt->status = PROC_SUSPEND;
+      rc = 0;
+      goto out;
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type);
+
+  rc = (* functab->lsa_originator)(top);
+out:
+  return rc;
+}
+
+extern int ospf_lsa_refresh_delay (struct ospf_lsa *); /* ospf_lsa.c */
+
+void
+ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0)
+{
+  struct opaque_info_per_type *oipt;
+  struct opaque_info_per_id *oipi;
+  struct ospf_lsa *lsa;
+  int delay;
+
+  if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
+  ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
+    {
+      zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
+      goto out;
+    }
+
+  /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
+  if ((lsa = oipi->lsa) == NULL)
+    {
+      zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?");
+      goto out;
+    }
+
+  if (oipi->t_opaque_lsa_self != NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
+      goto out;
+    }
+
+  /* Delete this lsa from neighbor retransmit-list. */
+  switch (lsa->data->type)
+    {
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+      ospf_ls_retransmit_delete_nbr_all (lsa->area, lsa);
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      ospf_ls_retransmit_delete_nbr_all (NULL, lsa);
+      break;
+    default:
+      zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type);
+      goto out;
+    }
+
+  delay = ospf_lsa_refresh_delay (lsa);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
+
+  OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self,
+                        ospf_opaque_lsa_refresh_timer, oipi, delay);
+out:
+  return;
+}
+
+static int
+ospf_opaque_lsa_refresh_timer (struct thread *t)
+{
+  struct opaque_info_per_id *oipi;
+  struct ospf_opaque_functab *functab;
+  struct ospf_lsa *lsa;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)");
+
+  oipi = THREAD_ARG (t);
+  oipi->t_opaque_lsa_self = NULL;
+
+  if ((lsa = oipi->lsa) != NULL)
+    if ((functab = oipi->opqctl_type->functab) != NULL)
+      if (functab->lsa_refresher != NULL)
+        (* functab->lsa_refresher)(lsa);
+
+  return 0;
+}
+
+void
+ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
+{
+  struct opaque_info_per_type *oipt;
+  struct opaque_info_per_id *oipi;
+  struct ospf_lsa *lsa;
+
+  if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL
+  ||  (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL)
+    {
+      zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?");
+      goto out;
+    }
+
+  /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
+  if ((lsa = oipi->lsa) == NULL)
+    {
+      zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?");
+      goto out;
+    }
+
+  /* Delete this lsa from neighbor retransmit-list. */
+  switch (lsa->data->type)
+    {
+    case OSPF_OPAQUE_LINK_LSA:
+    case OSPF_OPAQUE_AREA_LSA:
+      ospf_ls_retransmit_delete_nbr_all (lsa->area, lsa);
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      ospf_ls_retransmit_delete_nbr_all (NULL, lsa);
+      break;
+    default:
+      zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type);
+      goto out;
+    }
+
+  /* Dequeue listnode entry from the list. */
+  listnode_delete (oipt->id_list, oipi);
+
+  /* Avoid misjudgement in the next lookup. */
+  if (listcount (oipt->id_list) == 0)
+    oipt->id_list->head = oipt->id_list->tail = NULL;
+
+  /* Disassociate internal control information with the given lsa. */
+  oipi->lsa = NULL;
+  free_opaque_info_per_id ((void *) oipi);
+
+  /* Force given lsa's age to MaxAge. */
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
+
+  /* This lsa will be flushed and removed eventually. */
+  ospf_lsa_maxage (lsa);
+
+out:
+  return;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are control functions to block origination after restart.
+ *------------------------------------------------------------------------*/
+
+static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa);
+static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi);
+static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area);
+static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top);
+static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type);
+
+void
+ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas)
+{
+  struct ospf *top;
+  struct ospf_area *area;
+  struct ospf_interface *oi;
+  listnode node1, node2;
+  struct ospf_lsa *lsa;
+
+  if ((top = oi_to_top (nbr->oi)) == NULL)
+    goto out;
+
+  /*
+   * If an instance of self-originated Opaque-LSA is found in the given
+   * LSA list, and it is not installed to LSDB yet, exclude it from the
+   * list "nbr->ls_req". In this way, it is assured that an LSReq message,
+   * which might be sent in the process of flooding, will not request for
+   * the LSA to be flushed immediately; otherwise, depending on timing,
+   * an LSUpd message will carry instances of target LSAs with MaxAge,
+   * while other LSUpd message might carry old LSA instances (non-MaxAge).
+   * Obviously, the latter would trigger miserable situations that repeat
+   * installation and removal of unwanted LSAs indefinitely.
+   */
+  for (node1 = listhead (lsas); node1; nextnode (node1))
+    {
+      if ((lsa = getdata (node1)) == NULL)
+        continue;
+
+      /* Filter out unwanted LSAs. */
+      if (! IS_OPAQUE_LSA (lsa->data->type))
+        continue;
+      if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id))
+        continue;
+
+      /*
+       * Don't touch an LSA which has MaxAge; two possible cases.
+       *
+       *   1) This LSA has originally flushed by myself (received LSUpd
+       *      message's router-id is equal to my router-id), and flooded
+       *      back by an opaque-capable router.
+       *
+       *   2) This LSA has expired in an opaque-capable router and thus
+       *      flushed by the router.
+       */
+      if (IS_LSA_MAXAGE (lsa))
+        continue;
+
+      /* If the LSA has installed in the LSDB, nothing to do here. */
+      if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL)
+        continue;
+
+      /* Ok, here we go. */
+      switch (lsa->data->type)
+        {
+        case OSPF_OPAQUE_LINK_LSA:
+          oi = nbr->oi;
+          ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
+          break;
+        case OSPF_OPAQUE_AREA_LSA:
+          area = nbr->oi->area;
+          for (node2 = listhead (area->oiflist); node2; nextnode (node2))
+            {
+              if ((oi = getdata (node2)) == NULL)
+                continue;
+              ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
+            }
+          break;
+        case OSPF_OPAQUE_AS_LSA:
+          for (node2 = listhead (top->oiflist); node2; nextnode (node2))
+            {
+              if ((oi = getdata (node2)) == NULL)
+                continue;
+              ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa);
+            }
+          break;
+        default:
+          break;
+        }
+    }
+
+out:
+  return;
+}
+
+static void
+ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs,
+                                    struct ospf_neighbor *inbr,
+                                    struct ospf_lsa *lsa)
+{
+  struct route_node *rn;
+  struct ospf_neighbor *onbr;
+  struct ospf_lsa *ls_req;
+
+  for (rn = route_top (nbrs); rn; rn = route_next (rn))
+    {
+      if ((onbr = rn->info) == NULL)
+        continue;
+      if (onbr == inbr)
+        continue;
+      if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL)
+        continue;
+
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa));
+
+      ospf_ls_request_delete (onbr, ls_req);
+/*    ospf_check_nbr_loading (onbr);*//* XXX */
+    }
+
+  return;
+}
+
+void
+ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas)
+{
+  struct ospf *top;
+  listnode node, next;
+  struct ospf_lsa *lsa;
+  u_char before;
+
+  if ((top = oi_to_top (nbr->oi)) == NULL)
+    goto out;
+
+  before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
+
+  for (node = listhead (lsas); node; node = next)
+    {
+      next = node->next;
+
+      if ((lsa = getdata (node)) == NULL)
+        continue;
+
+      listnode_delete (lsas, lsa);
+
+      /*
+       * Since these LSA entries are not yet installed into corresponding
+       * LSDB, just flush them without calling ospf_ls_maxage() afterward.
+       */
+      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+      switch (lsa->data->type)
+        {
+        case OSPF_OPAQUE_LINK_LSA:
+          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
+          ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
+          break;
+        case OSPF_OPAQUE_AREA_LSA:
+          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
+          ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
+          break;
+        case OSPF_OPAQUE_AS_LSA:
+          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
+          ospf_flood_through_as (NULL/*inbr*/, lsa);
+          break;
+        default:
+          zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
+          goto out;
+        }
+
+      ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
+    }
+
+  if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Block Opaque-LSA origination: OFF -> ON");
+    }
+
+out:
+  return;
+}
+
+void
+ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, list acks)
+{
+  struct ospf *top;
+  listnode node;
+  struct ospf_lsa *lsa;
+  char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
+
+  if ((top = oi_to_top (nbr->oi)) == NULL)
+    goto out;
+
+  for (node = listhead (acks); node; nextnode (node))
+    {
+      if ((lsa = getdata (node)) == NULL)
+        continue;
+
+      switch (lsa->data->type)
+        {
+        case OSPF_OPAQUE_LINK_LSA:
+          type9_lsa_rcv = 1;
+          /* Callback function... */
+          break;
+        case OSPF_OPAQUE_AREA_LSA:
+          type10_lsa_rcv = 1;
+          /* Callback function... */
+          break;
+        case OSPF_OPAQUE_AS_LSA:
+          type11_lsa_rcv = 1;
+          /* Callback function... */
+          break;
+        default:
+          zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
+          goto out;
+        }
+    }
+
+  if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
+    {
+      int delay;
+      struct ospf_interface *oi;
+
+      if (type9_lsa_rcv
+      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
+        ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
+
+      if (type10_lsa_rcv
+      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
+        ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
+
+      if (type11_lsa_rcv
+      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
+        ospf_opaque_type11_lsa_rxmt_nbr_check (top);
+
+      if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
+        goto out; /* Blocking still in progress. */
+
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Block Opaque-LSA origination: ON -> OFF");
+
+      if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
+        goto out; /* Opaque capability condition must have changed. */
+
+      /* Ok, let's start origination of Opaque-LSAs. */
+      delay = OSPF_MIN_LS_INTERVAL;
+      for (node = listhead (top->oiflist); node; nextnode (node))
+        {
+          if ((oi = getdata (node)) == NULL)
+            continue;
+
+          if (! ospf_if_is_enable (oi)
+          ||    ospf_opaque_capable_nbr_count (oi->nbrs, NSM_Full) == 0)
+            continue;
+
+          ospf_opaque_lsa_originate_schedule (oi, &delay);
+        }
+    }
+
+out:
+  return;
+}
+
+static void
+ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi)
+{
+  unsigned long n;
+
+  n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA);
+  if (n == 0)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi));
+
+      UNSET_FLAG (oi->area->top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
+    }
+  return;
+}
+
+static void
+ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area)
+{
+  listnode node;
+  struct ospf_interface *oi;
+  unsigned long n = 0;
+
+  for (node = listhead (area->oiflist); node; nextnode (node))
+    {
+      if ((oi = getdata (node)) == NULL)
+        continue;
+
+      if (area->area_id.s_addr != OSPF_AREA_BACKBONE
+      &&  oi->type == OSPF_IFTYPE_VIRTUALLINK) 
+        continue;
+
+      n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA);
+      if (n > 0)
+        break;
+    }
+
+  if (n == 0)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id));
+
+      UNSET_FLAG (area->top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
+    }
+
+  return;
+}
+
+static void
+ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top)
+{
+  listnode node;
+  struct ospf_interface *oi;
+  unsigned long n = 0;
+
+  for (node = listhead (top->oiflist); node; nextnode (node))
+    {
+      if ((oi = getdata (node)) == NULL)
+        continue;
+
+      switch (oi->type)
+        {
+        case OSPF_IFTYPE_VIRTUALLINK:
+          continue;
+        default:
+          break;
+        }
+
+      n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA);
+      if (n > 0)
+        goto out;
+    }
+
+  if (n == 0)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("Self-originated type-11 Opaque-LSAs: Flush completed");
+
+      UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
+    }
+
+out:
+  return;
+}
+
+static unsigned long
+ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type)
+{
+  struct route_node *rn;
+  struct ospf_neighbor *nbr;
+  struct ospf *top;
+  unsigned long n = 0;
+
+  for (rn = route_top (nbrs); rn; rn = route_next (rn))
+    {
+      if ((nbr = rn->info) == NULL)
+        continue;
+      if ((top = oi_to_top (nbr->oi)) == NULL)
+        continue;
+      if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id))
+        continue;
+      n += ospf_ls_retransmit_count_self (nbr, lsa_type);
+    }
+
+  return n;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are util functions; probably be used by Opaque-LSAs only...
+ *------------------------------------------------------------------------*/
+
+void
+htonf (float *src, float *dst)
+{
+  u_int32_t lu1, lu2;
+
+  memcpy (&lu1, src, sizeof (u_int32_t));
+  lu2 = htonl (lu1);
+  memcpy (dst, &lu2, sizeof (u_int32_t));
+  return;
+}
+
+void
+ntohf (float *src, float *dst)
+{
+  u_int32_t lu1, lu2;
+
+  memcpy (&lu1, src, sizeof (u_int32_t));
+  lu2 = ntohl (lu1);
+  memcpy (dst, &lu2, sizeof (u_int32_t));
+  return;
+}
+
+struct ospf *
+oi_to_top (struct ospf_interface *oi)
+{
+  struct ospf *top = NULL;
+  struct ospf_area *area;
+
+  if (oi == NULL || (area = oi->area) == NULL || (top = area->top) == NULL)
+    zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?");
+
+  return top;
+}
+
+#endif /* HAVE_OPAQUE_LSA */
diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h
new file mode 100644
index 0000000..9aa08e5
--- /dev/null
+++ b/ospfd/ospf_opaque.h
@@ -0,0 +1,155 @@
+/*
+ * This is an implementation of rfc2370.
+ * Copyright (C) 2001 KDD R&D Laboratories, Inc.
+ * http://www.kddlabs.co.jp/
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_OPAQUE_H
+#define _ZEBRA_OSPF_OPAQUE_H
+
+#define	IS_OPAQUE_LSA(type) \
+	((type) == OSPF_OPAQUE_LINK_LSA  || \
+	 (type) == OSPF_OPAQUE_AREA_LSA  || \
+	 (type) == OSPF_OPAQUE_AS_LSA)
+
+/*
+ * Usage of Opaque-LSA administrative flags in "struct ospf".
+ *
+ *    7   6   5   4   3   2   1   0
+ * +---+---+---+---+---+---+---+---+
+ * |///|///|///|///|B11|B10|B09| O |
+ * +---+---+---+---+---+---+---+---+
+ *                 |<--------->| A
+ *                       |       +--- Operation status (operational = 1)
+ *                       +----------- Blocking status for each LSA type
+ */
+
+#define IS_OPAQUE_LSA_ORIGINATION_BLOCKED(V) \
+        CHECK_FLAG((V), (OPAQUE_BLOCK_TYPE_09_LSA_BIT | \
+                         OPAQUE_BLOCK_TYPE_10_LSA_BIT | \
+                         OPAQUE_BLOCK_TYPE_11_LSA_BIT))
+
+/*
+ * Opaque LSA's link state ID is redefined as follows.
+ *
+ *        24       16        8        0
+ * +--------+--------+--------+--------+
+ * |tttttttt|........|........|........|
+ * +--------+--------+--------+--------+
+ * |<-Type->|<------- Opaque ID ------>|
+ */
+#define LSID_OPAQUE_TYPE_MASK	0xff000000	/*  8 bits */
+#define LSID_OPAQUE_ID_MASK	0x00ffffff	/* 24 bits */
+
+#define	GET_OPAQUE_TYPE(lsid) \
+	(((u_int32_t)(lsid) & LSID_OPAQUE_TYPE_MASK) >> 24)
+
+#define	GET_OPAQUE_ID(lsid) \
+	 ((u_int32_t)(lsid) & LSID_OPAQUE_ID_MASK)
+
+#define	SET_OPAQUE_LSID(type, id) \
+	((((type) << 24) & LSID_OPAQUE_TYPE_MASK) \
+	| ((id)          & LSID_OPAQUE_ID_MASK))
+
+/*
+ * Opaque LSA types will be assigned by IANA.
+ * <http://www.iana.org/assignments/ospf-opaque-types>
+ */
+#define OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA		1
+#define OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC	2
+#define OPAQUE_TYPE_GRACE_LSA				3
+
+/* Followings types are proposed in internet-draft documents. */
+#define OPAQUE_TYPE_8021_QOSPF				129
+#define OPAQUE_TYPE_SECONDARY_NEIGHBOR_DISCOVERY	224
+#define OPAQUE_TYPE_FLOODGATE                           225
+
+/* Ugly hack to make use of an unallocated value for wildcard matching! */
+#define OPAQUE_TYPE_WILDCARD				0
+
+#define OPAQUE_TYPE_RANGE_UNASSIGNED(type) \
+	(  4 <= (type) && (type) <= 127)
+
+#define OPAQUE_TYPE_RANGE_RESERVED(type) \
+	(127 <  (type) && (type) <= 255)
+
+#define VALID_OPAQUE_INFO_LEN(lsahdr) \
+	((ntohs((lsahdr)->length) >= sizeof (struct lsa_header)) && \
+	((ntohs((lsahdr)->length) %  sizeof (u_int32_t)) == 0))
+
+/* Prototypes. */
+struct vty;
+struct stream;
+
+extern void ospf_opaque_init (void);
+extern void ospf_opaque_term (void);
+extern int ospf_opaque_type9_lsa_init (struct ospf_interface *oi);
+extern void ospf_opaque_type9_lsa_term (struct ospf_interface *oi);
+extern int ospf_opaque_type10_lsa_init (struct ospf_area *area);
+extern void ospf_opaque_type10_lsa_term (struct ospf_area *area);
+extern int ospf_opaque_type11_lsa_init (struct ospf *ospf);
+extern void ospf_opaque_type11_lsa_term (struct ospf *ospf);
+
+extern int
+ospf_register_opaque_functab (
+  u_char lsa_type,
+  u_char opaque_type,
+  int (* new_if_hook)(struct interface *ifp),
+  int (* del_if_hook)(struct interface *ifp),
+  void (* ism_change_hook)(struct ospf_interface *oi, int old_status),
+  void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status),
+  void (* config_write_router)(struct vty *vty),
+  void (* config_write_if    )(struct vty *vty, struct interface *ifp),
+  void (* config_write_debug )(struct vty *vty),
+  void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa),
+  int  (* lsa_originator)(void *arg),
+  void (* lsa_refresher )(struct ospf_lsa *lsa),
+  int (* new_lsa_hook)(struct ospf_lsa *lsa),
+  int (* del_lsa_hook)(struct ospf_lsa *lsa)
+);
+extern void ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type);
+
+extern int ospf_opaque_new_if (struct interface *ifp);
+extern int ospf_opaque_del_if (struct interface *ifp);
+extern void ospf_opaque_ism_change (struct ospf_interface *oi, int old_status);
+extern void ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_status);
+extern void ospf_opaque_config_write_router (struct vty *vty, struct ospf *);
+extern void ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp);
+extern void ospf_opaque_config_write_debug (struct vty *vty);
+extern void show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa);
+extern void ospf_opaque_lsa_dump (struct stream *s, u_int16_t length);
+
+extern void ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *init_delay);
+extern struct ospf_lsa *ospf_opaque_lsa_install (struct ospf_lsa *new, int rt_recalc);
+extern void ospf_opaque_lsa_refresh (struct ospf_lsa *lsa);
+
+extern void ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent, u_char lsa_type, u_char opaque_type);
+extern void ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa);
+extern void ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa);
+
+extern void ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, list lsas);
+extern void ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, list lsas);
+extern void ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, list acks);
+
+extern void htonf (float *src, float *dst);
+extern void ntohf (float *src, float *dst);
+extern struct ospf *oi_to_top (struct ospf_interface *oi);
+
+#endif /* _ZEBRA_OSPF_OPAQUE_H */
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
new file mode 100644
index 0000000..2156ce3
--- /dev/null
+++ b/ospfd/ospf_packet.c
@@ -0,0 +1,3243 @@
+/*
+ * OSPF Sending and Receiving OSPF Packets.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "sockunion.h"
+#include "stream.h"
+#include "log.h"
+#include "md5-gnu.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_network.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_dump.h"
+
+static void ospf_ls_ack_send_list (struct ospf_interface *, list,
+				   struct in_addr);
+
+/* Packet Type String. */
+char *ospf_packet_type_str[] =
+{
+  "unknown",
+  "Hello",
+  "Database Description",
+  "Link State Request",
+  "Link State Update",
+  "Link State Acknowledgment",
+};
+
+extern int in_cksum (void *ptr, int nbytes);
+
+/* OSPF authentication checking function */
+int
+ospf_auth_type (struct ospf_interface *oi)
+{
+  int auth_type;
+
+  if (OSPF_IF_PARAM (oi, auth_type) == OSPF_AUTH_NOTSET)
+    auth_type = oi->area->auth_type;
+  else
+    auth_type = OSPF_IF_PARAM (oi, auth_type);
+
+  /* Handle case where MD5 key list is not configured aka Cisco */
+  if (auth_type == OSPF_AUTH_CRYPTOGRAPHIC &&
+      list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
+    return OSPF_AUTH_NULL;
+  
+  return auth_type;
+
+}
+
+/* forward output pointer. */
+void
+ospf_output_forward (struct stream *s, int size)
+{
+  s->putp += size;
+}
+
+struct ospf_packet *
+ospf_packet_new (size_t size)
+{
+  struct ospf_packet *new;
+
+  new = XCALLOC (MTYPE_OSPF_PACKET, sizeof (struct ospf_packet));
+  new->s = stream_new (size);
+
+  return new;
+}
+
+void
+ospf_packet_free (struct ospf_packet *op)
+{
+  if (op->s)
+    stream_free (op->s);
+
+  XFREE (MTYPE_OSPF_PACKET, op);
+
+  op = NULL;
+}
+
+struct ospf_fifo *
+ospf_fifo_new ()
+{
+  struct ospf_fifo *new;
+
+  new = XCALLOC (MTYPE_OSPF_FIFO, sizeof (struct ospf_fifo));
+  return new;
+}
+
+/* Add new packet to fifo. */
+void
+ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
+{
+  if (fifo->tail)
+    fifo->tail->next = op;
+  else
+    fifo->head = op;
+
+  fifo->tail = op;
+
+  fifo->count++;
+}
+
+/* Delete first packet from fifo. */
+struct ospf_packet *
+ospf_fifo_pop (struct ospf_fifo *fifo)
+{
+  struct ospf_packet *op;
+
+  op = fifo->head;
+
+  if (op)
+    {
+      fifo->head = op->next;
+
+      if (fifo->head == NULL)
+	fifo->tail = NULL;
+
+      fifo->count--;
+    }
+
+  return op;
+}
+
+/* Return first fifo entry. */
+struct ospf_packet *
+ospf_fifo_head (struct ospf_fifo *fifo)
+{
+  return fifo->head;
+}
+
+/* Flush ospf packet fifo. */
+void
+ospf_fifo_flush (struct ospf_fifo *fifo)
+{
+  struct ospf_packet *op;
+  struct ospf_packet *next;
+
+  for (op = fifo->head; op; op = next)
+    {
+      next = op->next;
+      ospf_packet_free (op);
+    }
+  fifo->head = fifo->tail = NULL;
+  fifo->count = 0;
+}
+
+/* Free ospf packet fifo. */
+void
+ospf_fifo_free (struct ospf_fifo *fifo)
+{
+  ospf_fifo_flush (fifo);
+
+  XFREE (MTYPE_OSPF_FIFO, fifo);
+}
+
+void
+ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
+{
+  /* Add packet to end of queue. */
+  ospf_fifo_push (oi->obuf, op);
+
+  /* Debug of packet fifo*/
+  /* ospf_fifo_debug (oi->obuf); */
+}
+
+void
+ospf_packet_delete (struct ospf_interface *oi)
+{
+  struct ospf_packet *op;
+  
+  op = ospf_fifo_pop (oi->obuf);
+
+  if (op)
+    ospf_packet_free (op);
+}
+
+struct stream *
+ospf_stream_copy (struct stream *new, struct stream *s)
+{
+  new->endp = s->endp;
+  new->putp = s->putp;
+  new->getp = s->getp;
+
+  memcpy (new->data, s->data, stream_get_endp (s));
+
+  return new;
+}
+
+struct ospf_packet *
+ospf_packet_dup (struct ospf_packet *op)
+{
+  struct ospf_packet *new;
+
+  new = ospf_packet_new (op->length);
+  ospf_stream_copy (new->s, op->s);
+
+  new->dst = op->dst;
+  new->length = op->length;
+
+  return new;
+}
+
+int
+ospf_packet_max (struct ospf_interface *oi)
+{
+  int max;
+
+  if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
+    max = oi->ifp->mtu - OSPF_AUTH_MD5_SIZE - 88;
+  else
+    max = oi->ifp->mtu - 88;
+
+  return max;
+}
+
+
+int
+ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
+                       u_int16_t length)
+{
+  void *ibuf;
+  struct md5_ctx ctx;
+  unsigned char digest[OSPF_AUTH_MD5_SIZE];
+  unsigned char *pdigest;
+  struct crypt_key *ck;
+  struct ospf_header *ospfh;
+  struct ospf_neighbor *nbr;
+  
+
+  ibuf = STREAM_PNT (s);
+  ospfh = (struct ospf_header *) ibuf;
+
+  /* Get pointer to the end of the packet. */
+  pdigest = ibuf + length;
+
+  /* Get secret key. */
+  ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
+			      ospfh->u.crypt.key_id);
+  if (ck == NULL)
+    {
+      zlog_warn ("interface %s: ospf_check_md5 no key %d",
+		 IF_NAME (oi), ospfh->u.crypt.key_id);
+      return 0;
+    }
+
+  /* check crypto seqnum. */
+  nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id);
+
+  if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum))
+    {
+      zlog_warn ("interface %s: ospf_check_md5 bad sequence %d (expect %d)",
+		 IF_NAME (oi),
+		 ntohl(ospfh->u.crypt.crypt_seqnum),
+		 ntohl(nbr->crypt_seqnum));
+      return 0;
+    }
+      
+  /* Generate a digest for the ospf packet - their digest + our digest. */
+  md5_init_ctx (&ctx);
+  md5_process_bytes (ibuf, length, &ctx);
+  md5_process_bytes (ck->auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
+  md5_finish_ctx (&ctx, digest);
+
+  /* compare the two */
+  if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
+    {
+      zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
+		 IF_NAME (oi));
+      return 0;
+    }
+
+  /* save neighbor's crypt_seqnum */
+  if (nbr)
+    nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
+  return 1;
+}
+
+/* This function is called from ospf_write(), it will detect the
+   authentication scheme and if it is MD5, it will change the sequence
+   and update the MD5 digest. */
+int
+ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
+{
+  struct ospf_header *ospfh;
+  unsigned char digest[OSPF_AUTH_MD5_SIZE];
+  struct md5_ctx ctx;
+  void *ibuf;
+  unsigned long oldputp;
+  struct crypt_key *ck;
+  char *auth_key;
+
+  ibuf = STREAM_DATA (op->s);
+  ospfh = (struct ospf_header *) ibuf;
+
+  if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
+    return 0;
+
+  /* We do this here so when we dup a packet, we don't have to
+     waste CPU rewriting other headers. */
+  ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum++);
+
+  /* Get MD5 Authentication key from auth_key list. */
+  if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
+    auth_key = "";
+  else
+    {
+      ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
+      auth_key = ck->auth_key;
+    }
+
+  /* Generate a digest for the entire packet + our secret key. */
+  md5_init_ctx (&ctx);
+  md5_process_bytes (ibuf, ntohs (ospfh->length), &ctx);
+  md5_process_bytes (auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
+  md5_finish_ctx (&ctx, digest);
+
+  /* Append md5 digest to the end of the stream. */
+  oldputp = stream_get_putp (op->s);
+  stream_set_putp (op->s, ntohs (ospfh->length));
+  stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
+  stream_set_putp (op->s, oldputp);
+
+  /* We do *NOT* increment the OSPF header length. */
+  op->length += OSPF_AUTH_MD5_SIZE;
+
+  return OSPF_AUTH_MD5_SIZE;
+}
+
+
+int
+ospf_ls_req_timer (struct thread *thread)
+{
+  struct ospf_neighbor *nbr;
+
+  nbr = THREAD_ARG (thread);
+  nbr->t_ls_req = NULL;
+
+  /* Send Link State Request. */
+  if (ospf_ls_request_count (nbr))
+    ospf_ls_req_send (nbr);
+
+  /* Set Link State Request retransmission timer. */
+  OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
+
+  return 0;
+}
+
+void
+ospf_ls_req_event (struct ospf_neighbor *nbr)
+{
+  if (nbr->t_ls_req)
+    {
+      thread_cancel (nbr->t_ls_req);
+      nbr->t_ls_req = NULL;
+    }
+  nbr->t_ls_req = thread_add_event (master, ospf_ls_req_timer, nbr, 0);
+}
+
+/* Cyclic timer function.  Fist registered in ospf_nbr_new () in
+   ospf_neighbor.c  */
+int
+ospf_ls_upd_timer (struct thread *thread)
+{
+  struct ospf_neighbor *nbr;
+
+  nbr = THREAD_ARG (thread);
+  nbr->t_ls_upd = NULL;
+
+  /* Send Link State Update. */
+  if (ospf_ls_retransmit_count (nbr) > 0)
+    {
+      list update;
+      struct ospf_lsdb *lsdb;
+      int i;
+      struct timeval now;
+      int retransmit_interval;
+
+      gettimeofday (&now, NULL);
+      retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
+
+      lsdb = &nbr->ls_rxmt;
+      update = list_new ();
+
+      for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+	{
+	  struct route_table *table = lsdb->type[i].db;
+	  struct route_node *rn;
+	  
+	  for (rn = route_top (table); rn; rn = route_next (rn))
+	    {
+	      struct ospf_lsa *lsa;
+	      
+	      if ((lsa = rn->info) != NULL)
+		/* Don't retransmit an LSA if we received it within
+		  the last RxmtInterval seconds - this is to allow the
+		  neighbour a chance to acknowledge the LSA as it may
+		  have ben just received before the retransmit timer
+		  fired.  This is a small tweak to what is in the RFC,
+		  but it will cut out out a lot of retransmit traffic
+		  - MAG */
+		if (tv_cmp (tv_sub (now, lsa->tv_recv), 
+			    int2tv (retransmit_interval)) >= 0)
+		  listnode_add (update, rn->info);
+	    }
+	}
+
+      if (listcount (update) > 0)
+	ospf_ls_upd_send (nbr, update, OSPF_SEND_PACKET_DIRECT);
+      list_delete (update);
+    }
+
+  /* Set LS Update retransmission timer. */
+  OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
+
+  return 0;
+}
+
+int
+ospf_ls_ack_timer (struct thread *thread)
+{
+  struct ospf_interface *oi;
+
+  oi = THREAD_ARG (thread);
+  oi->t_ls_ack = NULL;
+
+  /* Send Link State Acknowledgment. */
+  if (listcount (oi->ls_ack) > 0)
+    ospf_ls_ack_send_delayed (oi);
+
+  /* Set LS Ack timer. */
+  OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
+
+  return 0;
+}
+
+int
+ospf_write (struct thread *thread)
+{
+  struct ospf_interface *oi;
+  struct ospf_packet *op;
+  struct sockaddr_in sa_dst;
+  u_char type;
+  int ret;
+  int flags = 0;
+  struct ip iph;
+  struct msghdr msg;
+  struct iovec iov[2];
+  struct ospf *top;
+  listnode node;
+  
+  top = THREAD_ARG (thread);
+  top->t_write = NULL;
+
+  node = listhead (top->oi_write_q);
+  assert (node);
+  oi = getdata (node);
+  assert (oi);
+  
+  /* Get one packet from queue. */
+  op = ospf_fifo_head (oi->obuf);
+  assert (op);
+  assert (op->length >= OSPF_HEADER_SIZE);
+
+  if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS) ||
+      op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
+    ospf_if_ipmulticast (top, oi->address, oi->ifp->ifindex);
+
+  /* Rewrite the md5 signature & update the seq */
+  ospf_make_md5_digest (oi, op);
+
+  memset (&sa_dst, 0, sizeof (sa_dst));
+  sa_dst.sin_family = AF_INET;
+#ifdef HAVE_SIN_LEN
+  sa_dst.sin_len = sizeof(sa_dst);
+#endif /* HAVE_SIN_LEN */
+  sa_dst.sin_addr = op->dst;
+  sa_dst.sin_port = htons (0);
+
+  /* Set DONTROUTE flag if dst is unicast. */
+  if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
+    if (!IN_MULTICAST (htonl (op->dst.s_addr)))
+      flags = MSG_DONTROUTE;
+
+  iph.ip_hl = sizeof (struct ip) >> 2;
+  iph.ip_v = IPVERSION;
+  iph.ip_tos = 0;
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+  iph.ip_len = iph.ip_hl*4 + op->length;
+#else
+  iph.ip_len = htons (iph.ip_hl*4 + op->length);
+#endif
+  iph.ip_id = 0;
+  iph.ip_off = 0;
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+    iph.ip_ttl = OSPF_VL_IP_TTL;
+  else
+    iph.ip_ttl = OSPF_IP_TTL;
+  iph.ip_p = IPPROTO_OSPFIGP;
+  iph.ip_sum = 0;
+  iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
+  iph.ip_dst.s_addr = op->dst.s_addr;
+
+  memset (&msg, 0, sizeof (msg));
+  msg.msg_name = &sa_dst;
+  msg.msg_namelen = sizeof (sa_dst); 
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 2;
+  iov[0].iov_base = (char*)&iph;
+  iov[0].iov_len = iph.ip_hl*4;
+  iov[1].iov_base = STREAM_DATA (op->s);
+  iov[1].iov_len = op->length;
+
+  ret = sendmsg (top->fd, &msg, flags);
+  
+  if (ret < 0)
+    zlog_warn ("*** sendmsg in ospf_write failed with %s", strerror (errno));
+
+  /* Retrieve OSPF packet type. */
+  stream_set_getp (op->s, 1);
+  type = stream_getc (op->s);
+
+  /* Show debug sending packet. */
+  if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
+    {
+      if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
+	{
+	  zlog_info ("-----------------------------------------------------");
+	  stream_set_getp (op->s, 0);
+	  ospf_packet_dump (op->s);
+	}
+
+      zlog_info ("%s sent to [%s] via [%s].",
+		 ospf_packet_type_str[type], inet_ntoa (op->dst),
+		 IF_NAME (oi));
+
+      if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
+	zlog_info ("-----------------------------------------------------");
+    }
+
+  /* Now delete packet from queue. */
+  ospf_packet_delete (oi);
+
+  if (ospf_fifo_head (oi->obuf) == NULL)
+    {
+      oi->on_write_q = 0;
+      list_delete_node (top->oi_write_q, node);
+    }
+  
+  /* If packets still remain in queue, call write thread. */
+  if (!list_isempty (top->oi_write_q))
+    ospf_top->t_write =                                              
+      thread_add_write (master, ospf_write, top, top->fd);
+
+  return 0;
+}
+
+/* OSPF Hello message read -- RFC2328 Section 10.5. */
+void
+ospf_hello (struct ip *iph, struct ospf_header *ospfh,
+	    struct stream * s, struct ospf_interface *oi, int size)
+{
+  struct ospf_hello *hello;
+  struct ospf_neighbor *nbr;
+  struct route_node *rn;
+  struct prefix p, key;
+  int old_state;
+
+  /* increment statistics. */
+  oi->hello_in++;
+
+  hello = (struct ospf_hello *) STREAM_PNT (s);
+
+  /* If Hello is myself, silently discard. */
+  if (IPV4_ADDR_SAME (&ospfh->router_id, &ospf_top->router_id))
+    return;
+
+  /* If incoming interface is passive one, ignore Hello. */
+  if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+    return;
+
+  /* get neighbor prefix. */
+  p.family = AF_INET;
+  p.prefixlen = ip_masklen (hello->network_mask);
+  p.u.prefix4 = iph->ip_src;
+
+  /* Compare network mask. */
+  /* Checking is ignored for Point-to-Point and Virtual link. */
+  if (oi->type != OSPF_IFTYPE_POINTOPOINT 
+      && oi->type != OSPF_IFTYPE_VIRTUALLINK)
+    if (oi->address->prefixlen != p.prefixlen)
+      {
+	zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
+		   inet_ntoa (ospfh->router_id));
+	return;
+      }
+
+  /* Compare Hello Interval. */
+  if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
+    {
+      zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
+		 inet_ntoa (ospfh->router_id));
+      return;
+    }
+
+  /* Compare Router Dead Interval. */
+  if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
+    {
+      zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.",
+		 inet_ntoa (ospfh->router_id));
+      return;
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Packet %s [Hello:RECV]: Options %s",
+	       inet_ntoa (ospfh->router_id),
+	       ospf_options_dump (hello->options));
+
+  /* Compare options. */
+#define REJECT_IF_TBIT_ON	1 /* XXX */
+#ifdef REJECT_IF_TBIT_ON
+  if (CHECK_FLAG (hello->options, OSPF_OPTION_T))
+    {
+      /*
+       * This router does not support non-zero TOS.
+       * Drop this Hello packet not to establish neighbor relationship.
+       */
+      zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.",
+		 inet_ntoa (ospfh->router_id));
+      return;
+    }
+#endif /* REJECT_IF_TBIT_ON */
+
+#ifdef HAVE_OPAQUE_LSA
+  if (CHECK_FLAG (ospf_top->config, OSPF_OPAQUE_CAPABLE)
+      && CHECK_FLAG (hello->options, OSPF_OPTION_O))
+    {
+      /*
+       * This router does know the correct usage of O-bit
+       * the bit should be set in DD packet only.
+       */
+      zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?",
+		 inet_ntoa (ospfh->router_id));
+#ifdef STRICT_OBIT_USAGE_CHECK
+      return;                                     /* Reject this packet. */
+#else /* STRICT_OBIT_USAGE_CHECK */
+      UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */
+#endif /* STRICT_OBIT_USAGE_CHECK */
+    }
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* new for NSSA is to ensure that NP is on and E is off */
+
+#ifdef HAVE_NSSA
+  if (oi->area->external_routing == OSPF_AREA_NSSA) 
+    {
+      if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP)
+	     && CHECK_FLAG (hello->options, OSPF_OPTION_NP)
+	     && ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E)
+	     && ! CHECK_FLAG (hello->options, OSPF_OPTION_E)))
+	{
+	  zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options);
+	  return;
+	}
+      if (IS_DEBUG_OSPF_NSSA)
+        zlog_info ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
+    }
+  else    
+#endif /* HAVE_NSSA */
+    /* The setting of the E-bit found in the Hello Packet's Options
+       field must match this area's ExternalRoutingCapability A
+       mismatch causes processing to stop and the packet to be
+       dropped. The setting of the rest of the bits in the Hello
+       Packet's Options field should be ignored. */
+    if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
+	CHECK_FLAG (hello->options, OSPF_OPTION_E))
+      {
+	zlog_warn ("Packet[Hello:RECV]: my options: %x, his options %x",
+		   OPTIONS (oi), hello->options);
+	return;
+      }
+
+
+  /* Get neighbor information from table. */
+  key.family = AF_INET;
+  key.prefixlen = IPV4_MAX_BITLEN;
+  key.u.prefix4 = iph->ip_src;
+
+  rn = route_node_get (oi->nbrs, &key);
+  if (rn->info)
+    {
+      route_unlock_node (rn);
+      nbr = rn->info;
+
+      if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt)
+	{
+	  nbr->src = iph->ip_src;
+	  nbr->address = p;
+	}
+    }
+  else
+    {
+      /* Create new OSPF Neighbor structure. */
+      nbr = ospf_nbr_new (oi);
+      nbr->state = NSM_Down;
+      nbr->src = iph->ip_src;
+      nbr->address = p;
+
+      rn->info = nbr;
+
+      nbr->nbr_nbma = NULL;
+
+      if (oi->type == OSPF_IFTYPE_NBMA)
+	{
+	  struct ospf_nbr_nbma *nbr_nbma;
+	  listnode node;
+
+	  for (node = listhead (oi->nbr_nbma); node; nextnode (node))
+	    {
+	      nbr_nbma = getdata (node);
+	      assert (nbr_nbma);
+      
+	      if (IPV4_ADDR_SAME(&nbr_nbma->addr, &iph->ip_src))
+		{
+		  nbr_nbma->nbr = nbr;
+		  nbr->nbr_nbma = nbr_nbma;
+
+		  if (nbr_nbma->t_poll)
+		    OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
+		  
+		  nbr->state_change = nbr_nbma->state_change + 1;
+		}
+	    }
+	}
+      
+      /* New nbr, save the crypto sequence number if necessary */
+      if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC)
+	nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("NSM[%s:%s]: start", IF_NAME (nbr->oi),
+		   inet_ntoa (nbr->router_id));
+    }
+  
+  nbr->router_id = ospfh->router_id;
+
+  old_state = nbr->state;
+
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
+
+  /*  RFC2328  Section 9.5.1
+      If the router is not eligible to become Designated Router,
+      (snip)   It	must also send an Hello	Packet in reply	to an
+      Hello Packet received from any eligible neighbor (other than
+      the	current	Designated Router and Backup Designated	Router).  */
+  if (oi->type == OSPF_IFTYPE_NBMA)
+    if (PRIORITY(oi) == 0 && hello->priority > 0
+	&& IPV4_ADDR_CMP(&DR(oi),  &iph->ip_src)
+	&& IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src))
+      OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer,
+			 OSPF_HELLO_REPLY_DELAY);
+
+  /* on NBMA network type, it happens to receive bidirectional Hello packet
+     without advance 1-Way Received event.
+     To avoid incorrect DR-seletion, raise 1-Way Received event.*/
+  if (oi->type == OSPF_IFTYPE_NBMA &&
+      (old_state == NSM_Down || old_state == NSM_Attempt))
+    {
+      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+      nbr->priority = hello->priority;
+      nbr->d_router = hello->d_router;
+      nbr->bd_router = hello->bd_router;
+      return;
+    }
+
+  if (ospf_nbr_bidirectional (&ospf_top->router_id, hello->neighbors,
+			      size - OSPF_HELLO_MIN_SIZE))
+    {
+      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
+      nbr->options |= hello->options;
+    }
+  else
+    {
+      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+      /* Set neighbor information. */
+      nbr->priority = hello->priority;
+      nbr->d_router = hello->d_router;
+      nbr->bd_router = hello->bd_router;
+      return;
+    }
+
+  /* If neighbor itself declares DR and no BDR exists,
+     cause event BackupSeen */
+  if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router))
+    if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting)
+      OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
+
+  /* neighbor itself declares BDR. */
+  if (oi->state == ISM_Waiting &&
+      IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router))
+    OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
+
+  /* had not previously. */
+  if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) &&
+       IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) ||
+      (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) &&
+       IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router)))
+    OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+
+  /* had not previously. */
+  if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) &&
+       IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) ||
+      (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) &&
+       IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)))
+    OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+
+  /* Neighbor priority check. */
+  if (nbr->priority >= 0 && nbr->priority != hello->priority)
+    OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+
+  /* Set neighbor information. */
+  nbr->priority = hello->priority;
+  nbr->d_router = hello->d_router;
+  nbr->bd_router = hello->bd_router;
+}
+
+/* Save DD flags/options/Seqnum received. */
+void
+ospf_db_desc_save_current (struct ospf_neighbor *nbr,
+			   struct ospf_db_desc *dd)
+{
+  nbr->last_recv.flags = dd->flags;
+  nbr->last_recv.options = dd->options;
+  nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum);
+}
+
+/* Process rest of DD packet. */
+static void
+ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
+		   struct ospf_neighbor *nbr, struct ospf_db_desc *dd,
+		   u_int16_t size)
+{
+  struct ospf_lsa *new, *find;
+  struct lsa_header *lsah;
+
+  stream_forward (s, OSPF_DB_DESC_MIN_SIZE);
+  for (size -= OSPF_DB_DESC_MIN_SIZE;
+       size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE) 
+    {
+      lsah = (struct lsa_header *) STREAM_PNT (s);
+      stream_forward (s, OSPF_LSA_HEADER_SIZE);
+
+      /* Unknown LS type. */
+      if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
+	{
+	  zlog_warn ("Pakcet [DD:RECV]: Unknown LS type %d.", lsah->type);
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+	  return;
+	}
+
+#ifdef HAVE_OPAQUE_LSA
+      if (IS_OPAQUE_LSA (lsah->type)
+      &&  ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))
+        {
+          zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
+          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+          return;
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      switch (lsah->type)
+        {
+        case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+	case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+#ifdef HAVE_NSSA
+          /* Check for stub area.  Reject if AS-External from stub but
+             allow if from NSSA. */
+          if (oi->area->external_routing == OSPF_AREA_STUB)
+#else /* ! HAVE_NSSA */
+          if (oi->area->external_routing != OSPF_AREA_DEFAULT)
+#endif /* HAVE_NSSA */
+            {
+              zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.",
+                         lsah->type, inet_ntoa (lsah->id),
+                         (oi->area->external_routing == OSPF_AREA_STUB) ?\
+                         "STUB" : "NSSA");
+              OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+              return;
+            }
+          break;
+	default:
+	  break;
+        }
+
+      /* Create LS-request object. */
+      new = ospf_ls_request_new (lsah);
+
+      /* Lookup received LSA, then add LS request list. */
+      find = ospf_lsa_lookup_by_header (oi->area, lsah);
+      if (!find || ospf_lsa_more_recent (find, new) < 0)
+	{
+	  ospf_ls_request_add (nbr, new);
+	  ospf_lsa_discard (new);
+	}
+      else
+	{
+	  /* Received LSA is not recent. */
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("Packet [DD:RECV]: LSA received Type %d, "
+		       "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
+	  ospf_lsa_discard (new);
+	  continue;
+	}
+    }
+
+  /* Master */
+  if (IS_SET_DD_MS (nbr->dd_flags))
+    {
+      nbr->dd_seqnum++;
+      /* Entire DD packet sent. */
+      if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
+	OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
+      else
+	/* Send new DD packet. */
+	ospf_db_desc_send (nbr);
+    }
+  /* Slave */
+  else
+    {
+      nbr->dd_seqnum = ntohl (dd->dd_seqnum);
+
+      /* When master's more flags is not set. */
+      if (!IS_SET_DD_M (dd->flags) && ospf_db_summary_isempty (nbr))
+	{
+	  nbr->dd_flags &= ~(OSPF_DD_FLAG_M);
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
+	}
+
+      /* Send DD pakcet in reply. */
+      ospf_db_desc_send (nbr);
+    }
+
+  /* Save received neighbor values from DD. */
+  ospf_db_desc_save_current (nbr, dd);
+}
+
+int
+ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
+{
+  /* Is DD duplicated? */
+  if (dd->options == nbr->last_recv.options &&
+      dd->flags == nbr->last_recv.flags &&
+      dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum))
+    return 1;
+
+  return 0;
+}
+
+/* OSPF Database Description message read -- RFC2328 Section 10.6. */
+void
+ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
+	      struct stream *s, struct ospf_interface *oi, u_int16_t size)
+{
+  struct ospf_db_desc *dd;
+  struct ospf_neighbor *nbr;
+
+  /* Increment statistics. */
+  oi->db_desc_in++;
+
+  dd = (struct ospf_db_desc *) STREAM_PNT (s);
+
+  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+  if (nbr == NULL)
+    {
+      zlog_warn ("Packet[DD]: Unknown Neighbor %s",
+		 inet_ntoa (ospfh->router_id));
+      return;
+    }
+
+  /* Check MTU. */
+  if (ntohs (dd->mtu) > oi->ifp->mtu)
+    {
+      zlog_warn ("Packet[DD]: MTU is larger than [%s]'s MTU", IF_NAME (oi));
+      return;
+    }
+
+#ifdef REJECT_IF_TBIT_ON
+  if (CHECK_FLAG (dd->options, OSPF_OPTION_T))
+    {
+      /*
+       * In Hello protocol, optional capability must have checked
+       * to prevent this T-bit enabled router be my neighbor.
+       */
+      zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id));
+      return;
+    }
+#endif /* REJECT_IF_TBIT_ON */
+
+#ifdef HAVE_OPAQUE_LSA
+  if (CHECK_FLAG (dd->options, OSPF_OPTION_O)
+      && !CHECK_FLAG (ospf_top->config, OSPF_OPAQUE_CAPABLE))
+    {
+      /*
+       * This node is not configured to handle O-bit, for now.
+       * Clear it to ignore unsupported capability proposed by neighbor.
+       */
+      UNSET_FLAG (dd->options, OSPF_OPTION_O);
+    }
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* Process DD packet by neighbor status. */
+  switch (nbr->state)
+    {
+    case NSM_Down:
+    case NSM_Attempt:
+    case NSM_TwoWay:
+      zlog_warn ("Packet[DD]: Neighbor state is %s, packet discarded.",
+		 LOOKUP (ospf_nsm_state_msg, nbr->state));
+      break;
+    case NSM_Init:
+      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
+      /* If the new state is ExStart, the processing of the current
+	 packet should then continue in this new state by falling
+	 through to case ExStart below.  */
+      if (nbr->state != NSM_ExStart)
+	break;
+    case NSM_ExStart:
+      /* Initial DBD */
+      if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) &&
+	  (size == OSPF_DB_DESC_MIN_SIZE))
+	{
+	  if (IPV4_ADDR_CMP (&nbr->router_id, &ospf_top->router_id) > 0)
+	    {
+	      /* We're Slave---obey */
+	      zlog_warn ("Packet[DD]: Negotiation done (Slave).");
+	      nbr->dd_seqnum = ntohl (dd->dd_seqnum);
+	      nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */
+	    }
+	  else
+	    {
+	      /* We're Master, ignore the initial DBD from Slave */
+	      zlog_warn ("Packet[DD]: Initial DBD from Slave, ignoring.");
+	      break;
+	    }
+	}
+      /* Ack from the Slave */
+      else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) &&
+	       ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
+	       IPV4_ADDR_CMP (&nbr->router_id, &ospf_top->router_id) < 0)
+	{
+	  zlog_warn ("Packet[DD]: Negotiation done (Master).");
+	  nbr->dd_flags &= ~OSPF_DD_FLAG_I;
+	}
+      else
+	{
+	  zlog_warn ("Packet[DD]: Negotiation fails.");
+	  break;
+	}
+      
+      /* This is where the real Options are saved */
+      nbr->options = dd->options;
+
+#ifdef HAVE_OPAQUE_LSA
+      if (CHECK_FLAG (ospf_top->config, OSPF_OPAQUE_CAPABLE))
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_info ("Neighbor[%s] is %sOpaque-capable.",
+		       inet_ntoa (nbr->router_id),
+		       CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
+
+          if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
+          &&  IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
+            {
+              zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; Opaque-LSAs cannot be reliably advertised in this network.", inet_ntoa (nbr->router_id));
+              /* This situation is undesirable, but not a real error. */
+            }
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);
+
+      /* continue processing rest of packet. */
+      ospf_db_desc_proc (s, oi, nbr, dd, size);
+      break;
+    case NSM_Exchange:
+      if (ospf_db_desc_is_dup (dd, nbr))
+	{
+	  if (IS_SET_DD_MS (nbr->dd_flags))
+	    /* Master: discard duplicated DD packet. */
+	    zlog_warn ("Packet[DD] (Master): packet duplicated.");
+	  else
+	    /* Slave: cause to retransmit the last Database Description. */
+	    {
+	      zlog_warn ("Packet[DD] [Slave]: packet duplicated.");
+	      ospf_db_desc_resend (nbr);
+	    }
+	  break;
+	}
+
+      /* Otherwise DD packet should be checked. */
+      /* Check Master/Slave bit mismatch */
+      if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
+	{
+	  zlog_warn ("Packet[DD]: MS-bit mismatch.");
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
+		       dd->flags, nbr->dd_flags);
+	  break;
+	}
+
+      /* Check initialize bit is set. */
+      if (IS_SET_DD_I (dd->flags))
+	{
+	  zlog_warn ("Packet[DD]: I-bit set.");
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+	  break;
+	}
+
+      /* Check DD Options. */
+      if (dd->options != nbr->options)
+	{
+#ifdef ORIGINAL_CODING
+	  /* Save the new options for debugging */
+	  nbr->options = dd->options;
+#endif /* ORIGINAL_CODING */
+	  zlog_warn ("Packet[DD]: options mismatch.");
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+	  break;
+	}
+
+      /* Check DD sequence number. */
+      if ((IS_SET_DD_MS (nbr->dd_flags) &&
+	   ntohl (dd->dd_seqnum) != nbr->dd_seqnum) ||
+	  (!IS_SET_DD_MS (nbr->dd_flags) &&
+	   ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
+	{
+	  zlog_warn ("Pakcet[DD]: sequence number mismatch.");
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+	  break;
+	}
+
+      /* Continue processing rest of packet. */
+      ospf_db_desc_proc (s, oi, nbr, dd, size);
+      break;
+    case NSM_Loading:
+    case NSM_Full:
+      if (ospf_db_desc_is_dup (dd, nbr))
+	{
+	  if (IS_SET_DD_MS (nbr->dd_flags))
+	    {
+	      /* Master should discard duplicate DD packet. */
+	      zlog_warn ("Pakcet[DD]: duplicated, packet discarded.");
+	      break;
+	    }
+	  else
+	    {
+	      struct timeval t, now;
+	      gettimeofday (&now, NULL);
+	      t = tv_sub (now, nbr->last_send_ts);
+	      if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
+		{
+		  /* In states Loading and Full the slave must resend
+		     its last Database Description packet in response to
+		     duplicate Database Description packets received
+		     from the master.  For this reason the slave must
+		     wait RouterDeadInterval seconds before freeing the
+		     last Database Description packet.  Reception of a
+		     Database Description packet from the master after
+		     this interval will generate a SeqNumberMismatch
+		     neighbor event. RFC2328 Section 10.8 */
+		  ospf_db_desc_resend (nbr);
+		  break;
+		}
+	    }
+	}
+
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+      break;
+    default:
+      zlog_warn ("Packet[DD]: NSM illegal status.");
+      break;
+    }
+}
+
+#define OSPF_LSA_KEY_SIZE       12 /* type(4) + id(4) + ar(4) */
+
+/* OSPF Link State Request Read -- RFC2328 Section 10.7. */
+void
+ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
+	     struct stream *s, struct ospf_interface *oi, u_int16_t size)
+{
+  struct ospf_neighbor *nbr;
+  u_int32_t ls_type;
+  struct in_addr ls_id;
+  struct in_addr adv_router;
+  struct ospf_lsa *find;
+  list ls_upd;
+  int length;
+
+  /* Increment statistics. */
+  oi->ls_req_in++;
+
+  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+  if (nbr == NULL)
+    {
+      zlog_warn ("Link State Request: Unknown Neighbor %s.",
+		 inet_ntoa (ospfh->router_id));
+      return;
+    }
+
+  /* Neighbor State should be Exchange or later. */
+  if (nbr->state != NSM_Exchange &&
+      nbr->state != NSM_Loading &&
+      nbr->state != NSM_Full)
+    {
+      zlog_warn ("Link State Request: Neighbor state is %s, packet discarded.",
+		 LOOKUP (ospf_nsm_state_msg, nbr->state));
+      return;
+    }
+
+  /* Send Link State Update for ALL requested LSAs. */
+  ls_upd = list_new ();
+  length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
+
+  while (size >= OSPF_LSA_KEY_SIZE)
+    {
+      /* Get one slice of Link State Request. */
+      ls_type = stream_getl (s);
+      ls_id.s_addr = stream_get_ipv4 (s);
+      adv_router.s_addr = stream_get_ipv4 (s);
+
+      /* Verify LSA type. */
+      if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA)
+	{
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
+	  list_delete (ls_upd);
+	  return;
+	}
+
+      /* Search proper LSA in LSDB. */
+      find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router);
+      if (find == NULL)
+	{
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
+	  list_delete (ls_upd);
+	  return;
+	}
+
+      /* Packet overflows MTU size, send immediatly. */
+      if (length + ntohs (find->data->length) > OSPF_PACKET_MAX (oi))
+	{
+	  if (oi->type == OSPF_IFTYPE_NBMA)
+	    ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
+	  else
+	    ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
+
+	  /* Only remove list contents.  Keep ls_upd. */
+	  list_delete_all_node (ls_upd);
+
+	  length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
+	}
+
+      /* Append LSA to update list. */
+      listnode_add (ls_upd, find);
+      length += ntohs (find->data->length);
+
+      size -= OSPF_LSA_KEY_SIZE;
+    }
+
+  /* Send rest of Link State Update. */
+  if (listcount (ls_upd) > 0)
+    {
+      if (oi->type == OSPF_IFTYPE_NBMA)
+	ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
+      else
+	ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
+
+      list_delete (ls_upd);
+    }
+  else
+    list_free (ls_upd);
+}
+
+/* Get the list of LSAs from Link State Update packet.
+   And process some validation -- RFC2328 Section 13. (1)-(2). */
+static list
+ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
+                      struct ospf_interface *oi, size_t size)
+{
+  u_int16_t count, sum;
+  u_int32_t length;
+  struct lsa_header *lsah;
+  struct ospf_lsa *lsa;
+  list lsas;
+
+  lsas = list_new ();
+
+  count = stream_getl (s);
+  size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
+
+  for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
+       size -= length, stream_forward (s, length), count--)
+    {
+      lsah = (struct lsa_header *) STREAM_PNT (s);
+      length = ntohs (lsah->length);
+
+      if (length > size)
+	{
+	  zlog_warn ("Link State Update: LSA length exceeds packet size.");
+	  break;
+	}
+
+      /* Validate the LSA's LS checksum. */
+      sum = lsah->checksum;
+      if (sum != ospf_lsa_checksum (lsah))
+	{
+	  zlog_warn ("Link State Update: LSA checksum error %x, %x.",
+		     sum, lsah->checksum);
+	  continue;
+	}
+
+      /* Examine the LSA's LS type. */
+      if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
+	{
+	  zlog_warn ("Link State Update: Unknown LS type %d", lsah->type);
+	  continue;
+	}
+
+      /*
+       * What if the received LSA's age is greater than MaxAge?
+       * Treat it as a MaxAge case -- endo.
+       */
+      if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)
+        lsah->ls_age = htons (OSPF_LSA_MAXAGE);
+
+#ifdef HAVE_OPAQUE_LSA
+      if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
+        {
+#ifdef STRICT_OBIT_USAGE_CHECK
+	  if ((IS_OPAQUE_LSA(lsah->type) &&
+               ! CHECK_FLAG (lsah->options, OSPF_OPTION_O))
+	  ||  (! IS_OPAQUE_LSA(lsah->type) &&
+               CHECK_FLAG (lsah->options, OSPF_OPTION_O)))
+            {
+              /*
+               * This neighbor must know the exact usage of O-bit;
+               * the bit will be set in Type-9,10,11 LSAs only.
+               */
+              zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id));
+              continue;
+            }
+#endif /* STRICT_OBIT_USAGE_CHECK */
+
+          /* Do not take in AS External Opaque-LSAs if we are a stub. */
+          if (lsah->type == OSPF_OPAQUE_AS_LSA
+	      && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) 
+            {
+              if (IS_DEBUG_OSPF_EVENT)
+                zlog_info ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
+              continue;
+            }
+        }
+      else if (IS_OPAQUE_LSA(lsah->type))
+        {
+          zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
+          continue;
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      /* Create OSPF LSA instance. */
+      lsa = ospf_lsa_new ();
+
+      /* We may wish to put some error checking if type NSSA comes in
+         and area not in NSSA mode */
+      switch (lsah->type)
+        {
+        case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+        case OSPF_OPAQUE_AS_LSA:
+          lsa->area = NULL;
+          break;
+        case OSPF_OPAQUE_LINK_LSA:
+          lsa->oi = oi; /* Remember incoming interface for flooding control. */
+          /* Fallthrough */
+#endif /* HAVE_OPAQUE_LSA */
+        default:
+          lsa->area = oi->area;
+          break;
+        }
+
+      lsa->data = ospf_lsa_data_new (length);
+      memcpy (lsa->data, lsah, length);
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info("LSA[Type%d:%s]: %p new LSA created with Link State Update",
+		  lsa->data->type, inet_ntoa (lsa->data->id), lsa);
+      listnode_add (lsas, lsa);
+    }
+
+  return lsas;
+}
+
+/* Cleanup Update list. */
+void
+ospf_upd_list_clean (list lsas)
+{
+  listnode node;
+  struct ospf_lsa *lsa;
+
+  for (node = listhead (lsas); node; nextnode (node))
+    if ((lsa = getdata (node)) != NULL)
+      ospf_lsa_discard (lsa);
+
+  list_delete (lsas);
+}
+
+/* OSPF Link State Update message read -- RFC2328 Section 13. */
+void
+ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
+	     struct stream *s, struct ospf_interface *oi, u_int16_t size)
+{
+  struct ospf_neighbor *nbr;
+  list lsas;
+#ifdef HAVE_OPAQUE_LSA
+  list mylsa_acks, mylsa_upds;
+#endif /* HAVE_OPAQUE_LSA */
+  listnode node, next;
+  struct ospf_lsa *lsa = NULL;
+  /* unsigned long ls_req_found = 0; */
+
+  /* Dis-assemble the stream, update each entry, re-encapsulate for flooding */
+
+  /* Increment statistics. */
+  oi->ls_upd_in++;
+
+  /* Check neighbor. */
+  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+  if (nbr == NULL)
+    {
+      zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",
+		 inet_ntoa (ospfh->router_id), IF_NAME (oi));
+      return;
+    }
+
+  /* Check neighbor state. */
+  if (nbr->state < NSM_Exchange)
+    {
+      zlog_warn ("Link State Update: Neighbor[%s] state is less than Exchange",
+		 inet_ntoa (ospfh->router_id));
+      return;
+    }
+
+  /* Get list of LSAs from Link State Update packet. - Also perorms Stages 
+   * 1 (validate LSA checksum) and 2 (check for LSA consistent type) 
+   * of section 13. 
+   */
+  lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
+
+#ifdef HAVE_OPAQUE_LSA
+  /*
+   * Prepare two kinds of lists to clean up unwanted self-originated
+   * Opaque-LSAs from the routing domain as soon as possible.
+   */
+  mylsa_acks = list_new (); /* Let the sender cease retransmission. */
+  mylsa_upds = list_new (); /* Flush target LSAs if necessary. */
+
+  /*
+   * If self-originated Opaque-LSAs that have flooded before restart
+   * are contained in the received LSUpd message, corresponding LSReq
+   * messages to be sent may have to be modified.
+   * To eliminate possible race conditions such that flushing and normal
+   * updating for the same LSA would take place alternately, this trick
+   * must be done before entering to the loop below.
+   */
+   ospf_opaque_adjust_lsreq (nbr, lsas);
+#endif /* HAVE_OPAQUE_LSA */
+
+#define DISCARD_LSA(L,N) {\
+        if (IS_DEBUG_OSPF_EVENT) \
+          zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
+        ospf_lsa_discard (L); \
+	continue; }
+
+  /* Process each LSA received in the one packet. */
+  for (node = listhead (lsas); node; node = next)
+    {
+      struct ospf_lsa *ls_ret, *current;
+      int ret = 1;
+
+      next = node->next;
+
+      lsa = getdata (node);
+
+#ifdef HAVE_NSSA
+      if (IS_DEBUG_OSPF_NSSA)
+	{
+	  char buf1[INET_ADDRSTRLEN];
+	  char buf2[INET_ADDRSTRLEN];
+	  char buf3[INET_ADDRSTRLEN];
+
+	  zlog_info("LSA Type-%d from %s, ID: %s, ADV: %s",
+		  lsa->data->type,
+		  inet_ntop (AF_INET, &ospfh->router_id,
+			     buf1, INET_ADDRSTRLEN),
+		  inet_ntop (AF_INET, &lsa->data->id,
+			     buf2, INET_ADDRSTRLEN),
+		  inet_ntop (AF_INET, &lsa->data->adv_router,
+			     buf3, INET_ADDRSTRLEN));
+	}
+#endif /* HAVE_NSSA */
+
+      listnode_delete (lsas, lsa); /* We don't need it in list anymore */
+
+      /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */
+
+      /* LSA Type  - Done above by ospf_ls_upd_list_lsa() */
+   
+      /* Do not take in AS External LSAs if we are a stub or NSSA. */
+
+      /* Do not take in AS NSSA if this neighbor and we are not NSSA */
+
+      /* Do take in Type-7's if we are an NSSA  */ 
+ 
+      /* If we are also an ABR, later translate them to a Type-5 packet */
+ 
+      /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will
+	 translate them to a separate Type-5 packet.  */
+
+      if (lsa->data->type == OSPF_AS_EXTERNAL_LSA)
+        /* Reject from STUB or NSSA */
+        if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) 
+	  {
+	    DISCARD_LSA (lsa, 1);
+#ifdef HAVE_NSSA
+	    if (IS_DEBUG_OSPF_NSSA)
+	      zlog_info("Incoming External LSA Discarded: We are NSSA/STUB Area");
+#endif /* HAVE_NSSA */
+	  }
+
+#ifdef  HAVE_NSSA 
+      if (lsa->data->type == OSPF_AS_NSSA_LSA)
+	if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
+	  {
+	    DISCARD_LSA (lsa,2);
+	    if (IS_DEBUG_OSPF_NSSA)
+	      zlog_info("Incoming NSSA LSA Discarded:  Not NSSA Area");
+	  }
+#endif /* HAVE_NSSA */
+
+      /* Find the LSA in the current database. */
+
+      current = ospf_lsa_lookup_by_header (oi->area, lsa->data);
+
+      /* If the LSA's LS age is equal to MaxAge, and there is currently
+	 no instance of the LSA in the router's link state database,
+	 and none of router's neighbors are in states Exchange or Loading,
+	 then take the following actions. */
+
+      if (IS_LSA_MAXAGE (lsa) && !current &&
+	  (ospf_nbr_count (oi->nbrs, NSM_Exchange) +
+	   ospf_nbr_count (oi->nbrs, NSM_Loading)) == 0)
+	{
+	  /* Response Link State Acknowledgment. */
+	  ospf_ls_ack_send (nbr, lsa);
+
+	  /* Discard LSA. */	  
+	  zlog_warn ("Link State Update: LS age is equal to MaxAge.");
+          DISCARD_LSA (lsa, 3);
+	}
+
+#ifdef HAVE_OPAQUE_LSA
+      if (IS_OPAQUE_LSA (lsa->data->type)
+      &&  IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf_top->router_id))
+        {
+          /*
+           * Even if initial flushing seems to be completed, there might
+           * be a case that self-originated LSA with MaxAge still remain
+           * in the routing domain.
+           * Just send an LSAck message to cease retransmission.
+           */
+          if (IS_LSA_MAXAGE (lsa))
+            {
+              zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa));
+              ospf_ls_ack_send (nbr, lsa);
+              ospf_lsa_discard (lsa);
+
+              if (current != NULL && ! IS_LSA_MAXAGE (current))
+                ospf_opaque_lsa_refresh_schedule (current);
+              continue;
+            }
+
+          /*
+           * If an instance of self-originated Opaque-LSA is not found
+           * in the LSDB, there are some possible cases here.
+           *
+           * 1) This node lost opaque-capability after restart.
+           * 2) Else, a part of opaque-type is no more supported.
+           * 3) Else, a part of opaque-id is no more supported.
+           *
+           * Anyway, it is still this node's responsibility to flush it.
+           * Otherwise, the LSA instance remains in the routing domain
+           * until its age reaches to MaxAge.
+           */
+          if (current == NULL)
+            {
+              if (IS_DEBUG_OSPF_EVENT)
+                zlog_info ("LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key (lsa));
+
+              SET_FLAG (lsa->flags, OSPF_LSA_SELF);
+              listnode_add (mylsa_upds, ospf_lsa_dup  (lsa));
+              listnode_add (mylsa_acks, ospf_lsa_lock (lsa));
+              continue;
+            }
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      /* (5) Find the instance of this LSA that is currently contained
+	 in the router's link state database.  If there is no
+	 database copy, or the received LSA is more recent than
+	 the database copy the following steps must be performed. */
+
+      if (current == NULL ||
+	  (ret = ospf_lsa_more_recent (current, lsa)) < 0)
+	{
+	  /* Actual flooding procedure. */
+	  if (ospf_flood (nbr, current, lsa) < 0)  /* Trap NSSA later. */
+	    DISCARD_LSA (lsa, 4);
+	  continue;
+	}
+
+      /* (6) Else, If there is an instance of the LSA on the sending
+	 neighbor's Link state request list, an error has occurred in
+	 the Database Exchange process.  In this case, restart the
+	 Database Exchange process by generating the neighbor event
+	 BadLSReq for the sending neighbor and stop processing the
+	 Link State Update packet. */
+
+      if (ospf_ls_request_lookup (nbr, lsa))
+	{
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
+	  zlog_warn ("LSA instance exists on Link state request list");
+
+	  /* Clean list of LSAs. */
+          ospf_upd_list_clean (lsas);
+	  /* this lsa is not on lsas list already. */
+	  ospf_lsa_discard (lsa);
+#ifdef HAVE_OPAQUE_LSA
+          list_delete (mylsa_acks);
+          list_delete (mylsa_upds);
+#endif /* HAVE_OPAQUE_LSA */
+	  return;
+	}
+
+      /* If the received LSA is the same instance as the database copy
+	 (i.e., neither one is more recent) the following two steps
+	 should be performed: */
+
+      if (ret == 0)
+	{
+	  /* If the LSA is listed in the Link state retransmission list
+	     for the receiving adjacency, the router itself is expecting
+	     an acknowledgment for this LSA.  The router should treat the
+	     received LSA as an acknowledgment by removing the LSA from
+	     the Link state retransmission list.  This is termed an
+	     "implied acknowledgment". */
+
+	  ls_ret = ospf_ls_retransmit_lookup (nbr, lsa);
+
+	  if (ls_ret != NULL)
+	    {
+	      ospf_ls_retransmit_delete (nbr, ls_ret);
+
+	      /* Delayed acknowledgment sent if advertisement received
+		 from Designated Router, otherwise do nothing. */
+	      if (oi->state == ISM_Backup)
+		if (NBR_IS_DR (nbr))
+		  listnode_add (oi->ls_ack, ospf_lsa_lock (lsa));
+
+              DISCARD_LSA (lsa, 5);
+	    }
+	  else
+	    /* Acknowledge the receipt of the LSA by sending a
+	       Link State Acknowledgment packet back out the receiving
+	       interface. */
+	    {
+	      ospf_ls_ack_send (nbr, lsa);
+	      DISCARD_LSA (lsa, 6);
+	    }
+	}
+
+      /* The database copy is more recent.  If the database copy
+	 has LS age equal to MaxAge and LS sequence number equal to
+	 MaxSequenceNumber, simply discard the received LSA without
+	 acknowledging it. (In this case, the LSA's LS sequence number is
+	 wrapping, and the MaxSequenceNumber LSA must be completely
+	 flushed before any new LSA instance can be introduced). */
+
+      else if (ret > 0)  /* Database copy is more recent */
+	{ 
+	  if (IS_LSA_MAXAGE (current) &&
+	      current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
+	    {
+	      DISCARD_LSA (lsa, 7);
+	    }
+	  /* Otherwise, as long as the database copy has not been sent in a
+	     Link State Update within the last MinLSArrival seconds, send the
+	     database copy back to the sending neighbor, encapsulated within
+	     a Link State Update Packet. The Link State Update Packet should
+	     be sent directly to the neighbor. In so doing, do not put the
+	     database copy of the LSA on the neighbor's link state
+	     retransmission list, and do not acknowledge the received (less
+	     recent) LSA instance. */
+	  else
+	    {
+	      struct timeval now;
+	      
+	      gettimeofday (&now, NULL);
+	      
+	      if (tv_cmp (tv_sub (now, current->tv_orig), 
+			  int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
+		/* Trap NSSA type later.*/
+		ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
+	      DISCARD_LSA (lsa, 8);
+	    }
+	}
+    }
+  
+#ifdef HAVE_OPAQUE_LSA
+  /*
+   * Now that previously originated Opaque-LSAs those which not yet
+   * installed into LSDB are captured, take several steps to clear
+   * them completely from the routing domain, before proceeding to
+   * origination for the current target Opaque-LSAs.
+   */
+  while (listcount (mylsa_acks) > 0)
+    ospf_ls_ack_send_list (oi, mylsa_acks, nbr->address.u.prefix4);
+
+  if (listcount (mylsa_upds) > 0)
+    ospf_opaque_self_originated_lsa_received (nbr, mylsa_upds);
+
+  list_delete (mylsa_upds);
+#endif /* HAVE_OPAQUE_LSA */
+
+  assert (listcount (lsas) == 0);
+  list_delete (lsas);
+}
+
+/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
+void
+ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
+	     struct stream *s, struct ospf_interface *oi, u_int16_t size)
+{
+  struct ospf_neighbor *nbr;
+#ifdef HAVE_OPAQUE_LSA
+  list opaque_acks;
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* increment statistics. */
+  oi->ls_ack_in++;
+
+  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+  if (nbr == NULL)
+    {
+      zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",
+		 inet_ntoa (ospfh->router_id));
+      return;
+    }
+
+  if (nbr->state < NSM_Exchange)
+    {
+      zlog_warn ("Link State Acknowledgment: State is less than Exchange.");
+      return;
+    }
+
+#ifdef HAVE_OPAQUE_LSA
+  opaque_acks = list_new ();
+#endif /* HAVE_OPAQUE_LSA */
+
+  while (size >= OSPF_LSA_HEADER_SIZE)
+    {
+      struct ospf_lsa *lsa, *lsr;
+
+      lsa = ospf_lsa_new ();
+      lsa->data = (struct lsa_header *) STREAM_PNT (s);
+
+      /* lsah = (struct lsa_header *) STREAM_PNT (s); */
+      size -= OSPF_LSA_HEADER_SIZE;
+      stream_forward (s, OSPF_LSA_HEADER_SIZE);
+
+      if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
+	{
+	  lsa->data = NULL;
+	  ospf_lsa_discard (lsa);
+	  continue;
+	}
+
+      lsr = ospf_ls_retransmit_lookup (nbr, lsa);
+
+      if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
+        {
+#ifdef HAVE_OPAQUE_LSA
+          /* Keep this LSA entry for later reference. */
+          if (IS_OPAQUE_LSA (lsr->data->type))
+            listnode_add (opaque_acks, ospf_lsa_dup (lsr));
+#endif /* HAVE_OPAQUE_LSA */
+
+          ospf_ls_retransmit_delete (nbr, lsr);
+        }
+
+      lsa->data = NULL;
+      ospf_lsa_discard (lsa);
+    }
+
+#ifdef HAVE_OPAQUE_LSA
+  if (listcount (opaque_acks) > 0)
+    ospf_opaque_ls_ack_received (nbr, opaque_acks);
+
+  list_delete (opaque_acks);
+  return;
+#endif /* HAVE_OPAQUE_LSA */
+}
+
+struct stream *
+ospf_recv_packet (int fd, struct interface **ifp)
+{
+  int ret;
+  struct ip iph;
+  u_int16_t ip_len;
+  struct stream *ibuf;
+  unsigned int ifindex = 0;
+  struct iovec iov;
+  struct cmsghdr *cmsg;
+#if defined (IP_PKTINFO)
+  struct in_pktinfo *pktinfo;
+#elif defined (IP_RECVIF)
+  struct sockaddr_dl *pktinfo;
+#else
+  char *pktinfo; /* dummy */
+#endif
+  char buff [sizeof (*cmsg) + sizeof (*pktinfo)];
+  struct msghdr msgh = {NULL, 0, &iov, 1, buff,
+			sizeof (*cmsg) + sizeof (*pktinfo), 0};
+    
+  ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
+  
+  if (ret != sizeof (iph))
+    {
+      zlog_warn ("ospf_recv_packet packet smaller than ip header");
+      return NULL;
+    }
+
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+  ip_len = iph.ip_len;
+#else
+  ip_len = ntohs (iph.ip_len);
+#endif
+
+#if !defined(GNU_LINUX)
+  /*
+   * Kernel network code touches incoming IP header parameters,
+   * before protocol specific processing.
+   *
+   *   1) Convert byteorder to host representation.
+   *      --> ip_len, ip_id, ip_off
+   *
+   *   2) Adjust ip_len to strip IP header size!
+   *      --> If user process receives entire IP packet via RAW
+   *          socket, it must consider adding IP header size to
+   *          the "ip_len" field of "ip" structure.
+   *
+   * For more details, see <netinet/ip_input.c>.
+   */
+  ip_len = ip_len + (iph.ip_hl << 2);
+#endif
+  
+  ibuf = stream_new (ip_len);
+  iov.iov_base = STREAM_DATA (ibuf);
+  iov.iov_len = ip_len;
+  ret = recvmsg (fd, &msgh, 0);
+  
+  cmsg = CMSG_FIRSTHDR (&msgh);
+  
+  if (cmsg != NULL && //cmsg->cmsg_len == sizeof (*pktinfo) &&
+      cmsg->cmsg_level == IPPROTO_IP &&
+#if defined (IP_PKTINFO)
+      cmsg->cmsg_type == IP_PKTINFO
+#elif defined (IP_RECVIF)
+      cmsg->cmsg_type == IP_RECVIF
+#else
+      0
+#endif
+      )
+    {
+#if defined (IP_PKTINFO)
+      pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
+      ifindex = pktinfo->ipi_ifindex;
+#elif defined (IP_RECVIF)
+      pktinfo = (struct sockaddr_dl *)CMSG_DATA(cmsg);
+      ifindex = pktinfo->sdl_index;
+#else
+      ifindex = 0;
+#endif
+    }
+  
+  *ifp = if_lookup_by_index (ifindex);
+
+  if (ret != ip_len)
+    {
+      zlog_warn ("ospf_recv_packet short read. "
+		 "ip_len %d bytes read %d", ip_len, ret);
+      stream_free (ibuf);
+      return NULL;
+    }
+  
+  return ibuf;
+}
+
+struct ospf_interface *
+ospf_associate_packet_vl (struct interface *ifp, struct ospf_interface *oi,
+			  struct ip *iph, struct ospf_header *ospfh)
+{
+  struct ospf_interface *rcv_oi;
+  listnode node;
+  struct ospf_vl_data *vl_data;
+  struct ospf_area *vl_area;
+
+  if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||
+      !OSPF_IS_AREA_BACKBONE (ospfh))
+    return oi;
+
+  if ((rcv_oi = oi) == NULL)
+    {
+     if ((rcv_oi = ospf_if_lookup_by_local_addr (ifp, iph->ip_dst)) == NULL)
+       return NULL;
+    }
+
+  for (node = listhead (ospf_top->vlinks); node; nextnode (node))
+    {
+      if ((vl_data = getdata (node)) == NULL)
+	continue;
+      
+      vl_area = ospf_area_lookup_by_area_id (vl_data->vl_area_id);
+      if (!vl_area)
+	continue;
+      
+      if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) &&
+	  IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("associating packet with %s",
+		       IF_NAME (vl_data->vl_oi));
+	  if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
+	    {
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("This VL is not up yet, sorry");
+	      return NULL;
+	    }
+	  
+	  return vl_data->vl_oi;
+	}
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("couldn't find any VL to associate the packet with");
+  
+  return oi;
+}
+
+int
+ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
+{
+  /* Check match the Area ID of the receiving interface. */
+  if (OSPF_AREA_SAME (&oi->area, &ospfh))
+    return 1;
+
+  return 0;
+}
+
+/* Unbound socket will accept any Raw IP packets if proto is matched.
+   To prevent it, compare src IP address and i/f address with masking
+   i/f network mask. */
+int
+ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
+{
+  struct in_addr mask, me, him;
+
+  if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
+      oi->type == OSPF_IFTYPE_VIRTUALLINK)
+    return 1;
+
+  masklen2ip (oi->address->prefixlen, &mask);
+
+  me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
+  him.s_addr = ip_src.s_addr & mask.s_addr;
+
+ if (IPV4_ADDR_SAME (&me, &him))
+   return 1;
+
+ return 0;
+}
+
+int
+ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
+		 struct ospf_header *ospfh)
+{
+  int ret = 0;
+  struct crypt_key *ck;
+
+  switch (ntohs (ospfh->auth_type))
+    {
+    case OSPF_AUTH_NULL:
+      ret = 1;
+      break;
+    case OSPF_AUTH_SIMPLE:
+      if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
+	ret = 1;
+      else
+	ret = 0;
+      break;
+    case OSPF_AUTH_CRYPTOGRAPHIC:
+      if ((ck = getdata (OSPF_IF_PARAM (oi,auth_crypt)->tail)) == NULL)
+	{
+	  ret = 0;
+	  break;
+	}
+      
+      /* This is very basic, the digest processing is elsewhere */
+      if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE && 
+          ospfh->u.crypt.key_id == ck->key_id &&
+          ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
+        ret = 1;
+      else
+        ret = 0;
+      break;
+    default:
+      ret = 0;
+      break;
+    }
+
+  return ret;
+}
+
+int
+ospf_check_sum (struct ospf_header *ospfh)
+{
+  u_int32_t ret;
+  u_int16_t sum;
+  int in_cksum (void *ptr, int nbytes);
+
+  /* clear auth_data for checksum. */
+  memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
+
+  /* keep checksum and clear. */
+  sum = ospfh->checksum;
+  memset (&ospfh->checksum, 0, sizeof (u_int16_t));
+
+  /* calculate checksum. */
+  ret = in_cksum (ospfh, ntohs (ospfh->length));
+
+  if (ret != sum)
+    {
+      zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X",
+		 ret, sum);
+      return 0;
+    }
+
+  return 1;
+}
+
+/* OSPF Header verification. */
+int
+ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
+		    struct ip *iph, struct ospf_header *ospfh)
+{
+  /* check version. */
+  if (ospfh->version != OSPF_VERSION)
+    {
+      zlog_warn ("interface %s: ospf_read version number mismatch.",
+		 IF_NAME (oi));
+      return -1;
+    }
+
+  /* Check Area ID. */
+  if (!ospf_check_area_id (oi, ospfh))
+    {
+      zlog_warn ("interface %s: ospf_read invalid Area ID %s.",
+		 IF_NAME (oi), inet_ntoa (ospfh->area_id));
+      return -1;
+    }
+
+  /* Check network mask, Silently discarded. */
+  if (! ospf_check_network_mask (oi, iph->ip_src))
+    {
+      zlog_warn ("interface %s: ospf_read network address is not same [%s]",
+		 IF_NAME (oi), inet_ntoa (iph->ip_src));
+      return -1;
+    }
+
+  /* Check authentication. */
+  if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
+    {
+      zlog_warn ("interface %s: ospf_read authentication type mismatch.",
+		 IF_NAME (oi));
+      return -1;
+    }
+
+  if (! ospf_check_auth (oi, ibuf, ospfh))
+    {
+      zlog_warn ("interface %s: ospf_read authentication failed.",
+		 IF_NAME (oi));
+      return -1;
+    }
+
+  /* if check sum is invalid, packet is discarded. */
+  if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
+    {
+      if (! ospf_check_sum (ospfh))
+	{
+	  zlog_warn ("interface %s: ospf_read packet checksum error %s",
+		     IF_NAME (oi), inet_ntoa (ospfh->router_id));
+	  return -1;
+	}
+    }
+  else
+    {
+      if (ospfh->checksum != 0)
+	return -1;
+      if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
+	{
+	  zlog_warn ("interface %s: ospf_read md5 authentication failed.",
+		     IF_NAME (oi));
+	  return -1;
+	}
+    }
+
+  return 0;
+}
+
+/* Starting point of packet process function. */
+int
+ospf_read (struct thread *thread)
+{
+  int ret;
+  struct stream *ibuf;
+  struct ospf *top;
+  struct ospf_interface *oi;
+  struct ip *iph;
+  struct ospf_header *ospfh;
+  u_int16_t length;
+  struct interface *ifp;
+
+  /* first of all get interface pointer. */
+  top = THREAD_ARG (thread);
+  top->t_read = NULL;
+
+  /* read OSPF packet. */
+  ibuf = ospf_recv_packet (top->fd, &ifp);
+  if (ibuf == NULL)
+    return -1;
+  
+  iph = (struct ip *) STREAM_DATA (ibuf);
+
+  /* prepare for next packet. */
+  top->t_read = thread_add_read (master, ospf_read, top, top->fd);
+
+  /* IP Header dump. */
+  /*
+  if (ospf_debug_packet & OSPF_DEBUG_RECV)
+    ospf_ip_header_dump (ibuf);
+  */
+  /* Self-originated packet should be discarded silently. */
+  if (ospf_if_lookup_by_local_addr (NULL, iph->ip_src))
+    {
+      stream_free (ibuf);
+      return 0;
+    }
+
+  /* Adjust size to message length. */
+  stream_forward (ibuf, iph->ip_hl * 4);
+  
+  /* Get ospf packet header. */
+  ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
+
+  /* associate packet with ospf interface */
+  oi = ospf_if_lookup_recv_interface (iph->ip_src);
+  if (ifp && oi && oi->ifp != ifp)
+    {
+      zlog_warn ("Packet from [%s] received on wrong link %s",
+		 inet_ntoa (iph->ip_src), ifp->name); 
+      stream_free (ibuf);
+      return 0;
+    }
+  
+  if ((oi = ospf_associate_packet_vl (ifp, oi, iph, ospfh)) == NULL)
+    {
+      stream_free (ibuf);
+      return 0;
+    }
+
+  /*
+   * If the received packet is destined for AllDRouters, the packet
+   * should be accepted only if the received ospf interface state is
+   * either DR or Backup -- endo.
+   */
+  if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
+  && (oi->state != ISM_DR && oi->state != ISM_Backup))
+    {
+      zlog_info ("Packet for AllDRouters from [%s] via [%s] (ISM: %s)",
+                 inet_ntoa (iph->ip_src), IF_NAME (oi),
+                 LOOKUP (ospf_ism_state_msg, oi->state));
+      stream_free (ibuf);
+      return 0;
+    }
+
+  /* Show debug receiving packet. */
+  if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
+    {
+      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
+	{
+	  zlog_info ("-----------------------------------------------------");
+	  ospf_packet_dump (ibuf);
+	}
+
+      zlog_info ("%s received from [%s] via [%s]",
+		 ospf_packet_type_str[ospfh->type],
+		 inet_ntoa (ospfh->router_id), IF_NAME (oi));
+      zlog_info (" src [%s],", inet_ntoa (iph->ip_src));
+      zlog_info (" dst [%s]", inet_ntoa (iph->ip_dst));
+
+      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
+	zlog_info ("-----------------------------------------------------");
+    }
+
+  /* Some header verification. */
+  ret = ospf_verify_header (ibuf, oi, iph, ospfh);
+  if (ret < 0)
+    {
+      stream_free (ibuf);
+      return ret;
+    }
+
+  stream_forward (ibuf, OSPF_HEADER_SIZE);
+
+  /* Adjust size to message length. */
+  length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
+
+  /* Read rest of the packet and call each sort of packet routine. */
+  switch (ospfh->type)
+    {
+    case OSPF_MSG_HELLO:
+      ospf_hello (iph, ospfh, ibuf, oi, length);
+      break;
+    case OSPF_MSG_DB_DESC:
+      ospf_db_desc (iph, ospfh, ibuf, oi, length);
+      break;
+    case OSPF_MSG_LS_REQ:
+      ospf_ls_req (iph, ospfh, ibuf, oi, length);
+      break;
+    case OSPF_MSG_LS_UPD:
+      ospf_ls_upd (iph, ospfh, ibuf, oi, length);
+      break;
+    case OSPF_MSG_LS_ACK:
+      ospf_ls_ack (iph, ospfh, ibuf, oi, length);
+      break;
+    default:
+      zlog (NULL, LOG_WARNING,
+	    "interface %s: OSPF packet header type %d is illegal",
+	    IF_NAME (oi), ospfh->type);
+      break;
+    }
+
+  stream_free (ibuf);
+  return 0;
+}
+
+/* Make OSPF header. */
+void
+ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
+{
+  struct ospf_header *ospfh;
+
+  ospfh = (struct ospf_header *) STREAM_DATA (s);
+
+  ospfh->version = (u_char) OSPF_VERSION;
+  ospfh->type = (u_char) type;
+
+  ospfh->router_id = ospf_top->router_id;
+
+  ospfh->checksum = 0;
+  ospfh->area_id = oi->area->area_id;
+  ospfh->auth_type = htons (ospf_auth_type (oi));
+
+  memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
+
+  ospf_output_forward (s, OSPF_HEADER_SIZE);
+}
+
+/* Make Authentication Data. */
+int
+ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
+{
+  struct crypt_key *ck;
+
+  switch (ospf_auth_type (oi))
+    {
+    case OSPF_AUTH_NULL:
+      /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
+      break;
+    case OSPF_AUTH_SIMPLE:
+      memcpy (ospfh->u.auth_data, OSPF_IF_PARAM (oi, auth_simple),
+	      OSPF_AUTH_SIMPLE_SIZE);
+      break;
+    case OSPF_AUTH_CRYPTOGRAPHIC:
+      /* If key is not set, then set 0. */
+      if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
+	{
+	  ospfh->u.crypt.zero = 0;
+	  ospfh->u.crypt.key_id = 0;
+	  ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
+	}
+      else
+	{
+	  ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
+	  ospfh->u.crypt.zero = 0;
+	  ospfh->u.crypt.key_id = ck->key_id;
+	  ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
+	}
+      /* note: the seq is done in ospf_make_md5_digest() */
+      break;
+    default:
+      /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
+      break;
+    }
+
+  return 0;
+}
+
+/* Fill rest of OSPF header. */
+void
+ospf_fill_header (struct ospf_interface *oi,
+		  struct stream *s, u_int16_t length)
+{
+  struct ospf_header *ospfh;
+
+  ospfh = (struct ospf_header *) STREAM_DATA (s);
+
+  /* Fill length. */
+  ospfh->length = htons (length);
+
+  /* Calculate checksum. */
+  if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
+    ospfh->checksum = in_cksum (ospfh, length);
+  else
+    ospfh->checksum = 0;
+
+  /* Add Authentication Data. */
+  ospf_make_auth (oi, ospfh);
+}
+
+int
+ospf_make_hello (struct ospf_interface *oi, struct stream *s)
+{
+  struct ospf_neighbor *nbr;
+  struct route_node *rn;
+  u_int16_t length = OSPF_HELLO_MIN_SIZE;
+  struct in_addr mask;
+  unsigned long p;
+  int flag = 0;
+
+  /* Set netmask of interface. */
+  if (oi->type != OSPF_IFTYPE_POINTOPOINT &&
+      oi->type != OSPF_IFTYPE_VIRTUALLINK)
+    masklen2ip (oi->address->prefixlen, &mask);
+  else
+    memset ((char *) &mask, 0, sizeof (struct in_addr));
+  stream_put_ipv4 (s, mask.s_addr);
+
+  /* Set Hello Interval. */
+  stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("make_hello: options: %x, int: %s",
+	       OPTIONS(oi), IF_NAME (oi));
+
+  /* Set Options. */
+  stream_putc (s, OPTIONS (oi));
+
+  /* Set Router Priority. */
+  stream_putc (s, PRIORITY (oi));
+
+  /* Set Router Dead Interval. */
+  stream_putl (s, OSPF_IF_PARAM (oi, v_wait));
+
+  /* Set Designated Router. */
+  stream_put_ipv4 (s, DR (oi).s_addr);
+
+  p = s->putp;
+
+  /* Set Backup Designated Router. */
+  stream_put_ipv4 (s, BDR (oi).s_addr);
+
+  /* Add neighbor seen. */
+  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+    if ((nbr = rn->info) != NULL)
+      /* ignore 0.0.0.0 node. */
+      if (nbr->router_id.s_addr != 0)
+	if (nbr->state != NSM_Attempt)
+	/* ignore Down neighbor. */
+	if (nbr->state != NSM_Down)
+	  /* this is myself for DR election. */
+	  if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf_top->router_id))
+	    {
+	      /* Check neighbor is sane? */
+	      if (nbr->d_router.s_addr != 0 &&
+		  IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4) &&
+		  IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4))
+		flag = 1;
+
+	      stream_put_ipv4 (s, nbr->router_id.s_addr);
+	      length += 4;
+	    }
+
+  /* Let neighbor generate BackupSeen. */
+  if (flag == 1)
+    {
+      stream_set_putp (s, p);
+      stream_put_ipv4 (s, 0);
+    }
+
+  return length;
+}
+
+int
+ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
+		   struct stream *s)
+{
+  struct ospf_lsa *lsa;
+  u_int16_t length = OSPF_DB_DESC_MIN_SIZE;
+  u_char options;
+  unsigned long pp;
+  int i;
+  struct ospf_lsdb *lsdb;
+  
+  /* Set Interface MTU. */
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+    stream_putw (s, 0);
+  else
+    stream_putw (s, oi->ifp->mtu);
+
+  /* Set Options. */
+  options = OPTIONS (oi);
+#ifdef HAVE_OPAQUE_LSA
+  if (CHECK_FLAG (ospf_top->config, OSPF_OPAQUE_CAPABLE))
+    {
+      if (IS_SET_DD_I (nbr->dd_flags)
+      ||  CHECK_FLAG (nbr->options, OSPF_OPTION_O))
+        /*
+         * Set O-bit in the outgoing DD packet for capablity negotiation,
+         * if one of following case is applicable. 
+         *
+         * 1) WaitTimer expiration event triggered the neighbor state to
+         *    change to Exstart, but no (valid) DD packet has received
+         *    from the neighbor yet.
+         *
+         * 2) At least one DD packet with O-bit on has received from the
+         *    neighbor.
+         */
+        SET_FLAG (options, OSPF_OPTION_O);
+    }
+#endif /* HAVE_OPAQUE_LSA */
+  stream_putc (s, options);
+
+  /* Keep pointer to flags. */
+  pp = stream_get_putp (s);
+  stream_putc (s, nbr->dd_flags);
+
+  /* Set DD Sequence Number. */
+  stream_putl (s, nbr->dd_seqnum);
+
+  if (ospf_db_summary_isempty (nbr))
+    {
+      if (nbr->state >= NSM_Exchange)
+	{
+	  nbr->dd_flags &= ~OSPF_DD_FLAG_M;
+	  /* Set DD flags again */
+	  stream_set_putp (s, pp);
+	  stream_putc (s, nbr->dd_flags);
+	}
+      return length;
+    }
+
+  /* Describe LSA Header from Database Summary List. */
+  lsdb = &nbr->db_sum;
+
+  for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+    {
+      struct route_table *table = lsdb->type[i].db;
+      struct route_node *rn;
+
+      for (rn = route_top (table); rn; rn = route_next (rn))
+	if ((lsa = rn->info) != NULL)
+	  {
+#ifdef HAVE_OPAQUE_LSA
+            if (IS_OPAQUE_LSA (lsa->data->type)
+            && (! CHECK_FLAG (options, OSPF_OPTION_O)))
+              {
+                /* Suppress advertising opaque-informations. */
+                /* Remove LSA from DB summary list. */
+                ospf_lsdb_delete (lsdb, lsa);
+                continue;
+              }
+#endif /* HAVE_OPAQUE_LSA */
+
+	    if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
+	      {
+		struct lsa_header *lsah;
+		u_int16_t ls_age;
+		
+		/* DD packet overflows interface MTU. */
+		if (length + OSPF_LSA_HEADER_SIZE > OSPF_PACKET_MAX (oi))
+		  break;
+		
+		/* Keep pointer to LS age. */
+		lsah = (struct lsa_header *) (STREAM_DATA (s) +
+					      stream_get_putp (s));
+		
+		/* Proceed stream pointer. */
+		stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
+		length += OSPF_LSA_HEADER_SIZE;
+		
+		/* Set LS age. */
+		ls_age = LS_AGE (lsa);
+		lsah->ls_age = htons (ls_age);
+		
+	      }
+	    
+	    /* Remove LSA from DB summary list. */
+	    ospf_lsdb_delete (lsdb, lsa);
+	  }
+    }
+
+  return length;
+}
+
+int
+ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
+		       unsigned long delta, struct ospf_neighbor *nbr,
+		       struct ospf_lsa *lsa)
+{
+  struct ospf_interface *oi;
+
+  oi = nbr->oi;
+
+  /* LS Request packet overflows interface MTU. */
+  if (*length + delta > OSPF_PACKET_MAX(oi))
+    return 0;
+
+  stream_putl (s, lsa->data->type);
+  stream_put_ipv4 (s, lsa->data->id.s_addr);
+  stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
+  
+  ospf_lsa_unlock (nbr->ls_req_last);
+  nbr->ls_req_last = ospf_lsa_lock (lsa);
+  
+  *length += 12;
+  return 1;
+}
+
+int
+ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
+{
+  struct ospf_lsa *lsa;
+  u_int16_t length = OSPF_LS_REQ_MIN_SIZE;
+  unsigned long delta = stream_get_putp(s)+12;
+  struct route_table *table;
+  struct route_node *rn;
+  int i;
+  struct ospf_lsdb *lsdb;
+
+  lsdb = &nbr->ls_req;
+
+  for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+    {
+      table = lsdb->type[i].db;
+      for (rn = route_top (table); rn; rn = route_next (rn))
+	if ((lsa = (rn->info)) != NULL)
+	  if (ospf_make_ls_req_func (s, &length, delta, nbr, lsa) == 0)
+	    {
+	      route_unlock_node (rn);
+	      break;
+	    }
+    }
+  return length;
+}
+
+int
+ls_age_increment (struct ospf_lsa *lsa, int delay)
+{
+  int age;
+
+  age = IS_LSA_MAXAGE (lsa) ? OSPF_LSA_MAXAGE : LS_AGE (lsa) + delay;
+
+  return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
+}
+
+int
+ospf_make_ls_upd (struct ospf_interface *oi, list update, struct stream *s)
+{
+  struct ospf_lsa *lsa;
+  listnode node;
+  u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
+  unsigned long delta = stream_get_putp (s);
+  unsigned long pp;
+  int count = 0;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info("ospf_make_ls_upd: Start");
+  
+  pp = stream_get_putp (s);
+  ospf_output_forward (s, 4);
+
+  while ((node = listhead (update)) != NULL)
+    {
+      struct lsa_header *lsah;
+      u_int16_t ls_age;
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info("ospf_make_ls_upd: List Iteration");
+
+      lsa = getdata (node);
+      assert (lsa);
+      assert (lsa->data);
+
+      /* Check packet size. */
+      if (length + delta + ntohs (lsa->data->length) > OSPF_PACKET_MAX (oi))
+	break;
+      
+      /* Keep pointer to LS age. */
+      lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_putp (s));
+
+      /* Put LSA to Link State Request. */
+      stream_put (s, lsa->data, ntohs (lsa->data->length));
+
+      /* Set LS age. */
+      /* each hop must increment an lsa_age by transmit_delay 
+         of OSPF interface */
+      ls_age = ls_age_increment (lsa, OSPF_IF_PARAM (oi, transmit_delay));
+      lsah->ls_age = htons (ls_age);
+
+      length += ntohs (lsa->data->length);
+      count++;
+
+      list_delete_node (update, node);
+      ospf_lsa_unlock (lsa);
+    }
+
+  /* Now set #LSAs. */
+  stream_set_putp (s, pp);
+  stream_putl (s, count);
+
+  stream_set_putp (s, s->endp);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info("ospf_make_ls_upd: Stop");
+  return length;
+}
+
+int
+ospf_make_ls_ack (struct ospf_interface *oi, list ack, struct stream *s)
+{
+  list rm_list;
+  listnode node;
+  u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
+  unsigned long delta = stream_get_putp(s) + 24;
+  struct ospf_lsa *lsa;
+
+  rm_list = list_new ();
+  
+  for (node = listhead (ack); node; nextnode (node))
+    {
+      lsa = getdata (node);
+      assert (lsa);
+      
+      if (length + delta > OSPF_PACKET_MAX (oi))
+	break;
+      
+      stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
+      length += OSPF_LSA_HEADER_SIZE;
+      
+      listnode_add (rm_list, lsa);
+    }
+  
+  /* Remove LSA from LS-Ack list. */
+  for (node = listhead (rm_list); node; nextnode (node))
+    {
+      lsa = (struct ospf_lsa *) getdata (node);
+      
+      listnode_delete (ack, lsa);
+      ospf_lsa_unlock (lsa);
+    }
+  
+  list_delete (rm_list);
+  
+  return length;
+}
+
+void
+ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
+{
+  struct ospf_packet *op;
+  u_int16_t length = OSPF_HEADER_SIZE;
+
+  op = ospf_packet_new (oi->ifp->mtu);
+
+  /* Prepare OSPF common header. */
+  ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
+
+  /* Prepare OSPF Hello body. */
+  length += ospf_make_hello (oi, op->s);
+
+  /* Fill OSPF header. */
+  ospf_fill_header (oi, op->s, length);
+
+  /* Set packet length. */
+  op->length = length;
+
+  op->dst.s_addr = addr->s_addr;
+
+  /* Add packet to the interface output queue. */
+  ospf_packet_add (oi, op);
+
+  /* Hook thread to write packet. */
+  OSPF_ISM_WRITE_ON ();
+}
+
+void
+ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
+{
+  struct ospf_interface *oi;
+
+  oi = nbr_nbma->oi;
+  assert(oi);
+
+  /* If this is passive interface, do not send OSPF Hello. */
+  if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+    return;
+
+  if (oi->type != OSPF_IFTYPE_NBMA)
+    return;
+
+  if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
+    return;
+
+  if (PRIORITY(oi) == 0)
+    return;
+
+  if (nbr_nbma->priority == 0
+      && oi->state != ISM_DR && oi->state != ISM_Backup)
+    return;
+
+  ospf_hello_send_sub (oi, &nbr_nbma->addr);
+}
+
+int
+ospf_poll_timer (struct thread *thread)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  nbr_nbma = THREAD_ARG (thread);
+  nbr_nbma->t_poll = NULL;
+
+  if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
+    zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (Poll timer expire)",
+    IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
+
+  ospf_poll_send (nbr_nbma);
+
+  if (nbr_nbma->v_poll > 0)
+    OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
+			nbr_nbma->v_poll);
+
+  return 0;
+}
+
+
+int
+ospf_hello_reply_timer (struct thread *thread)
+{
+  struct ospf_neighbor *nbr;
+
+  nbr = THREAD_ARG (thread);
+  nbr->t_hello_reply = NULL;
+
+  assert (nbr->oi);
+
+  if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
+    zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (hello-reply timer expire)",
+	  IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
+
+  ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
+
+  return 0;
+}
+
+/* Send OSPF Hello. */
+void
+ospf_hello_send (struct ospf_interface *oi)
+{
+  struct ospf_packet *op;
+  u_int16_t length = OSPF_HEADER_SIZE;
+
+  /* If this is passive interface, do not send OSPF Hello. */
+  if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+    return;
+
+  op = ospf_packet_new (oi->ifp->mtu);
+
+  /* Prepare OSPF common header. */
+  ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
+
+  /* Prepare OSPF Hello body. */
+  length += ospf_make_hello (oi, op->s);
+
+  /* Fill OSPF header. */
+  ospf_fill_header (oi, op->s, length);
+
+  /* Set packet length. */
+  op->length = length;
+
+  if (oi->type == OSPF_IFTYPE_NBMA)
+    {
+      struct ospf_neighbor *nbr;
+      struct route_node *rn;
+
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info))
+	  if (nbr != oi->nbr_self)
+	    if (nbr->state != NSM_Down)
+	      {
+		/*  RFC 2328  Section 9.5.1
+		    If the router is not eligible to become Designated Router,
+		    it must periodically send Hello Packets to both the
+		    Designated Router and the Backup Designated Router (if they
+		    exist).  */
+		if (PRIORITY(oi) == 0 &&
+		    IPV4_ADDR_CMP(&DR(oi),  &nbr->address.u.prefix4) &&
+		    IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
+		  continue;
+
+		/*  If the router is eligible to become Designated Router, it
+		    must periodically send Hello Packets to all neighbors that
+		    are also eligible. In addition, if the router is itself the
+		    Designated Router or Backup Designated Router, it must also
+		    send periodic Hello Packets to all other neighbors. */
+
+		if (nbr->priority == 0 && oi->state == ISM_DROther)
+		  continue;
+		/* if oi->state == Waiting, send hello to all neighbors */
+		{
+		  struct ospf_packet *op_dup;
+
+		  op_dup = ospf_packet_dup(op);
+		  op_dup->dst = nbr->address.u.prefix4;
+
+		  /* Add packet to the interface output queue. */
+		  ospf_packet_add (oi, op_dup);
+
+		  OSPF_ISM_WRITE_ON ();
+		}
+
+	      }
+      ospf_packet_free (op);
+    }
+  else
+    {
+      /* Decide destination address. */
+      if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+	op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
+      else 
+	op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+
+      /* Add packet to the interface output queue. */
+      ospf_packet_add (oi, op);
+
+      /* Hook thread to write packet. */
+      OSPF_ISM_WRITE_ON ();
+    }
+}
+
+/* Send OSPF Database Description. */
+void
+ospf_db_desc_send (struct ospf_neighbor *nbr)
+{
+  struct ospf_interface *oi;
+  struct ospf_packet *op;
+  u_int16_t length = OSPF_HEADER_SIZE;
+
+  oi = nbr->oi;
+  op = ospf_packet_new (oi->ifp->mtu);
+
+  /* Prepare OSPF common header. */
+  ospf_make_header (OSPF_MSG_DB_DESC, oi, op->s);
+
+  /* Prepare OSPF Database Description body. */
+  length += ospf_make_db_desc (oi, nbr, op->s);
+
+  /* Fill OSPF header. */
+  ospf_fill_header (oi, op->s, length);
+
+  /* Set packet length. */
+  op->length = length;
+
+  /* Decide destination address. */
+  op->dst = nbr->address.u.prefix4;
+
+  /* Add packet to the interface output queue. */
+  ospf_packet_add (oi, op);
+
+  /* Hook thread to write packet. */
+  OSPF_ISM_WRITE_ON ();
+
+  /* Remove old DD packet, then copy new one and keep in neighbor structure. */
+  if (nbr->last_send)
+    ospf_packet_free (nbr->last_send);
+  nbr->last_send = ospf_packet_dup (op);
+  gettimeofday (&nbr->last_send_ts, NULL);
+}
+
+/* Re-send Database Description. */
+void
+ospf_db_desc_resend (struct ospf_neighbor *nbr)
+{
+  struct ospf_interface *oi;
+
+  oi = nbr->oi;
+
+  /* Add packet to the interface output queue. */
+  ospf_packet_add (oi, ospf_packet_dup (nbr->last_send));
+
+  /* Hook thread to write packet. */
+  OSPF_ISM_WRITE_ON ();
+}
+
+/* Send Link State Request. */
+void
+ospf_ls_req_send (struct ospf_neighbor *nbr)
+{
+  struct ospf_interface *oi;
+  struct ospf_packet *op;
+  u_int16_t length = OSPF_HEADER_SIZE;
+
+  oi = nbr->oi;
+  op = ospf_packet_new (oi->ifp->mtu);
+
+  /* Prepare OSPF common header. */
+  ospf_make_header (OSPF_MSG_LS_REQ, oi, op->s);
+
+  /* Prepare OSPF Link State Request body. */
+  length += ospf_make_ls_req (nbr, op->s);
+  if (length == OSPF_HEADER_SIZE)
+    {
+      ospf_packet_free (op);
+      return;
+    }
+
+  /* Fill OSPF header. */
+  ospf_fill_header (oi, op->s, length);
+
+  /* Set packet length. */
+  op->length = length;
+
+  /* Decide destination address. */
+  op->dst = nbr->address.u.prefix4;
+
+  /* Add packet to the interface output queue. */
+  ospf_packet_add (oi, op);
+
+  /* Hook thread to write packet. */
+  OSPF_ISM_WRITE_ON ();
+
+  /* Add Link State Request Retransmission Timer. */
+  OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
+}
+
+/* Send Link State Update with an LSA. */
+void
+ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
+		      int flag)
+{
+  list update;
+
+  update = list_new ();
+
+  listnode_add (update, lsa);
+  ospf_ls_upd_send (nbr, update, flag);
+
+  list_delete (update);
+}
+
+static void
+ospf_ls_upd_queue_send (struct ospf_interface *oi, list update,
+			struct in_addr addr)
+{
+  struct ospf_packet *op;
+  u_int16_t length = OSPF_HEADER_SIZE;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
+
+  op = ospf_packet_new (oi->ifp->mtu);
+
+  /* Prepare OSPF common header. */
+  ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
+
+  /* Prepare OSPF Link State Update body. */
+  /* Includes Type-7 translation. */
+  length += ospf_make_ls_upd (oi, update, op->s);
+
+  /* Fill OSPF header. */
+  ospf_fill_header (oi, op->s, length);
+
+  /* Set packet length. */
+  op->length = length;
+
+  /* Decide destination address. */
+  op->dst.s_addr = addr.s_addr;
+
+  /* Add packet to the interface output queue. */
+  ospf_packet_add (oi, op);
+
+  /* Hook thread to write packet. */
+  OSPF_ISM_WRITE_ON ();
+}
+
+static int
+ospf_ls_upd_send_queue_event (struct thread *thread)
+{
+  struct ospf_interface *oi = THREAD_ARG(thread);
+  struct route_node *rn;
+  
+  oi->t_ls_upd_event = NULL;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_ls_upd_send_queue start");
+
+  for (rn = route_top (oi->ls_upd_queue); rn; rn = route_next (rn))
+    {
+      if (rn->info == NULL)
+	continue;
+
+      while (!list_isempty ((list)rn->info))
+	ospf_ls_upd_queue_send (oi, rn->info, rn->p.u.prefix4);
+
+      list_delete (rn->info);
+      rn->info = NULL;
+      
+      route_unlock_node (rn);
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_ls_upd_send_queue stop");
+  return 0;
+}
+
+void
+ospf_ls_upd_send (struct ospf_neighbor *nbr, list update, int flag)
+{
+  struct ospf_interface *oi;
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+  listnode n;
+  
+  oi = nbr->oi;
+
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+  
+  /* Decide destination address. */
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+    p.prefix = oi->vl_data->peer_addr;
+  else if (flag == OSPF_SEND_PACKET_DIRECT)
+     p.prefix = nbr->address.u.prefix4;
+  else if (oi->state == ISM_DR || oi->state == ISM_Backup)
+     p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
+  else if ((oi->type == OSPF_IFTYPE_POINTOPOINT) 
+	   && (flag == OSPF_SEND_PACKET_INDIRECT))
+     p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
+  else
+     p.prefix.s_addr = htonl (OSPF_ALLDROUTERS);
+
+  if (oi->type == OSPF_IFTYPE_NBMA)
+    {
+      if (flag == OSPF_SEND_PACKET_INDIRECT)
+	zlog_warn ("* LS-Update is directly sent on NBMA network.");
+      if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr))
+	zlog_warn ("* LS-Update is sent to myself.");
+    }
+
+  rn = route_node_get (oi->ls_upd_queue, (struct prefix *) &p);
+
+  if (rn->info == NULL)
+    rn->info = list_new ();
+
+  for (n = listhead (update); n; nextnode (n))
+    listnode_add (rn->info, ospf_lsa_lock (getdata (n)));
+
+  if (oi->t_ls_upd_event == NULL)
+    oi->t_ls_upd_event =
+      thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
+}
+
+static void
+ospf_ls_ack_send_list (struct ospf_interface *oi, list ack, struct in_addr dst)
+{
+  struct ospf_packet *op;
+  u_int16_t length = OSPF_HEADER_SIZE;
+
+  op = ospf_packet_new (oi->ifp->mtu);
+
+  /* Prepare OSPF common header. */
+  ospf_make_header (OSPF_MSG_LS_ACK, oi, op->s);
+
+  /* Prepare OSPF Link State Acknowledgment body. */
+  length += ospf_make_ls_ack (oi, ack, op->s);
+
+  /* Fill OSPF header. */
+  ospf_fill_header (oi, op->s, length);
+
+  /* Set packet length. */
+  op->length = length;
+
+  /* Set destination IP address. */
+  op->dst = dst;
+  
+  /* Add packet to the interface output queue. */
+  ospf_packet_add (oi, op);
+
+  /* Hook thread to write packet. */
+  OSPF_ISM_WRITE_ON ();
+}
+
+static int
+ospf_ls_ack_send_event (struct thread *thread)
+{
+  struct ospf_interface *oi = THREAD_ARG (thread);
+
+  oi->t_ls_ack_direct = NULL;
+  
+  while (listcount (oi->ls_ack_direct.ls_ack))
+    ospf_ls_ack_send_list (oi, oi->ls_ack_direct.ls_ack,
+			   oi->ls_ack_direct.dst);
+
+  return 0;
+}
+
+void
+ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  struct ospf_interface *oi = nbr->oi;
+
+  if (listcount (oi->ls_ack_direct.ls_ack) == 0)
+    oi->ls_ack_direct.dst = nbr->address.u.prefix4;
+  
+  listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa));
+  
+  if (oi->t_ls_ack_direct == NULL)
+    oi->t_ls_ack_direct =
+      thread_add_event (master, ospf_ls_ack_send_event, oi, 0);
+}
+
+/* Send Link State Acknowledgment delayed. */
+void
+ospf_ls_ack_send_delayed (struct ospf_interface *oi)
+{
+  struct in_addr dst;
+  
+  /* Decide destination address. */
+  /* RFC2328 Section 13.5                           On non-broadcast
+	networks, delayed Link State Acknowledgment packets must be
+	unicast	separately over	each adjacency (i.e., neighbor whose
+	state is >= Exchange).  */
+  if (oi->type == OSPF_IFTYPE_NBMA)
+    {
+      struct ospf_neighbor *nbr;
+      struct route_node *rn;
+
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info) != NULL)
+	  if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
+	    while (listcount (oi->ls_ack))
+	      ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4);
+      return;
+    }
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+    dst.s_addr = oi->vl_data->peer_addr.s_addr;
+  else if (oi->state == ISM_DR || oi->state == ISM_Backup)
+    dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+  else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+    dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+  else
+    dst.s_addr = htonl (OSPF_ALLDROUTERS);
+
+  while (listcount (oi->ls_ack))
+    ospf_ls_ack_send_list (oi, oi->ls_ack, dst);
+}
diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h
new file mode 100644
index 0000000..81a104c
--- /dev/null
+++ b/ospfd/ospf_packet.h
@@ -0,0 +1,171 @@
+/*
+ * OSPF Sending and Receiving OSPF Packets.
+ * Copyright (C) 1999 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_PACKET_H
+#define _ZEBRA_OSPF_PACKET_H
+
+#define OSPF_HEADER_SIZE         24
+#define OSPF_AUTH_SIMPLE_SIZE     8
+#define OSPF_AUTH_MD5_SIZE       16
+
+#define OSPF_MAX_PACKET_SIZE  65535   /* includes IP Header size. */
+#define OSPF_HELLO_MIN_SIZE      20   /* not including neighbors */
+#define OSPF_DB_DESC_MIN_SIZE     8
+#define OSPF_LS_REQ_MIN_SIZE      0
+#define OSPF_LS_UPD_MIN_SIZE      4
+#define OSPF_LS_ACK_MIN_SIZE      0
+
+#define OSPF_MSG_HELLO         1  /* OSPF Hello Message. */
+#define OSPF_MSG_DB_DESC       2  /* OSPF Database Descriptoin Message. */
+#define OSPF_MSG_LS_REQ        3  /* OSPF Link State Request Message. */
+#define OSPF_MSG_LS_UPD        4  /* OSPF Link State Update Message. */
+#define OSPF_MSG_LS_ACK        5  /* OSPF Link State Acknoledgement Message. */
+
+#define OSPF_SEND_PACKET_DIRECT         1
+#define OSPF_SEND_PACKET_INDIRECT       2
+
+#ifdef HAVE_NSSA
+#define OSPF_SEND_PACKET_LOOP           3
+#endif /* HAVE_NSSA */
+
+#define OSPF_HELLO_REPLY_DELAY          1
+
+struct ospf_packet
+{
+  struct ospf_packet *next;
+
+  /* Pointer to data stream. */
+  struct stream *s;
+
+  /* IP destination address. */
+  struct in_addr dst;
+
+  /* OSPF packet length. */
+  u_int16_t length;
+};
+
+/* OSPF packet queue structure. */
+struct ospf_fifo
+{
+  unsigned long count;
+
+  struct ospf_packet *head;
+  struct ospf_packet *tail;
+};
+
+/* OSPF packet header structure. */
+struct ospf_header
+{
+  u_char version;                       /* OSPF Version. */
+  u_char type;                          /* Packet Type. */
+  u_int16_t length;                     /* Packet Length. */
+  struct in_addr router_id;             /* Router ID. */
+  struct in_addr area_id;               /* Area ID. */
+  u_int16_t checksum;                   /* Check Sum. */
+  u_int16_t auth_type;                  /* Authentication Type. */
+  /* Authentication Data. */
+  union
+  {
+    /* Simple Authentication. */
+    u_char auth_data [OSPF_AUTH_SIMPLE_SIZE];
+    /* Cryptographic Authentication. */
+    struct
+    {
+      u_int16_t zero;                   /* Should be 0. */
+      u_char key_id;                    /* Key ID. */
+      u_char auth_data_len;             /* Auth Data Length. */
+      u_int32_t crypt_seqnum;           /* Cryptographic Sequence Number. */
+    } crypt;
+  } u;
+};
+
+/* OSPF Hello body format. */
+struct ospf_hello
+{
+  struct in_addr network_mask;
+  u_int16_t hello_interval;
+  u_char options;
+  u_char priority;
+  u_int32_t dead_interval;
+  struct in_addr d_router;
+  struct in_addr bd_router;
+  struct in_addr neighbors[1];
+};
+
+/* OSPF Database Description body format. */
+struct ospf_db_desc
+{
+  u_int16_t mtu;
+  u_char options;
+  u_char flags;
+  u_int32_t dd_seqnum;
+};
+
+
+/* Macros. */
+#define OSPF_PACKET_MAX(oi)     ospf_packet_max (oi)
+/*
+#define OSPF_PACKET_MAX(oi)     (((oi)->ifp->mtu - ((oi)->auth_md5 ? OSPF_AUTH_MD5_SIZE : 0)) - 88)
+*/
+
+#define OSPF_OUTPUT_PNT(S)      ((S)->data + (S)->putp)
+#define OSPF_OUTPUT_LENGTH(S)   ((S)->endp)
+
+#define IS_SET_DD_MS(X)         ((X) & OSPF_DD_FLAG_MS)
+#define IS_SET_DD_M(X)          ((X) & OSPF_DD_FLAG_M)
+#define IS_SET_DD_I(X)          ((X) & OSPF_DD_FLAG_I)
+#define IS_SET_DD_ALL(X)        ((X) & OSPF_DD_FLAG_ALL)
+
+/* Prototypes. */
+void ospf_output_forward (struct stream *, int);
+struct ospf_packet *ospf_packet_new (size_t);
+void ospf_packet_free (struct ospf_packet *);
+struct ospf_fifo *ospf_fifo_new ();
+void ospf_fifo_push (struct ospf_fifo *, struct ospf_packet *);
+struct ospf_packet *ospf_fifo_pop (struct ospf_fifo *);
+struct ospf_packet *ospf_fifo_head (struct ospf_fifo *);
+void ospf_fifo_flush (struct ospf_fifo *);
+void ospf_fifo_free (struct ospf_fifo *);
+void ospf_packet_add (struct ospf_interface *, struct ospf_packet *);
+void ospf_packet_delete (struct ospf_interface *);
+struct stream *ospf_stream_dup (struct stream *);
+struct ospf_packet *ospf_packet_dup (struct ospf_packet *);
+
+int ospf_read (struct thread *);
+void ospf_hello_send (struct ospf_interface *);
+void ospf_db_desc_send (struct ospf_neighbor *);
+void ospf_db_desc_resend (struct ospf_neighbor *);
+void ospf_ls_req_send (struct ospf_neighbor *);
+void ospf_ls_upd_send_lsa (struct ospf_neighbor *, struct ospf_lsa *, int);
+void ospf_ls_upd_send (struct ospf_neighbor *, list, int);
+void ospf_ls_ack_send (struct ospf_neighbor *, struct ospf_lsa *);
+void ospf_ls_ack_send_delayed (struct ospf_interface *);
+void ospf_ls_retransmit (struct ospf_interface *, struct ospf_lsa *);
+void ospf_ls_req_event (struct ospf_neighbor *);
+
+int ospf_ls_upd_timer (struct thread *);
+int ospf_ls_ack_timer (struct thread *);
+int ospf_poll_timer (struct thread *);
+int ospf_hello_reply_timer (struct thread *);
+void ospf_hello_send_sub (struct ospf_interface *, struct in_addr *);
+
+#endif /* _ZEBRA_OSPF_PACKET_H */
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
new file mode 100644
index 0000000..96f7531
--- /dev/null
+++ b/ospfd/ospf_route.c
@@ -0,0 +1,1026 @@
+/*
+ * OSPF routing table.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "table.h"
+#include "memory.h"
+#include "linklist.h"
+#include "log.h"
+#include "if.h"
+#include "command.h"
+#include "sockunion.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_dump.h"
+
+struct ospf_route *
+ospf_route_new ()
+{
+  struct ospf_route *new;
+
+  new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
+
+  new->ctime = time (NULL);
+  new->mtime = new->ctime;
+
+  return new;
+}
+
+void
+ospf_route_free (struct ospf_route *or)
+{
+  listnode node;
+
+  if (or->path)
+    {
+      for (node = listhead (or->path); node; nextnode (node))
+	ospf_path_free (node->data);
+
+      list_delete (or->path);
+    }
+
+  XFREE (MTYPE_OSPF_ROUTE, or);
+}
+
+struct ospf_path *
+ospf_path_new ()
+{
+  struct ospf_path *new;
+
+  new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
+
+  return new;
+}
+
+struct ospf_path *
+ospf_path_dup (struct ospf_path *path)
+{
+  struct ospf_path *new;
+
+  new = ospf_path_new ();
+  memcpy (new, path, sizeof (struct ospf_path));
+
+  return new;
+}
+
+void
+ospf_path_free (struct ospf_path *op)
+{
+  XFREE (MTYPE_OSPF_PATH, op);
+}
+
+void
+ospf_route_delete (struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((or = rn->info) != NULL)
+      {
+	if (or->type == OSPF_DESTINATION_NETWORK)
+	  ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p,
+				       or);
+	else if (or->type == OSPF_DESTINATION_DISCARD)
+	  ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
+      }
+}
+
+void
+ospf_route_table_free (struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((or = rn->info) != NULL)
+      {
+	ospf_route_free (or);
+
+	rn->info = NULL;
+	route_unlock_node (rn);
+      }
+
+   route_table_finish (rt);
+}
+
+/* If a prefix and a nexthop match any route in the routing table,
+   then return 1, otherwise return 0. */
+int
+ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
+		       struct ospf_route *newor)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct ospf_path *op;
+  struct ospf_path *newop;
+  listnode n1;
+  listnode n2;
+
+  if (! rt || ! prefix)
+    return 0;
+
+   rn = route_node_lookup (rt, (struct prefix *) prefix);
+   if (! rn || ! rn->info)
+     return 0;
+ 
+   route_unlock_node (rn);
+
+   or = rn->info;
+   if (or->type == newor->type && or->cost == newor->cost)
+     {
+       if (or->type == OSPF_DESTINATION_NETWORK)
+	 {
+	   if (or->path->count != newor->path->count)
+	     return 0;
+
+	   /* Check each path. */
+	   for (n1 = listhead (or->path), n2 = listhead (newor->path);
+		n1 && n2; nextnode (n1), nextnode (n2))
+	     { 
+	       op = getdata (n1);
+	       newop = getdata (n2);
+
+	       if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
+		 return 0;
+	     }
+	   return 1;
+	 }
+       else if (prefix_same (&rn->p, (struct prefix *) prefix))
+	 return 1;
+     }
+  return 0;
+}
+
+/* rt: Old, cmprt: New */
+void
+ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((or = rn->info) != NULL) 
+      if (or->path_type == OSPF_PATH_INTRA_AREA ||
+	  or->path_type == OSPF_PATH_INTER_AREA)
+	{
+	  if (or->type == OSPF_DESTINATION_NETWORK)
+	    {
+	      if (! ospf_route_match_same (cmprt, 
+					   (struct prefix_ipv4 *) &rn->p, or))
+		ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
+	    }
+	  else if (or->type == OSPF_DESTINATION_DISCARD)
+	    if (! ospf_route_match_same (cmprt,
+					 (struct prefix_ipv4 *) &rn->p, or))
+	      ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
+	}
+}
+
+/* Install routes to table. */
+void
+ospf_route_install (struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+
+  /* rt contains new routing table, new_table contains an old one.
+     updating pointers */
+  if (ospf_top->old_table)
+    ospf_route_table_free (ospf_top->old_table);
+ 
+  ospf_top->old_table = ospf_top->new_table;
+  ospf_top->new_table = rt;
+
+  /* Delete old routes. */
+  if (ospf_top->old_table)
+    ospf_route_delete_uniq (ospf_top->old_table, rt);
+
+  /* Install new routes. */
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((or = rn->info) != NULL)
+      {
+	if (or->type == OSPF_DESTINATION_NETWORK)
+	  {
+	    if (! ospf_route_match_same (ospf_top->old_table,
+					 (struct prefix_ipv4 *)&rn->p, or))
+	      ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
+	  }
+	else if (or->type == OSPF_DESTINATION_DISCARD)
+	  if (! ospf_route_match_same (ospf_top->old_table,
+				       (struct prefix_ipv4 *) &rn->p, or))
+	    ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
+      }
+}
+
+void
+ospf_intra_route_add (struct route_table *rt, struct vertex *v,
+		      struct ospf_area *area)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct prefix_ipv4 p;
+  struct ospf_path *path;
+  struct vertex_nexthop *nexthop;
+  listnode nnode;
+
+  p.family = AF_INET;
+  p.prefix = v->id;
+  if (v->type == OSPF_VERTEX_ROUTER)
+    p.prefixlen = IPV4_MAX_BITLEN;
+  else
+    {
+      struct network_lsa *lsa = (struct network_lsa *) v->lsa;
+      p.prefixlen = ip_masklen (lsa->mask);
+    }
+  apply_mask_ipv4 (&p);
+
+  rn = route_node_get (rt, (struct prefix *) &p);
+  if (rn->info)
+    {
+      zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id));
+      route_unlock_node (rn);
+      return;
+    }
+
+  or = ospf_route_new ();
+
+  if (v->type == OSPF_VERTEX_NETWORK)
+    {
+      or->type = OSPF_DESTINATION_NETWORK;
+      or->path = list_new ();
+
+      for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
+	{
+	  nexthop = getdata (nnode);
+	  path = ospf_path_new ();
+	  path->nexthop = nexthop->router;
+	  listnode_add (or->path, path);
+	}
+    }
+  else
+    or->type = OSPF_DESTINATION_ROUTER;
+
+  or->id = v->id;
+  or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+  or->u.std.external_routing= area->external_routing;
+#endif /* HAVE_NSSA */
+  or->path_type = OSPF_PATH_INTRA_AREA;
+  or->cost = v->distance;
+
+  rn->info = or;
+}
+
+/* RFC2328 16.1. (4). For "router". */
+void
+ospf_intra_add_router (struct route_table *rt, struct vertex *v,
+		       struct ospf_area *area)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct prefix_ipv4 p;
+  struct router_lsa *lsa;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_intra_add_router: Start");
+
+  lsa = (struct router_lsa *) v->lsa;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_intra_add_router: LS ID: %s",
+	       inet_ntoa (lsa->header.id));
+
+  ospf_vl_up_check (area, lsa->header.id, v);
+
+  if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
+    area->shortcut_capability = 0;
+
+  /* If the newly added vertex is an area border router or AS boundary
+     router, a routing table entry is added whose destination type is
+     "router". */
+  if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_intra_add_router: "
+		   "this router is neither ASBR nor ABR, skipping it");
+      return;
+    }
+
+  /* Update ABR and ASBR count in this area. */
+  if (IS_ROUTER_LSA_BORDER (lsa))
+    area->abr_count++;
+  if (IS_ROUTER_LSA_EXTERNAL (lsa))
+    area->asbr_count++;
+
+  /* The Options field found in the associated router-LSA is copied
+     into the routing table entry's Optional capabilities field. Call
+     the newly added vertex Router X. */
+  or = ospf_route_new ();
+
+  or->id = v->id;
+  or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+  or->u.std.external_routing = area->external_routing;
+#endif /* HAVE_NSSA */
+  or->path_type = OSPF_PATH_INTRA_AREA;
+  or->cost = v->distance;
+  or->type = OSPF_DESTINATION_ROUTER;
+  or->u.std.origin = (struct lsa_header *) lsa;
+  or->u.std.options = lsa->header.options;
+  or->u.std.flags = lsa->flags;
+
+  /* If Router X is the endpoint of one of the calculating router's
+     virtual links, and the virtual link uses Area A as Transit area:
+     the virtual link is declared up, the IP address of the virtual
+     interface is set to the IP address of the outgoing interface
+     calculated above for Router X, and the virtual neighbor's IP
+     address is set to Router X's interface address (contained in
+     Router X's router-LSA) that points back to the root of the
+     shortest- path tree; equivalently, this is the interface that
+     points back to Router X's parent vertex on the shortest-path tree
+     (similar to the calculation in Section 16.1.1). */
+
+  p.family = AF_INET;
+  p.prefix = v->id;
+  p.prefixlen = IPV4_MAX_BITLEN;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_intra_add_router: talking about %s/%d",
+	       inet_ntoa (p.prefix), p.prefixlen);
+
+  rn = route_node_get (rt, (struct prefix *) &p);
+
+  /* Note that we keep all routes to ABRs and ASBRs, not only the best */
+  if (rn->info == NULL)
+    rn->info = list_new ();
+  else
+    route_unlock_node (rn);
+
+  ospf_route_copy_nexthops_from_vertex (or, v);
+
+  listnode_add (rn->info, or);
+
+  zlog_info ("ospf_intra_add_router: Start");
+}
+
+/* RFC2328 16.1. (4).  For transit network. */
+void
+ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
+			struct ospf_area *area)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct prefix_ipv4 p;
+  struct network_lsa *lsa;
+
+  lsa = (struct network_lsa*) v->lsa;
+
+  /* If the newly added vertex is a transit network, the routing table
+     entry for the network is located.  The entry's Destination ID is
+     the IP network number, which can be obtained by masking the
+     Vertex ID (Link State ID) with its associated subnet mask (found
+     in the body of the associated network-LSA). */
+  p.family = AF_INET;
+  p.prefix = v->id;
+  p.prefixlen = ip_masklen (lsa->mask);
+  apply_mask_ipv4 (&p);
+
+  rn = route_node_get (rt, (struct prefix *) &p);
+
+  /* If the routing table entry already exists (i.e., there is already
+     an intra-area route to the destination installed in the routing
+     table), multiple vertices have mapped to the same IP network.
+     For example, this can occur when a new Designated Router is being
+     established.  In this case, the current routing table entry
+     should be overwritten if and only if the newly found path is just
+     as short and the current routing table entry's Link State Origin
+     has a smaller Link State ID than the newly added vertex' LSA. */
+  if (rn->info)
+    {
+      struct ospf_route *cur_or;
+
+      route_unlock_node (rn);
+      cur_or = rn->info;
+
+      if (v->distance > cur_or->cost ||
+          IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
+	return;
+      
+      ospf_route_free (rn->info);
+    }
+
+  or = ospf_route_new ();
+
+  or->id = v->id;
+  or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+  or->u.std.external_routing = area->external_routing;
+#endif /* HAVE_NSSA */
+  or->path_type = OSPF_PATH_INTRA_AREA;
+  or->cost = v->distance;
+  or->type = OSPF_DESTINATION_NETWORK;
+  or->u.std.origin = (struct lsa_header *) lsa;
+
+  ospf_route_copy_nexthops_from_vertex (or, v);
+  
+  rn->info = or;
+}
+
+/* RFC2328 16.1. second stage. */
+void
+ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
+		     struct vertex *v, struct ospf_area *area)
+{
+  u_int32_t cost;
+  struct route_node *rn;
+  struct ospf_route *or;
+  struct prefix_ipv4 p;
+  struct router_lsa *lsa;
+  struct ospf_interface *oi;
+  struct ospf_path *path;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_intra_add_stub(): Start");
+
+  lsa = (struct router_lsa *) v->lsa;
+
+  p.family = AF_INET;
+  p.prefix = link->link_id;
+  p.prefixlen = ip_masklen (link->link_data);
+  apply_mask_ipv4 (&p);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_intra_add_stub(): processing route to %s/%d",  
+	       inet_ntoa (p.prefix), p.prefixlen);
+
+  /* (1) Calculate the distance D of stub network from the root.  D is
+     equal to the distance from the root to the router vertex
+     (calculated in stage 1), plus the stub network link's advertised
+     cost. */
+  cost = v->distance + ntohs (link->m[0].metric);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_intra_add_stub(): calculated cost is %d + %d = %d", 
+	       v->distance, ntohs(link->m[0].metric), cost);
+
+  rn = route_node_get (rt, (struct prefix *) &p);
+
+  /* Lookup current routing table. */
+  if (rn->info)
+    {
+      struct ospf_route *cur_or;
+
+      route_unlock_node (rn);
+
+      cur_or = rn->info;
+
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_intra_add_stub(): "
+		   "another route to the same prefix found");
+
+      /* Compare this distance to the current best cost to the stub
+	 network.  This is done by looking up the stub network's
+	 current routing table entry.  If the calculated distance D is
+	 larger, go on to examine the next stub network link in the
+	 LSA. */
+      if (cost > cur_or->cost)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_intra_add_stub(): old route is better, exit");
+	  return;
+	}
+
+      /* (2) If this step is reached, the stub network's routing table
+	 entry must be updated.  Calculate the set of next hops that
+	 would result from using the stub network link.  This
+	 calculation is shown in Section 16.1.1; input to this
+	 calculation is the destination (the stub network) and the
+	 parent vertex (the router vertex). If the distance D is the
+	 same as the current routing table cost, simply add this set
+	 of next hops to the routing table entry's list of next hops.
+	 In this case, the routing table already has a Link State
+	 Origin.  If this Link State Origin is a router-LSA whose Link
+	 State ID is smaller than V's Router ID, reset the Link State
+	 Origin to V's router-LSA. */
+
+      if (cost == cur_or->cost)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_intra_add_stub(): routes are equal, merge");
+
+	  ospf_route_copy_nexthops_from_vertex (cur_or, v);
+
+	  if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
+	    cur_or->u.std.origin = (struct lsa_header *) lsa;
+	  return;
+	}
+
+      /* Otherwise D is smaller than the routing table cost.
+	 Overwrite the current routing table entry by setting the
+	 routing table entry's cost to D, and by setting the entry's
+	 list of next hops to the newly calculated set.  Set the
+	 routing table entry's Link State Origin to V's router-LSA.
+	 Then go on to examine the next stub network link. */
+
+      if (cost < cur_or->cost)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_intra_add_stub(): new route is better, set it");
+
+	  cur_or->cost = cost;
+
+	  list_delete (cur_or->path);
+	  cur_or->path = NULL;
+
+	  ospf_route_copy_nexthops_from_vertex (cur_or, v);
+
+	  cur_or->u.std.origin = (struct lsa_header *) lsa;
+	  return;
+	}
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_intra_add_stub(): installing new route");
+
+  or = ospf_route_new ();
+
+  or->id = v->id;
+  or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+  or->u.std.external_routing = area->external_routing;
+#endif /* HAVE_NSSA */
+  or->path_type = OSPF_PATH_INTRA_AREA;
+  or->cost = cost;
+  or->type = OSPF_DESTINATION_NETWORK;
+  or->u.std.origin = (struct lsa_header *) lsa;
+  or->path = list_new ();
+
+  /* Nexthop is depend on connection type. */
+  if (v != area->spf)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_intra_add_stub(): this network is on remote router");
+      ospf_route_copy_nexthops_from_vertex (or, v);
+    }
+  else
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_intra_add_stub(): this network is on this router");
+
+      if ((oi = ospf_if_lookup_by_prefix (&p)))
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_intra_add_stub(): the interface is %s",
+		       IF_NAME (oi));
+
+	  path = ospf_path_new ();
+	  path->nexthop.s_addr = 0;
+	  path->oi = oi;
+	  listnode_add (or->path, path);
+	}
+      else
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_intra_add_stub(): where's the interface ?");
+	}
+    }
+
+  rn->info = or;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info("ospf_intra_add_stub(): Stop");
+}
+
+char *ospf_path_type_str[] =
+{
+  "unknown-type",
+  "intra-area",
+  "inter-area",
+  "type1-external",
+  "type2-external"
+};
+
+void
+ospf_route_table_dump (struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  char buf1[BUFSIZ];
+  char buf2[BUFSIZ];
+  listnode pnode;
+  struct ospf_path *path;
+
+#if 0
+  zlog_info ("Type   Dest   Area   Path	 Type	 Cost	Next	 Adv.");
+  zlog_info ("					Hop(s)	 Router(s)");
+#endif /* 0 */
+
+  zlog_info ("========== OSPF routing table ==========");
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((or = rn->info) != NULL)
+      {
+        if (or->type == OSPF_DESTINATION_NETWORK)
+	  {
+	    zlog_info ("N %s/%d\t%s\t%s\t%d", 
+		       inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
+		       rn->p.prefixlen,
+		       inet_ntop (AF_INET, &or->u.std.area_id, buf2,
+				  BUFSIZ),
+		       ospf_path_type_str[or->path_type],
+		       or->cost);
+	    for (pnode = listhead (or->path); pnode; nextnode (pnode))
+	      {
+		path = getdata (pnode);
+		zlog_info ("  -> %s", inet_ntoa (path->nexthop));
+	      }
+	  }
+        else
+	  zlog_info ("R %s\t%s\t%s\t%d", 
+		     inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
+		     inet_ntop (AF_INET, &or->u.std.area_id, buf2,
+				BUFSIZ),
+		     ospf_path_type_str[or->path_type],
+		     or->cost);
+      }
+  zlog_info ("========================================");
+}
+
+void
+ospf_terminate ()
+{
+  if (ospf_top)
+    {
+      if (ospf_top->new_table)
+	ospf_route_delete (ospf_top->new_table);
+      if (ospf_top->old_external_route)
+	ospf_route_delete (ospf_top->old_external_route);
+    }
+}
+
+/* This is 16.4.1 implementation.
+   o Intra-area paths using non-backbone areas are always the most preferred.
+   o The other paths, intra-area backbone paths and inter-area paths,
+     are of equal preference. */
+int
+ospf_asbr_route_cmp (struct ospf_route *r1, struct ospf_route *r2)
+{
+  u_char r1_type, r2_type;
+
+  r1_type = r1->path_type;
+  r2_type = r2->path_type;
+
+  /* If RFC1583Compat flag is on -- all paths are equal. */
+  if (CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+    return 0;
+
+  /* r1/r2 itself is backbone, and it's Inter-area path. */
+  if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
+    r1_type = OSPF_PATH_INTER_AREA;
+  if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
+    r2_type = OSPF_PATH_INTER_AREA;
+
+  return (r1_type - r2_type);
+}
+
+/* Compare two routes.
+ ret <  0 -- r1 is better.
+ ret == 0 -- r1 and r2 are the same.
+ ret >  0 -- r2 is better. */
+int
+ospf_route_cmp (struct ospf_route *r1, struct ospf_route *r2)
+{
+  int ret = 0;
+
+  /* Path types of r1 and r2 are not the same. */
+  if ((ret = (r1->path_type - r2->path_type)))
+    return ret;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Route[Compare]: Path types are the same.");
+  /* Path types are the same, compare any cost. */
+  switch (r1->path_type)
+    {
+    case OSPF_PATH_INTRA_AREA:
+    case OSPF_PATH_INTER_AREA:
+      break;
+    case OSPF_PATH_TYPE1_EXTERNAL:
+      if (!CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+	{
+	  ret = ospf_asbr_route_cmp (r1->u.ext.asbr, r2->u.ext.asbr);
+	  if (ret != 0)
+	    return ret;
+	}
+      break;
+    case OSPF_PATH_TYPE2_EXTERNAL:
+      if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
+	return ret;
+
+      if (!CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+	{
+	  ret = ospf_asbr_route_cmp (r1->u.ext.asbr, r2->u.ext.asbr);
+	  if (ret != 0)
+	    return ret;
+	}
+      break;
+    }      
+
+  /* Anyway, compare the costs. */
+  return (r1->cost - r2->cost);
+}
+
+int
+ospf_path_exist (struct list *plist, struct in_addr nexthop,
+		 struct ospf_interface *oi)
+{
+  listnode node;
+  struct ospf_path *path;
+
+  for (node = listhead (plist); node; nextnode (node))
+    {
+      path = node->data;
+
+      if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
+	return 1;
+    }
+  return 0;
+}
+
+void
+ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
+				      struct vertex *v)
+{
+  listnode nnode;
+  struct ospf_path *path;
+  struct vertex_nexthop *nexthop;
+
+  if (to->path == NULL)
+    to->path = list_new ();
+
+  for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
+    {
+      nexthop = getdata (nnode);
+
+      if (nexthop->oi != NULL) 
+	{
+	  if (! ospf_path_exist (to->path, nexthop->router, nexthop->oi))
+	    {
+	      path = ospf_path_new ();
+	      path->nexthop = nexthop->router;
+	      path->oi = nexthop->oi;
+	      listnode_add (to->path, path);
+	    }
+	}
+    }
+}
+
+struct ospf_path *
+ospf_path_lookup (list plist, struct ospf_path *path)
+{
+  listnode node;
+
+  for (node = listhead (plist); node; nextnode (node))
+    {
+      struct ospf_path *op = node->data;
+
+      if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
+	  IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
+	return op;
+    }
+
+  return NULL;
+}
+
+void
+ospf_route_copy_nexthops (struct ospf_route *to, list from)
+{
+  listnode node;
+
+  if (to->path == NULL)
+    to->path = list_new ();
+
+  for (node = listhead (from); node; nextnode (node))
+    /* The same routes are just discarded. */
+    if (!ospf_path_lookup (to->path, node->data))
+      listnode_add (to->path, ospf_path_dup (node->data));
+}
+
+void
+ospf_route_subst_nexthops (struct ospf_route *to, list from)
+{
+  listnode node;
+  struct ospf_path *op;
+
+  for (node = listhead (to->path); node; nextnode (node))
+    if ((op = getdata (node)) != NULL)
+      {
+	ospf_path_free (op);
+	node->data = NULL;
+      }
+
+  list_delete_all_node (to->path);
+  ospf_route_copy_nexthops (to, from);
+}
+
+void
+ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
+		  struct ospf_route *over)
+{
+  route_lock_node (rn);
+  ospf_route_free (rn->info);
+
+  ospf_route_copy_nexthops (new_or, over->path);
+  rn->info = new_or;
+  route_unlock_node (rn);
+}
+
+void
+ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
+		struct ospf_route *new_or, struct ospf_route *over)
+{
+  struct route_node *rn;
+
+  rn = route_node_get (rt, (struct prefix *) p);
+
+  ospf_route_copy_nexthops (new_or, over->path);
+
+  if (rn->info)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_route_add(): something's wrong !");
+      route_unlock_node (rn);
+      return;
+    }
+
+  rn->info = new_or;
+}
+
+void
+ospf_prune_unreachable_networks (struct route_table *rt)
+{
+  struct route_node *rn, *next;
+  struct ospf_route *or;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Pruning unreachable networks");
+
+  for (rn = route_top (rt); rn; rn = next)
+    {
+      next = route_next (rn);
+      if (rn->info != NULL)
+	{
+	  or = rn->info;
+	  if (listcount (or->path) == 0)
+	    {
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("Pruning route to %s/%d",
+			   inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
+
+	      ospf_route_free (or);
+	      rn->info = NULL;
+	      route_unlock_node (rn);
+	    }
+	}
+    }
+}
+
+void
+ospf_prune_unreachable_routers (struct route_table *rtrs)
+{
+  struct route_node *rn, *next;
+  struct ospf_route *or;
+  listnode node, nnext;
+  list paths;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Pruning unreachable routers");
+
+  for (rn = route_top (rtrs); rn; rn = next)
+    {
+      next = route_next (rn);
+      if ((paths = rn->info) == NULL)
+	continue;
+
+      for (node = listhead (paths); node; node = nnext) 
+	{
+	  nnext = node->next;
+
+	  or = getdata (node);
+
+	  if (listcount (or->path) == 0)
+	    {
+	      if (IS_DEBUG_OSPF_EVENT)
+		{
+		  zlog_info ("Pruning route to rtr %s",
+			     inet_ntoa (rn->p.u.prefix4));
+		  zlog_info ("               via area %s",
+			     inet_ntoa (or->u.std.area_id));
+		}
+
+	      listnode_delete (paths, or);
+	      ospf_route_free (or);
+	    }
+	}
+
+      if (listcount (paths) == 0)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
+
+	  list_delete (paths);
+	  rn->info = NULL;
+	  route_unlock_node (rn);
+	}
+    }
+}
+
+int
+ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
+			struct prefix_ipv4 *p)
+{
+  struct route_node *rn;
+  struct ospf_route *or, *new_or;
+
+  rn = route_node_get (rt, (struct prefix *) p);
+
+  if (rn == NULL)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_add_discard_route(): router installation error");
+      return 0;
+    }
+
+  if (rn->info) /* If the route to the same destination is found */
+    {
+      route_unlock_node (rn);
+
+      or = rn->info;
+
+      if (or->path_type == OSPF_PATH_INTRA_AREA)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_add_discard_route(): "
+		       "an intra-area route exists");
+	  return 0;
+	}
+
+      if (or->type == OSPF_DESTINATION_DISCARD)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_add_discard_route(): "
+		       "discard entry already installed");
+	  return 0;
+	}
+
+      ospf_route_free (rn->info);
+  }
+
+  new_or = ospf_route_new ();
+  new_or->type = OSPF_DESTINATION_DISCARD;
+  new_or->id.s_addr = 0;
+  new_or->cost = 0;
+  new_or->u.std.area_id = area->area_id;
+#ifdef HAVE_NSSA
+  new_or->u.std.external_routing = area->external_routing;
+#endif /* HAVE_NSSA */
+  new_or->path_type = OSPF_PATH_INTER_AREA;
+  rn->info = new_or;
+
+  ospf_zebra_add_discard (p);
+
+  return 1;
+}
+
+void
+ospf_delete_discard_route (struct prefix_ipv4 *p)
+{
+  ospf_zebra_delete_discard(p);
+}
+
diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h
new file mode 100644
index 0000000..81f59c4
--- /dev/null
+++ b/ospfd/ospf_route.h
@@ -0,0 +1,165 @@
+/*
+ * OSPF routing table.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_ROUTE_H
+#define _ZEBRA_OSPF_ROUTE_H
+
+#define OSPF_DESTINATION_ROUTER		1
+#define OSPF_DESTINATION_NETWORK	2
+#define OSPF_DESTINATION_DISCARD	3
+
+#define OSPF_PATH_MIN			0
+#define OSPF_PATH_INTRA_AREA		1
+#define OSPF_PATH_INTER_AREA		2
+#define OSPF_PATH_TYPE1_EXTERNAL	3
+#define OSPF_PATH_TYPE2_EXTERNAL	4
+#define OSPF_PATH_MAX			5
+
+/* OSPF Path. */
+struct ospf_path
+{
+  struct in_addr nexthop;
+  struct in_addr adv_router;
+  struct ospf_interface *oi;
+};
+
+/* Below is the structure linked to every
+   route node. Note that for Network routing
+   entries a single ospf_route is kept, while
+   for ABRs and ASBRs (Router routing entries),
+   we link an instance of ospf_router_route
+   where a list of paths is maintained, so
+
+   nr->info is a (struct ospf_route *) for OSPF_DESTINATION_NETWORK
+   but
+   nr->info is a (struct ospf_router_route *) for OSPF_DESTINATION_ROUTER
+*/
+
+struct route_standard
+{
+  /* Link Sate Origin. */
+  struct lsa_header *origin;
+
+  /* Associated Area. */
+  struct in_addr area_id;	/* The area the route belongs to */
+
+#ifdef HAVE_NSSA
+  /*  Area Type */
+  int external_routing;
+#endif /* HAVE_NSSA */
+
+  /* Optional Capability. */
+  u_char options;		/* Get from LSA header. */
+
+  /*  */
+  u_char flags; 		/* From router-LSA */
+};
+
+struct route_external
+{
+  /* Link State Origin. */
+  struct ospf_lsa *origin;
+
+  /* Link State Cost Type2. */
+  u_int32_t type2_cost;
+
+  /* Tag value. */
+  u_int32_t tag;
+
+  /* ASBR route. */
+  struct ospf_route *asbr;
+};
+
+struct ospf_route
+{
+  /* Create time. */
+  time_t ctime;
+
+  /* Modified time. */
+  time_t mtime;
+
+  /* Destination Type. */
+  u_char type;
+
+  /* Destination ID. */		/* i.e. Link State ID. */
+  struct in_addr id;
+
+  /* Address Mask. */
+  struct in_addr mask;		/* Only valid for networks. */
+
+  /* Path Type. */
+  u_char path_type;
+
+  /* List of Paths. */
+  list path;
+
+  /* Link State Cost. */
+  u_int32_t cost;		/* i.e. metric. */
+
+  /* Route specific info. */
+  union
+  {
+    struct route_standard std;
+    struct route_external ext;
+  } u;
+};
+
+struct ospf_path *ospf_path_new ();
+void ospf_path_free (struct ospf_path *op);
+struct ospf_path *ospf_path_lookup (list, struct ospf_path *);
+struct ospf_route *ospf_route_new ();
+void ospf_route_free (struct ospf_route *or);
+void ospf_route_delete (struct route_table *rt);
+void ospf_route_table_free (struct route_table *rt);
+
+void ospf_route_install (struct route_table *);
+void ospf_route_table_dump (struct route_table *);
+
+void ospf_intra_add_router (struct route_table *, struct vertex *,
+			    struct ospf_area *);
+
+void ospf_intra_add_transit (struct route_table *, struct vertex *,
+			     struct ospf_area *);
+
+void ospf_intra_add_stub (struct route_table *, struct router_lsa_link *,
+ 		          struct vertex *, struct ospf_area *);
+
+int ospf_route_cmp (struct ospf_route *, struct ospf_route *);
+void ospf_route_copy_nexthops (struct ospf_route *, list);
+void ospf_route_copy_nexthops_from_vertex (struct ospf_route *,
+					   struct vertex * );
+
+void ospf_route_subst (struct route_node *, struct ospf_route *,
+		       struct ospf_route *);
+void ospf_route_add (struct route_table *, struct prefix_ipv4 *,
+		     struct ospf_route *, struct ospf_route *);
+
+void ospf_route_subst_nexthops (struct ospf_route *, list);
+void ospf_prune_unreachable_networks (struct route_table *);
+void ospf_prune_unreachable_routers (struct route_table *);
+int ospf_add_discard_route (struct route_table *, struct ospf_area *, 
+			    struct prefix_ipv4 *);
+void ospf_delete_discard_route (struct prefix_ipv4 *);
+int ospf_route_match_same (struct route_table *, struct prefix_ipv4 *,
+			   struct ospf_route *);
+
+#endif /* _ZEBRA_OSPF_ROUTE_H */
diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c
new file mode 100644
index 0000000..a2b257f
--- /dev/null
+++ b/ospfd/ospf_routemap.c
@@ -0,0 +1,828 @@
+/*
+ * Route map function of ospfd.
+ * Copyright (C) 2000 IP Infusion Inc.
+ *
+ * Written by Toshiaki Takada.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "memory.h"
+#include "prefix.h"
+#include "table.h"
+#include "routemap.h"
+#include "command.h"
+#include "log.h"
+#include "plist.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_zebra.h"
+
+/* Hook function for updating route_map assignment. */
+void
+ospf_route_map_update (char *name)
+{
+  int type;
+
+  /* If OSPF instatnce does not exist, return right now. */
+  if (!ospf_top)
+    return;
+
+  /* Update route-map */
+  for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
+    {
+      if (ROUTEMAP_NAME (type) && strcmp (ROUTEMAP_NAME (type), name) == 0)
+	{
+	  /* Keep old route-map. */
+	  struct route_map *old = ROUTEMAP (type);
+
+	  /* Update route-map. */
+	  ROUTEMAP (type) = route_map_lookup_by_name (ROUTEMAP_NAME (type));
+
+	  /* No update for this distribute type. */
+	  if (old == NULL && ROUTEMAP (type) == NULL)
+	    continue;
+
+	  ospf_distribute_list_update (type);
+	}
+    }
+}
+
+void
+ospf_route_map_event (route_map_event_t event, char *name)
+{
+  int type;
+
+  /* If OSPF instatnce does not exist, return right now. */
+  if (!ospf_top)
+    return;
+
+  /* Update route-map. */
+  for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
+    {
+      if (ROUTEMAP_NAME (type) &&  ROUTEMAP (type) &&
+          !strcmp (ROUTEMAP_NAME (type), name))
+        {
+          ospf_distribute_list_update (type);
+        }
+    }
+}
+
+/* Delete rip route map rule. */
+int
+ospf_route_match_delete (struct vty *vty, struct route_map_index *index,
+			 char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_delete_match (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+        {
+        case RMAP_RULE_MISSING:
+          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        case RMAP_COMPILE_ERROR:
+          vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        }
+    }
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_route_match_add (struct vty *vty, struct route_map_index *index,
+		      char *command, char *arg)
+{                                                                              
+  int ret;
+
+  ret = route_map_add_match (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+        {
+        case RMAP_RULE_MISSING:
+          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        case RMAP_COMPILE_ERROR:
+          vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        }
+    }
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_route_set_add (struct vty *vty, struct route_map_index *index,
+		    char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_add_set (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+        {
+        case RMAP_RULE_MISSING:
+          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        case RMAP_COMPILE_ERROR:
+          vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        }
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* Delete rip route map rule. */
+int
+ospf_route_set_delete (struct vty *vty, struct route_map_index *index,
+		       char *command, char *arg)
+{                                              
+  int ret;
+
+  ret = route_map_delete_set (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+        {
+        case RMAP_RULE_MISSING:
+          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        case RMAP_COMPILE_ERROR:
+          vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+          return CMD_WARNING;
+          break;
+        }
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* `match ip netxthop ' */
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_ip_nexthop (void *rule, struct prefix *prefix,
+			route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+  struct external_info *ei = object;
+  struct prefix_ipv4 p;
+
+  if (type == RMAP_OSPF)
+    {
+      p.family = AF_INET;
+      p.prefix = ei->nexthop;
+      p.prefixlen = IPV4_MAX_BITLEN;
+
+      alist = access_list_lookup (AFI_IP, (char *) rule);
+      if (alist == NULL)
+        return RMAP_NOMATCH;
+
+      return (access_list_apply (alist, &p) == FILTER_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `ip next-hop' match statement. `arg' should be
+   access-list name. */
+void *
+route_match_ip_nexthop_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_ip_nexthop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for metric matching. */
+struct route_map_rule_cmd route_match_ip_nexthop_cmd =
+{
+  "ip next-hop",
+  route_match_ip_nexthop,
+  route_match_ip_nexthop_compile,
+  route_match_ip_nexthop_free
+};
+
+/* `match ip next-hop prefix-list PREFIX_LIST' */
+
+route_map_result_t
+route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
+                                    route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+  struct external_info *ei = object;
+  struct prefix_ipv4 p;
+
+  if (type == RMAP_OSPF)
+    {
+      p.family = AF_INET;
+      p.prefix = ei->nexthop;
+      p.prefixlen = IPV4_MAX_BITLEN;
+
+      plist = prefix_list_lookup (AFI_IP, (char *) rule);
+      if (plist == NULL)
+        return RMAP_NOMATCH;
+
+      return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ip_next_hop_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ip_next_hop_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
+{
+  "ip next-hop prefix-list",
+  route_match_ip_next_hop_prefix_list,
+  route_match_ip_next_hop_prefix_list_compile,
+  route_match_ip_next_hop_prefix_list_free
+};
+
+/* `match ip address IP_ACCESS_LIST' */
+/* Match function should return 1 if match is success else return
+   zero. */
+route_map_result_t
+route_match_ip_address (void *rule, struct prefix *prefix,
+                        route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+  /* struct prefix_ipv4 match; */
+
+  if (type == RMAP_OSPF)
+    {
+      alist = access_list_lookup (AFI_IP, (char *) rule);
+      if (alist == NULL)
+        return RMAP_NOMATCH;
+
+      return (access_list_apply (alist, prefix) == FILTER_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `ip address' match statement.  `arg' should be
+   access-list name. */
+void *
+route_match_ip_address_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_ip_address_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_ip_address_cmd =
+{
+  "ip address",
+  route_match_ip_address,
+  route_match_ip_address_compile,
+  route_match_ip_address_free
+};
+
+/* `match ip address prefix-list PREFIX_LIST' */
+route_map_result_t
+route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
+                                    route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+
+  if (type == RMAP_OSPF)
+    {
+      plist = prefix_list_lookup (AFI_IP, (char *) rule);
+      if (plist == NULL)
+        return RMAP_NOMATCH;
+
+      return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ip_address_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ip_address_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
+{
+  "ip address prefix-list",
+  route_match_ip_address_prefix_list,
+  route_match_ip_address_prefix_list_compile,
+  route_match_ip_address_prefix_list_free
+};
+
+/* `match interface IFNAME' */
+/* Match function should return 1 if match is success else return
+   zero. */
+route_map_result_t
+route_match_interface (void *rule, struct prefix *prefix,
+		       route_map_object_t type, void *object)
+{
+  struct interface *ifp;
+  struct external_info *ei;
+
+  if (type == RMAP_OSPF)
+    {
+      ei = object;
+      ifp = if_lookup_by_name ((char *)rule);
+
+      if (ifp == NULL || ifp->ifindex != ei->ifindex)
+	return RMAP_NOMATCH;
+
+      return RMAP_MATCH;
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `interface' match statement.  `arg' should be
+   interface name. */
+void *
+route_match_interface_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `interface' value. */
+void
+route_match_interface_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_interface_cmd =
+{
+  "interface",
+  route_match_interface,
+  route_match_interface_compile,
+  route_match_interface_free
+};
+
+/* `set metric METRIC' */
+/* Set metric to attribute. */
+route_map_result_t
+route_set_metric (void *rule, struct prefix *prefix,
+                  route_map_object_t type, void *object)
+{
+  u_int32_t *metric;
+  struct external_info *ei;
+
+  if (type == RMAP_OSPF)
+    {
+      /* Fetch routemap's rule information. */
+      metric = rule;
+      ei = object;
+
+      /* Set metric out value. */
+      ei->route_map_set.metric = *metric;
+    }
+  return RMAP_OKAY;
+}
+
+/* set metric compilation. */
+void *
+route_set_metric_compile (char *arg)
+{
+  u_int32_t *metric;
+
+  metric = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  *metric = atoi (arg);
+
+  if (*metric >= 0)
+    return metric;
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
+  return NULL;
+}
+
+/* Free route map's compiled `set metric' value. */
+void
+route_set_metric_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_metric_cmd =
+{
+  "metric",
+  route_set_metric,
+  route_set_metric_compile,
+  route_set_metric_free,
+};
+
+/* `set metric-type TYPE' */
+/* Set metric-type to attribute. */
+route_map_result_t
+route_set_metric_type (void *rule, struct prefix *prefix,
+		       route_map_object_t type, void *object)
+{
+  u_int32_t *metric_type;
+  struct external_info *ei;
+
+  if (type == RMAP_OSPF)
+    {
+      /* Fetch routemap's rule information. */
+      metric_type = rule;
+      ei = object;
+
+      /* Set metric out value. */
+      ei->route_map_set.metric_type = *metric_type;
+    }
+  return RMAP_OKAY;
+}
+
+/* set metric-type compilation. */
+void *
+route_set_metric_type_compile (char *arg)
+{
+  u_int32_t *metric_type;
+
+  metric_type = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  if (strcmp (arg, "type-1") == 0)
+    *metric_type = EXTERNAL_METRIC_TYPE_1;
+  else if (strcmp (arg, "type-2") == 0)
+    *metric_type = EXTERNAL_METRIC_TYPE_2;
+
+  if (*metric_type == EXTERNAL_METRIC_TYPE_1 ||
+      *metric_type == EXTERNAL_METRIC_TYPE_2)
+    return metric_type;
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, metric_type);
+  return NULL;
+}
+
+/* Free route map's compiled `set metric-type' value. */
+void
+route_set_metric_type_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_metric_type_cmd =
+{
+  "metric-type",
+  route_set_metric_type,
+  route_set_metric_type_compile,
+  route_set_metric_type_free,
+};
+
+DEFUN (match_ip_nexthop,
+       match_ip_nexthop_cmd,
+       "match ip next-hop (<1-199>|<1300-2699>|WORD)",
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP access-list name\n")
+{
+  return ospf_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+DEFUN (no_match_ip_nexthop,
+       no_match_ip_nexthop_cmd,
+       "no match ip next-hop",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n")
+{
+  if (argc == 0)
+    return ospf_route_match_delete (vty, vty->index, "ip next-hop", NULL);
+
+  return ospf_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+ALIAS (no_match_ip_nexthop,
+       no_match_ip_nexthop_val_cmd,
+       "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP access-list name\n")
+
+DEFUN (match_ip_next_hop_prefix_list,
+       match_ip_next_hop_prefix_list_cmd,
+       "match ip next-hop prefix-list WORD",
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return ospf_route_match_add (vty, vty->index, "ip next-hop prefix-list",
+			       argv[0]);
+}
+
+DEFUN (no_match_ip_next_hop_prefix_list,
+       no_match_ip_next_hop_prefix_list_cmd,
+       "no match ip next-hop prefix-list",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n")
+{
+  if (argc == 0)
+    return ospf_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
+				    NULL);
+  return ospf_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
+				  argv[0]);
+}
+
+ALIAS (no_match_ip_next_hop_prefix_list,
+       no_match_ip_next_hop_prefix_list_val_cmd,
+       "no match ip next-hop prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+
+DEFUN (match_ip_address,
+       match_ip_address_cmd,
+       "match ip address (<1-199>|<1300-2699>|WORD)",
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP access-list name\n")
+{
+  return ospf_route_match_add (vty, vty->index, "ip address", argv[0]);
+}
+
+DEFUN (no_match_ip_address,
+       no_match_ip_address_cmd,
+       "no match ip address",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n")
+{
+  if (argc == 0)
+    return ospf_route_match_delete (vty, vty->index, "ip address", NULL);
+
+  return ospf_route_match_delete (vty, vty->index, "ip address", argv[0]);
+}
+
+ALIAS (no_match_ip_address,
+       no_match_ip_address_val_cmd,
+       "no match ip address (<1-199>|<1300-2699>|WORD)",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP access-list name\n")
+
+DEFUN (match_ip_address_prefix_list,
+       match_ip_address_prefix_list_cmd,
+       "match ip address prefix-list WORD",
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return ospf_route_match_add (vty, vty->index, "ip address prefix-list",
+			       argv[0]);
+}
+
+DEFUN (no_match_ip_address_prefix_list,
+       no_match_ip_address_prefix_list_cmd,
+       "no match ip address prefix-list",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n")
+{
+  if (argc == 0)
+    return ospf_route_match_delete (vty, vty->index, "ip address prefix-list",
+				    NULL);
+  return ospf_route_match_delete (vty, vty->index, "ip address prefix-list",
+				  argv[0]);
+}
+
+ALIAS (no_match_ip_address_prefix_list,
+       no_match_ip_address_prefix_list_val_cmd,
+       "no match ip address prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+
+DEFUN (match_interface,
+       match_interface_cmd,
+       "match interface WORD",
+       MATCH_STR
+       "Match first hop interface of route\n"
+       "Interface name\n")
+{
+  return ospf_route_match_add (vty, vty->index, "interface", argv[0]);
+}
+
+DEFUN (no_match_interface,
+       no_match_interface_cmd,
+       "no match interface",
+       NO_STR
+       MATCH_STR
+       "Match first hop interface of route\n")
+{
+  if (argc == 0)
+    return ospf_route_match_delete (vty, vty->index, "interface", NULL);
+
+  return ospf_route_match_delete (vty, vty->index, "interface", argv[0]);
+}
+
+ALIAS (no_match_interface,
+       no_match_interface_val_cmd,
+       "no match interface WORD",
+       NO_STR
+       MATCH_STR
+       "Match first hop interface of route\n"
+       "Interface name\n")
+
+DEFUN (set_metric,
+       set_metric_cmd,
+       "set metric <0-4294967295>",
+       SET_STR
+       "Metric value for destination routing protocol\n"
+       "Metric value\n")
+{
+  return ospf_route_set_add (vty, vty->index, "metric", argv[0]);
+}
+
+DEFUN (no_set_metric,
+       no_set_metric_cmd,
+       "no set metric",
+       NO_STR
+       SET_STR
+       "Metric value for destination routing protocol\n")
+{
+  if (argc == 0)
+    return ospf_route_set_delete (vty, vty->index, "metric", NULL);
+
+  return ospf_route_set_delete (vty, vty->index, "metric", argv[0]);
+}
+
+ALIAS (no_set_metric,
+       no_set_metric_val_cmd,
+       "no set metric <0-4294967295>",
+       NO_STR
+       SET_STR
+       "Metric value for destination routing protocol\n"
+       "Metric value\n")
+
+DEFUN (set_metric_type,
+       set_metric_type_cmd,
+       "set metric-type (type-1|type-2)",
+       SET_STR
+       "Type of metric for destination routing protocol\n"
+       "OSPF external type 1 metric\n"
+       "OSPF external type 2 metric\n")
+{
+  if (strcmp (argv[0], "1") == 0)
+    return ospf_route_set_add (vty, vty->index, "metric-type", "type-1");
+  if (strcmp (argv[0], "2") == 0)
+    return ospf_route_set_add (vty, vty->index, "metric-type", "type-2");
+
+  return ospf_route_set_add (vty, vty->index, "metric-type", argv[0]);
+}
+
+DEFUN (no_set_metric_type,
+       no_set_metric_type_cmd,
+       "no set metric-type",
+       NO_STR
+       SET_STR
+       "Type of metric for destination routing protocol\n")
+{
+  if (argc == 0)
+    return ospf_route_set_delete (vty, vty->index, "metric-type", NULL);
+
+  return ospf_route_set_delete (vty, vty->index, "metric-type", argv[0]);
+}
+
+ALIAS (no_set_metric_type,
+       no_set_metric_type_val_cmd,
+       "no set metric-type (type-1|type-2)",
+       NO_STR
+       SET_STR
+       "Type of metric for destination routing protocol\n"
+       "OSPF external type 1 metric\n"
+       "OSPF external type 2 metric\n")
+
+/* Route-map init */
+void
+ospf_route_map_init (void)
+{
+  route_map_init ();
+  route_map_init_vty ();
+
+  route_map_add_hook (ospf_route_map_update);
+  route_map_delete_hook (ospf_route_map_update);
+  route_map_event_hook (ospf_route_map_event);
+  
+  route_map_install_match (&route_match_ip_nexthop_cmd);
+  route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
+  route_map_install_match (&route_match_ip_address_cmd);
+  route_map_install_match (&route_match_ip_address_prefix_list_cmd);
+  route_map_install_match (&route_match_interface_cmd);
+
+  route_map_install_set (&route_set_metric_cmd);
+  route_map_install_set (&route_set_metric_type_cmd);
+
+  install_element (RMAP_NODE, &match_ip_nexthop_cmd);
+  install_element (RMAP_NODE, &no_match_ip_nexthop_cmd);
+  install_element (RMAP_NODE, &no_match_ip_nexthop_val_cmd);
+  install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
+  install_element (RMAP_NODE, &match_ip_address_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
+  install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
+  install_element (RMAP_NODE, &match_interface_cmd);
+  install_element (RMAP_NODE, &no_match_interface_cmd);
+  install_element (RMAP_NODE, &no_match_interface_val_cmd);
+
+  install_element (RMAP_NODE, &set_metric_cmd);
+  install_element (RMAP_NODE, &no_set_metric_cmd);
+  install_element (RMAP_NODE, &no_set_metric_val_cmd);
+  install_element (RMAP_NODE, &set_metric_type_cmd);
+  install_element (RMAP_NODE, &no_set_metric_type_cmd);
+  install_element (RMAP_NODE, &no_set_metric_type_val_cmd);
+}
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
new file mode 100644
index 0000000..6187977
--- /dev/null
+++ b/ospfd/ospf_snmp.c
@@ -0,0 +1,2443 @@
+/* OSPFv2 SNMP support
+ * Copyright (C) 2000 IP Infusion Inc.
+ *
+ * Written by Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include <zebra.h>
+
+#ifdef HAVE_SNMP
+#include <asn1.h>
+#include <snmp.h>
+#include <snmp_impl.h>
+
+#include "if.h"
+#include "log.h"
+#include "prefix.h"
+#include "table.h"
+#include "command.h"
+#include "memory.h"
+#include "smux.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_flood.h"
+
+/* OSPF2-MIB. */
+#define OSPF2MIB 1,3,6,1,2,1,14
+
+/* Zebra enterprise OSPF MIB.  This variable is used for register
+   OSPF MIB to SNMP agent under SMUX protocol.  */
+#define OSPFDOID 1,3,6,1,4,1,3317,1,2,5
+
+/* OSPF MIB General Group values. */
+#define OSPFROUTERID                     1
+#define OSPFADMINSTAT                    2
+#define OSPFVERSIONNUMBER                3
+#define OSPFAREABDRRTRSTATUS             4
+#define OSPFASBDRRTRSTATUS               5
+#define OSPFEXTERNLSACOUNT               6
+#define OSPFEXTERNLSACKSUMSUM            7
+#define OSPFTOSSUPPORT                   8
+#define OSPFORIGINATENEWLSAS             9
+#define OSPFRXNEWLSAS                    10
+#define OSPFEXTLSDBLIMIT                 11
+#define OSPFMULTICASTEXTENSIONS          12
+#define OSPFEXITOVERFLOWINTERVAL         13
+#define OSPFDEMANDEXTENSIONS             14
+
+/* OSPF MIB ospfAreaTable. */
+#define OSPFAREAID                       1
+#define OSPFAUTHTYPE                     2
+#define OSPFIMPORTASEXTERN               3
+#define OSPFSPFRUNS                      4
+#define OSPFAREABDRRTRCOUNT              5
+#define OSPFASBDRRTRCOUNT                6
+#define OSPFAREALSACOUNT                 7
+#define OSPFAREALSACKSUMSUM              8
+#define OSPFAREASUMMARY                  9
+#define OSPFAREASTATUS                   10
+
+/* OSPF MIB ospfStubAreaTable. */
+#define OSPFSTUBAREAID                   1
+#define OSPFSTUBTOS                      2
+#define OSPFSTUBMETRIC                   3
+#define OSPFSTUBSTATUS                   4
+#define OSPFSTUBMETRICTYPE               5
+
+/* OSPF MIB ospfLsdbTable. */
+#define OSPFLSDBAREAID                   1
+#define OSPFLSDBTYPE                     2
+#define OSPFLSDBLSID                     3
+#define OSPFLSDBROUTERID                 4
+#define OSPFLSDBSEQUENCE                 5
+#define OSPFLSDBAGE                      6
+#define OSPFLSDBCHECKSUM                 7
+#define OSPFLSDBADVERTISEMENT            8
+
+/* OSPF MIB ospfAreaRangeTable. */
+#define OSPFAREARANGEAREAID              1
+#define OSPFAREARANGENET                 2
+#define OSPFAREARANGEMASK                3
+#define OSPFAREARANGESTATUS              4
+#define OSPFAREARANGEEFFECT              5
+
+/* OSPF MIB ospfHostTable. */
+#define OSPFHOSTIPADDRESS                1
+#define OSPFHOSTTOS                      2
+#define OSPFHOSTMETRIC                   3
+#define OSPFHOSTSTATUS                   4
+#define OSPFHOSTAREAID                   5
+
+/* OSPF MIB ospfIfTable. */
+#define OSPFIFIPADDRESS                  1
+#define OSPFADDRESSLESSIF                2
+#define OSPFIFAREAID                     3
+#define OSPFIFTYPE                       4
+#define OSPFIFADMINSTAT                  5
+#define OSPFIFRTRPRIORITY                6
+#define OSPFIFTRANSITDELAY               7
+#define OSPFIFRETRANSINTERVAL            8
+#define OSPFIFHELLOINTERVAL              9
+#define OSPFIFRTRDEADINTERVAL            10
+#define OSPFIFPOLLINTERVAL               11
+#define OSPFIFSTATE                      12
+#define OSPFIFDESIGNATEDROUTER           13
+#define OSPFIFBACKUPDESIGNATEDROUTER     14
+#define OSPFIFEVENTS                     15
+#define OSPFIFAUTHKEY                    16
+#define OSPFIFSTATUS                     17
+#define OSPFIFMULTICASTFORWARDING        18
+#define OSPFIFDEMAND                     19
+#define OSPFIFAUTHTYPE                   20
+
+/* OSPF MIB ospfIfMetricTable. */
+#define OSPFIFMETRICIPADDRESS            1
+#define OSPFIFMETRICADDRESSLESSIF        2
+#define OSPFIFMETRICTOS                  3
+#define OSPFIFMETRICVALUE                4
+#define OSPFIFMETRICSTATUS               5
+
+/* OSPF MIB ospfVirtIfTable. */
+#define OSPFVIRTIFAREAID                 1
+#define OSPFVIRTIFNEIGHBOR               2
+#define OSPFVIRTIFTRANSITDELAY           3
+#define OSPFVIRTIFRETRANSINTERVAL        4
+#define OSPFVIRTIFHELLOINTERVAL          5
+#define OSPFVIRTIFRTRDEADINTERVAL        6
+#define OSPFVIRTIFSTATE                  7
+#define OSPFVIRTIFEVENTS                 8
+#define OSPFVIRTIFAUTHKEY                9
+#define OSPFVIRTIFSTATUS                 10
+#define OSPFVIRTIFAUTHTYPE               11
+
+/* OSPF MIB ospfNbrTable. */
+#define OSPFNBRIPADDR                    1
+#define OSPFNBRADDRESSLESSINDEX          2
+#define OSPFNBRRTRID                     3
+#define OSPFNBROPTIONS                   4
+#define OSPFNBRPRIORITY                  5
+#define OSPFNBRSTATE                     6
+#define OSPFNBREVENTS                    7
+#define OSPFNBRLSRETRANSQLEN             8
+#define OSPFNBMANBRSTATUS                9
+#define OSPFNBMANBRPERMANENCE            10
+#define OSPFNBRHELLOSUPPRESSED           11
+
+/* OSPF MIB ospfVirtNbrTable. */
+#define OSPFVIRTNBRAREA                  1
+#define OSPFVIRTNBRRTRID                 2
+#define OSPFVIRTNBRIPADDR                3
+#define OSPFVIRTNBROPTIONS               4
+#define OSPFVIRTNBRSTATE                 5
+#define OSPFVIRTNBREVENTS                6
+#define OSPFVIRTNBRLSRETRANSQLEN         7
+#define OSPFVIRTNBRHELLOSUPPRESSED       8
+
+/* OSPF MIB ospfExtLsdbTable. */
+#define OSPFEXTLSDBTYPE                  1
+#define OSPFEXTLSDBLSID                  2
+#define OSPFEXTLSDBROUTERID              3
+#define OSPFEXTLSDBSEQUENCE              4
+#define OSPFEXTLSDBAGE                   5
+#define OSPFEXTLSDBCHECKSUM              6
+#define OSPFEXTLSDBADVERTISEMENT         7
+
+/* OSPF MIB ospfAreaAggregateTable. */
+#define OSPFAREAAGGREGATEAREAID          1
+#define OSPFAREAAGGREGATELSDBTYPE        2
+#define OSPFAREAAGGREGATENET             3
+#define OSPFAREAAGGREGATEMASK            4
+#define OSPFAREAAGGREGATESTATUS          5
+#define OSPFAREAAGGREGATEEFFECT          6
+
+/* SYNTAX Status from OSPF-MIB. */
+#define OSPF_STATUS_ENABLED  1
+#define OSPF_STATUS_DISABLED 2
+
+/* SNMP value hack. */
+#define COUNTER     ASN_COUNTER
+#define INTEGER     ASN_INTEGER
+#define GAUGE       ASN_GAUGE
+#define TIMETICKS   ASN_TIMETICKS
+#define IPADDRESS   ASN_IPADDRESS
+#define STRING      ASN_OCTET_STR
+
+/* Declare static local variables for convenience. */
+SNMP_LOCAL_VARIABLES
+
+/* OSPF-MIB instances. */
+oid ospf_oid [] = { OSPF2MIB };
+oid ospfd_oid [] = { OSPFDOID };
+
+/* IP address 0.0.0.0. */
+static struct in_addr ospf_empty_addr = {0};
+
+/* Hook functions. */
+static u_char *ospfGeneralGroup ();
+static u_char *ospfAreaEntry ();
+static u_char *ospfStubAreaEntry ();
+static u_char *ospfLsdbEntry ();
+static u_char *ospfAreaRangeEntry ();
+static u_char *ospfHostEntry ();
+static u_char *ospfIfEntry ();
+static u_char *ospfIfMetricEntry ();
+static u_char *ospfVirtIfEntry ();
+static u_char *ospfNbrEntry ();
+static u_char *ospfVirtNbrEntry ();
+static u_char *ospfExtLsdbEntry ();
+static u_char *ospfAreaAggregateEntry ();
+
+struct variable ospf_variables[] = 
+{
+  /* OSPF general variables */
+  {OSPFROUTERID,              IPADDRESS, RWRITE, ospfGeneralGroup,
+   2, {1, 1}},
+  {OSPFADMINSTAT,             INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 2}},
+  {OSPFVERSIONNUMBER,         INTEGER, RONLY, ospfGeneralGroup,
+   2, {1, 3}},
+  {OSPFAREABDRRTRSTATUS,      INTEGER, RONLY, ospfGeneralGroup,
+   2, {1, 4}},
+  {OSPFASBDRRTRSTATUS,        INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 5}},
+  {OSPFEXTERNLSACOUNT,        GAUGE, RONLY, ospfGeneralGroup,
+   2, {1, 6}},
+  {OSPFEXTERNLSACKSUMSUM,     INTEGER, RONLY, ospfGeneralGroup,
+   2, {1, 7}},
+  {OSPFTOSSUPPORT,            INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 8}},
+  {OSPFORIGINATENEWLSAS,      COUNTER, RONLY, ospfGeneralGroup,
+   2, {1, 9}},
+  {OSPFRXNEWLSAS,             COUNTER, RONLY, ospfGeneralGroup,
+   2, {1, 10}},
+  {OSPFEXTLSDBLIMIT,          INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 11}},
+  {OSPFMULTICASTEXTENSIONS,   INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 12}},
+  {OSPFEXITOVERFLOWINTERVAL,  INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 13}},
+  {OSPFDEMANDEXTENSIONS,      INTEGER, RWRITE, ospfGeneralGroup,
+   2, {1, 14}},
+
+  /* OSPF area data structure. */
+  {OSPFAREAID,                IPADDRESS, RONLY, ospfAreaEntry,
+   3, {2, 1, 1}},
+  {OSPFAUTHTYPE,              INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 2}},
+  {OSPFIMPORTASEXTERN,        INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 3}},
+  {OSPFSPFRUNS,               COUNTER, RONLY, ospfAreaEntry,
+   3, {2, 1, 4}},
+  {OSPFAREABDRRTRCOUNT,       GAUGE, RONLY, ospfAreaEntry,
+   3, {2, 1, 5}},
+  {OSPFASBDRRTRCOUNT,         GAUGE, RONLY, ospfAreaEntry,
+   3, {2, 1, 6}},
+  {OSPFAREALSACOUNT,          GAUGE, RONLY, ospfAreaEntry,
+   3, {2, 1, 7}},
+  {OSPFAREALSACKSUMSUM,       INTEGER, RONLY, ospfAreaEntry,
+   3, {2, 1, 8}},
+  {OSPFAREASUMMARY,           INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 9}},
+  {OSPFAREASTATUS,            INTEGER, RWRITE, ospfAreaEntry,
+   3, {2, 1, 10}},
+
+  /* OSPF stub area information. */
+  {OSPFSTUBAREAID,            IPADDRESS, RONLY, ospfStubAreaEntry,
+   3, {3, 1, 1}},
+  {OSPFSTUBTOS,               INTEGER, RONLY, ospfStubAreaEntry,
+   3, {3, 1, 2}},
+  {OSPFSTUBMETRIC,            INTEGER, RWRITE, ospfStubAreaEntry,
+   3, {3, 1, 3}},
+  {OSPFSTUBSTATUS,            INTEGER, RWRITE, ospfStubAreaEntry,
+   3, {3, 1, 4}},
+  {OSPFSTUBMETRICTYPE,        INTEGER, RWRITE, ospfStubAreaEntry,
+   3, {3, 1, 5}},
+
+  /* OSPF link state database. */
+  {OSPFLSDBAREAID,            IPADDRESS, RONLY, ospfLsdbEntry,
+   3, {4, 1, 1}},
+  {OSPFLSDBTYPE,              INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 2}},
+  {OSPFLSDBLSID,              IPADDRESS, RONLY, ospfLsdbEntry,
+   3, {4, 1, 3}},
+  {OSPFLSDBROUTERID,          IPADDRESS, RONLY, ospfLsdbEntry,
+   3, {4, 1, 4}},
+  {OSPFLSDBSEQUENCE,          INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 5}},
+  {OSPFLSDBAGE,               INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 6}},
+  {OSPFLSDBCHECKSUM,          INTEGER, RONLY, ospfLsdbEntry,
+   3, {4, 1, 7}},
+  {OSPFLSDBADVERTISEMENT,     STRING, RONLY, ospfLsdbEntry,
+   3, {4, 1, 8}},
+
+  /* Area range table. */
+  {OSPFAREARANGEAREAID,       IPADDRESS, RONLY, ospfAreaRangeEntry,
+   3, {5, 1, 1}},
+  {OSPFAREARANGENET,          IPADDRESS, RONLY, ospfAreaRangeEntry,
+   3, {5, 1, 2}},
+  {OSPFAREARANGEMASK,         IPADDRESS, RWRITE, ospfAreaRangeEntry,
+   3, {5, 1, 3}},
+  {OSPFAREARANGESTATUS,       INTEGER, RWRITE, ospfAreaRangeEntry,
+   3, {5, 1, 4}},
+  {OSPFAREARANGEEFFECT,       INTEGER, RWRITE, ospfAreaRangeEntry,
+   3, {5, 1, 5}},
+
+  /* OSPF host table. */
+  {OSPFHOSTIPADDRESS,         IPADDRESS, RONLY, ospfHostEntry,
+   3, {6, 1, 1}},
+  {OSPFHOSTTOS,               INTEGER, RONLY, ospfHostEntry,
+   3, {6, 1, 2}},
+  {OSPFHOSTMETRIC,            INTEGER, RWRITE, ospfHostEntry,
+   3, {6, 1, 3}},
+  {OSPFHOSTSTATUS,            INTEGER, RWRITE, ospfHostEntry,
+   3, {6, 1, 4}},
+  {OSPFHOSTAREAID,            IPADDRESS, RONLY, ospfHostEntry,
+   3, {6, 1, 5}},
+
+  /* OSPF interface table. */
+  {OSPFIFIPADDRESS,           IPADDRESS, RONLY, ospfIfEntry,
+   3, {7, 1, 1}},
+  {OSPFADDRESSLESSIF,         INTEGER, RONLY, ospfIfEntry,
+   3, {7, 1, 2}},
+  {OSPFIFAREAID,              IPADDRESS, RWRITE, ospfIfEntry,
+   3, {7, 1, 3}},
+  {OSPFIFTYPE,                INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 4}},
+  {OSPFIFADMINSTAT,           INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 5}},
+  {OSPFIFRTRPRIORITY,         INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 6}},
+  {OSPFIFTRANSITDELAY,        INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 7}},
+  {OSPFIFRETRANSINTERVAL,     INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 8}},
+  {OSPFIFHELLOINTERVAL,       INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 9}},
+  {OSPFIFRTRDEADINTERVAL,     INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 10}},
+  {OSPFIFPOLLINTERVAL,        INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 11}},
+  {OSPFIFSTATE,               INTEGER, RONLY, ospfIfEntry,
+   3, {7, 1, 12}},
+  {OSPFIFDESIGNATEDROUTER,    IPADDRESS, RONLY, ospfIfEntry,
+   3, {7, 1, 13}},
+  {OSPFIFBACKUPDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry,
+   3, {7, 1, 14}},
+  {OSPFIFEVENTS,              COUNTER, RONLY, ospfIfEntry,
+   3, {7, 1, 15}},
+  {OSPFIFAUTHKEY,             STRING,  RWRITE, ospfIfEntry,
+   3, {7, 1, 16}},
+  {OSPFIFSTATUS,              INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 17}},
+  {OSPFIFMULTICASTFORWARDING, INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 18}},
+  {OSPFIFDEMAND,              INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 19}},
+  {OSPFIFAUTHTYPE,            INTEGER, RWRITE, ospfIfEntry,
+   3, {7, 1, 20}},
+
+  /* OSPF interface metric table. */
+  {OSPFIFMETRICIPADDRESS,     IPADDRESS, RONLY, ospfIfMetricEntry,
+   3, {8, 1, 1}},
+  {OSPFIFMETRICADDRESSLESSIF, INTEGER, RONLY, ospfIfMetricEntry,
+   3, {8, 1, 2}},
+  {OSPFIFMETRICTOS,           INTEGER, RONLY, ospfIfMetricEntry,
+   3, {8, 1, 3}},
+  {OSPFIFMETRICVALUE,         INTEGER, RWRITE, ospfIfMetricEntry,
+   3, {8, 1, 4}},
+  {OSPFIFMETRICSTATUS,        INTEGER, RWRITE, ospfIfMetricEntry,
+   3, {8, 1, 5}},
+
+  /* OSPF virtual interface table. */
+  {OSPFVIRTIFAREAID,          IPADDRESS, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 1}},
+  {OSPFVIRTIFNEIGHBOR,        IPADDRESS, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 2}},
+  {OSPFVIRTIFTRANSITDELAY,    INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 3}},
+  {OSPFVIRTIFRETRANSINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 4}},
+  {OSPFVIRTIFHELLOINTERVAL,   INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 5}},
+  {OSPFVIRTIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 6}},
+  {OSPFVIRTIFSTATE,           INTEGER, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 7}},
+  {OSPFVIRTIFEVENTS,          COUNTER, RONLY, ospfVirtIfEntry,
+   3, {9, 1, 8}},
+  {OSPFVIRTIFAUTHKEY,         STRING,  RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 9}},
+  {OSPFVIRTIFSTATUS,          INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 10}},
+  {OSPFVIRTIFAUTHTYPE,        INTEGER, RWRITE, ospfVirtIfEntry,
+   3, {9, 1, 11}},
+
+  /* OSPF neighbor table. */
+  {OSPFNBRIPADDR,             IPADDRESS, RONLY, ospfNbrEntry,
+   3, {10, 1, 1}},
+  {OSPFNBRADDRESSLESSINDEX,   INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 2}},
+  {OSPFNBRRTRID,              IPADDRESS, RONLY, ospfNbrEntry,
+   3, {10, 1, 3}},
+  {OSPFNBROPTIONS,            INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 4}},
+  {OSPFNBRPRIORITY,           INTEGER, RWRITE, ospfNbrEntry,
+   3, {10, 1, 5}},
+  {OSPFNBRSTATE,              INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 6}},
+  {OSPFNBREVENTS,             COUNTER, RONLY, ospfNbrEntry,
+   3, {10, 1, 7}},
+  {OSPFNBRLSRETRANSQLEN,      GAUGE, RONLY, ospfNbrEntry,
+   3, {10, 1, 8}},
+  {OSPFNBMANBRSTATUS,         INTEGER, RWRITE, ospfNbrEntry,
+   3, {10, 1, 9}},
+  {OSPFNBMANBRPERMANENCE,     INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 10}},
+  {OSPFNBRHELLOSUPPRESSED,    INTEGER, RONLY, ospfNbrEntry,
+   3, {10, 1, 11}},
+
+  /* OSPF virtual neighbor table. */
+  {OSPFVIRTNBRAREA,           IPADDRESS, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 1}},
+  {OSPFVIRTNBRRTRID,          IPADDRESS, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 2}},
+  {OSPFVIRTNBRIPADDR,         IPADDRESS, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 3}},
+  {OSPFVIRTNBROPTIONS,        INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 4}},
+  {OSPFVIRTNBRSTATE,          INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 5}},
+  {OSPFVIRTNBREVENTS,         COUNTER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 6}},
+  {OSPFVIRTNBRLSRETRANSQLEN,  INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 7}},
+  {OSPFVIRTNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfVirtNbrEntry,
+   3, {11, 1, 8}},
+
+  /* OSPF link state database, external. */
+  {OSPFEXTLSDBTYPE,           INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 1}},
+  {OSPFEXTLSDBLSID,           IPADDRESS, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 2}},
+  {OSPFEXTLSDBROUTERID,       IPADDRESS, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 3}},
+  {OSPFEXTLSDBSEQUENCE,       INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 4}},
+  {OSPFEXTLSDBAGE,            INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 5}},
+  {OSPFEXTLSDBCHECKSUM,       INTEGER, RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 6}},
+  {OSPFEXTLSDBADVERTISEMENT,  STRING,  RONLY, ospfExtLsdbEntry,
+   3, {12, 1, 7}},
+
+  /* OSPF area aggregate table. */
+  {OSPFAREAAGGREGATEAREAID,   IPADDRESS, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 1}},
+  {OSPFAREAAGGREGATELSDBTYPE, INTEGER, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 2}},
+  {OSPFAREAAGGREGATENET,      IPADDRESS, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 3}},
+  {OSPFAREAAGGREGATEMASK,     IPADDRESS, RONLY, ospfAreaAggregateEntry, 
+   3, {14, 1, 4}},
+  {OSPFAREAAGGREGATESTATUS,   INTEGER, RWRITE, ospfAreaAggregateEntry,
+   3, {14, 1, 5}},
+  {OSPFAREAAGGREGATEEFFECT,   INTEGER, RWRITE, ospfAreaAggregateEntry,
+   3, {14, 1, 6}}
+};
+
+/* The administrative status of OSPF.  When OSPF is enbled on at least
+   one interface return 1. */
+int
+ospf_admin_stat ()
+{
+  listnode node;
+  struct ospf_interface *oi;
+
+  if (! ospf_top)
+    return 0;
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      oi = getdata (node);
+
+      if (oi && oi->address)
+	return 1;
+    }
+  return 0;
+}
+
+static u_char *
+ospfGeneralGroup (struct variable *v, oid *name, size_t *length,
+		  int exact, size_t *var_len, WriteMethod **write_method)
+{
+  /* Check whether the instance identifier is valid */
+  if (smux_header_generic (v, name, length, exact, var_len, write_method)
+      == MATCH_FAILED)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFROUTERID:		/* 1 */
+      /* Router-ID of this OSPF instance. */
+      if (ospf_top)
+	return SNMP_IPADDRESS (ospf_top->router_id);
+      else
+	return SNMP_IPADDRESS (ospf_empty_addr);
+      break;
+    case OSPFADMINSTAT:		/* 2 */
+      /* The administrative status of OSPF in the router. */
+      if (ospf_admin_stat ())
+	return SNMP_INTEGER (OSPF_STATUS_ENABLED);
+      else
+	return SNMP_INTEGER (OSPF_STATUS_DISABLED);
+      break;
+    case OSPFVERSIONNUMBER:	/* 3 */
+      /* OSPF version 2. */
+      return SNMP_INTEGER (OSPF_VERSION);
+      break;
+    case OSPFAREABDRRTRSTATUS:	/* 4 */
+      /* Area Border router status. */
+      if (ospf_top && CHECK_FLAG (ospf_top->flags, OSPF_FLAG_ABR))
+	return SNMP_INTEGER (SNMP_TRUE);
+      else
+	return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFASBDRRTRSTATUS:	/* 5 */
+      /* AS Border router status. */
+      if (ospf_top && CHECK_FLAG (ospf_top->flags, OSPF_FLAG_ASBR))
+	return SNMP_INTEGER (SNMP_TRUE);
+      else
+	return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFEXTERNLSACOUNT:	/* 6 */
+      /* External LSA counts. */
+      if (ospf_top)
+	return SNMP_INTEGER (ospf_lsdb_count_all (ospf_top->lsdb));
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case OSPFEXTERNLSACKSUMSUM:	/* 7 */
+      /* External LSA checksum. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFTOSSUPPORT:	/* 8 */
+      /* TOS is not supported. */
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFORIGINATENEWLSAS:	/* 9 */
+      /* The number of new link-state advertisements. */
+      if (ospf_top)
+	return SNMP_INTEGER (ospf_top->lsa_originate_count);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case OSPFRXNEWLSAS:		/* 10 */
+      /* The number of link-state advertisements received determined
+         to be new instantiations. */
+      if (ospf_top)
+	return SNMP_INTEGER (ospf_top->rx_lsa_count);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case OSPFEXTLSDBLIMIT:	/* 11 */
+      /* There is no limit for the number of non-default
+         AS-external-LSAs. */
+      return SNMP_INTEGER (-1);
+      break;
+    case OSPFMULTICASTEXTENSIONS: /* 12 */
+      /* Multicast Extensions to OSPF is not supported. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFEXITOVERFLOWINTERVAL: /* 13 */
+      /* Overflow is not supported. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFDEMANDEXTENSIONS:	/* 14 */
+      /* Demand routing is not supported. */
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    default:
+      return NULL;
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospf_area_lookup_next (struct in_addr *area_id, int first)
+{
+  struct ospf_area *area;
+  listnode node;
+
+  if (! ospf_top)
+    return NULL;
+
+  if (first)
+    {
+      node = listhead (ospf_top->areas);
+      if (node)
+	{
+	  area = getdata (node);
+	  *area_id = area->area_id;
+	  return area;
+	}
+      return NULL;
+    }
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
+	{
+	  *area_id = area->area_id;
+	  return area;
+	}
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospfAreaLookup (struct variable *v, oid name[], size_t *length,
+		struct in_addr *addr, int exact)
+{
+  int len;
+  struct ospf_area *area;
+
+  if (! ospf_top)
+    return NULL;
+
+  if (exact)
+    {
+      /* Length is insufficient to lookup OSPF area. */
+      if (*length - v->namelen != sizeof (struct in_addr))
+	return NULL;
+
+      oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
+
+      area = ospf_area_lookup_by_area_id (*addr);
+
+      return area;
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len > 4)
+	len = 4;
+      
+      oid2in_addr (name + v->namelen, len, addr);
+
+      area = ospf_area_lookup_next (addr, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
+      *length = sizeof (struct in_addr) + v->namelen;
+
+      return area;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfAreaEntry (struct variable *v, oid *name, size_t *length, int exact,
+	       size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_area *area;
+  struct in_addr addr;
+
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  area = ospfAreaLookup (v, name, length, &addr, exact);
+  if (! area)
+    return NULL;
+  
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFAREAID:		/* 1 */
+      return SNMP_IPADDRESS (area->area_id);
+      break;
+    case OSPFAUTHTYPE:		/* 2 */
+      return SNMP_INTEGER (area->auth_type);
+      break;
+    case OSPFIMPORTASEXTERN:	/* 3 */
+      return SNMP_INTEGER (area->external_routing + 1);
+      break;
+    case OSPFSPFRUNS:		/* 4 */
+      return SNMP_INTEGER (area->spf_calculation);
+      break;
+    case OSPFAREABDRRTRCOUNT:	/* 5 */
+      return SNMP_INTEGER (area->abr_count);
+      break;
+    case OSPFASBDRRTRCOUNT:	/* 6 */
+      return SNMP_INTEGER (area->asbr_count);
+      break;
+    case OSPFAREALSACOUNT:	/* 7 */
+      return SNMP_INTEGER (area->lsdb->total);
+      break;
+    case OSPFAREALSACKSUMSUM:	/* 8 */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFAREASUMMARY:	/* 9 */
+#define OSPF_noAreaSummary   1
+#define OSPF_sendAreaSummary 2
+      if (area->no_summary)
+	return SNMP_INTEGER (OSPF_noAreaSummary);
+      else
+	return SNMP_INTEGER (OSPF_sendAreaSummary);
+      break;
+    case OSPFAREASTATUS:	/* 10 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospf_stub_area_lookup_next (struct in_addr *area_id, int first)
+{
+  struct ospf_area *area;
+  listnode node;
+
+  if (! ospf_top)
+    return NULL;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (area->external_routing == OSPF_AREA_STUB)
+	{
+	  if (first)
+	    {
+	      *area_id = area->area_id;
+	      return area;
+	    }
+	  else if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr))
+	    {
+	      *area_id = area->area_id;
+	      return area;
+	    }
+	}
+    }
+  return NULL;
+}
+
+struct ospf_area *
+ospfStubAreaLookup (struct variable *v, oid name[], size_t *length,
+		    struct in_addr *addr, int exact)
+{
+  int len;
+  struct ospf_area *area;
+
+  if (! ospf_top)
+    return NULL;
+
+  /* Exact lookup. */
+  if (exact)
+    {
+      /* ospfStubAreaID + ospfStubTOS. */
+      if (*length != v->namelen + sizeof (struct in_addr) + 1)
+	return NULL;
+
+      /* Check ospfStubTOS is zero. */
+      if (name[*length - 1] != 0)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
+
+      area = ospf_area_lookup_by_area_id (*addr);
+
+      if (area->external_routing == OSPF_AREA_STUB)
+	return area;
+      else
+	return NULL;
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len > 4)
+	len = 4;
+      
+      oid2in_addr (name + v->namelen, len, addr);
+
+      area = ospf_stub_area_lookup_next (addr, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
+      /* Set TOS 0. */
+      name[v->namelen + sizeof (struct in_addr)] = 0;
+      *length = v->namelen + sizeof (struct in_addr) + 1;
+
+      return area;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfStubAreaEntry (struct variable *v, oid *name, size_t *length,
+		   int exact, size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_area *area;
+  struct in_addr addr;
+
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  area = ospfStubAreaLookup (v, name, length, &addr, exact);
+  if (! area)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFSTUBAREAID:	/* 1 */
+      /* OSPF stub area id. */
+      return SNMP_IPADDRESS (area->area_id);
+      break;
+    case OSPFSTUBTOS:		/* 2 */
+      /* TOS value is not supported. */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFSTUBMETRIC:	/* 3 */
+      /* Default cost to stub area. */
+      return SNMP_INTEGER (area->default_cost);
+      break;
+    case OSPFSTUBSTATUS:	/* 4 */
+      /* Status of the stub area. */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFSTUBMETRICTYPE:	/* 5 */
+      /* OSPF Metric type. */
+#define OSPF_ospfMetric     1
+#define OSPF_comparableCost 2
+#define OSPF_nonComparable  3
+      return SNMP_INTEGER (OSPF_ospfMetric);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+lsdb_lookup_next (struct ospf_area *area, u_char *type, int type_next,
+		  struct in_addr *ls_id, int ls_id_next,
+		  struct in_addr *router_id, int router_id_next)
+{
+  struct ospf_lsa *lsa;
+  int i;
+
+  if (type_next)
+    i = OSPF_MIN_LSA;
+  else
+    i = *type;
+
+  for (; i < OSPF_MAX_LSA; i++)
+    {
+      *type = i;
+
+      lsa = ospf_lsdb_lookup_by_id_next (area->lsdb, *type, *ls_id, *router_id,
+					ls_id_next);
+      if (lsa)
+	return lsa;
+
+      ls_id_next = 1;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+ospfLsdbLookup (struct variable *v, oid *name, size_t *length,
+		struct in_addr *area_id, u_char *type,
+		struct in_addr *ls_id, struct in_addr *router_id, int exact)
+{
+  struct ospf_area *area;
+  struct ospf_lsa *lsa;
+  int len;
+  int type_next;
+  int ls_id_next;
+  int router_id_next;
+  oid *offset;
+  int offsetlen;
+
+#define OSPF_LSDB_ENTRY_OFFSET \
+          (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
+
+  if (exact)
+    {
+      /* Area ID + Type + LS ID + Router ID. */
+      if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET)
+	return NULL;
+      
+      /* Set OID offset for Area ID. */
+      offset = name + v->namelen;
+
+      /* Lookup area first. */
+      oid2in_addr (offset, IN_ADDR_SIZE, area_id);
+      area = ospf_area_lookup_by_area_id (*area_id);
+      if (! area)
+	return NULL;
+      offset += IN_ADDR_SIZE;
+
+      /* Type. */
+      *type = *offset;
+      offset++;
+
+      /* LS ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
+      offset += IN_ADDR_SIZE;
+
+      /* Router ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, router_id);
+
+      /* Lookup LSDB. */
+      return ospf_lsdb_lookup_by_id (area->lsdb, *type, *ls_id, *router_id);
+    }
+  else
+    {
+      /* Get variable length. */
+      offset = name + v->namelen;
+      offsetlen = *length - v->namelen;
+      len = offsetlen;
+
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, area_id);
+
+      /* First we search area. */
+      if (len == IN_ADDR_SIZE)
+	area = ospf_area_lookup_by_area_id (*area_id);
+      else
+	area = ospf_area_lookup_next (area_id, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      do 
+	{
+	  /* Next we lookup type. */
+	  offset += IN_ADDR_SIZE;
+	  offsetlen -= IN_ADDR_SIZE;
+	  len = offsetlen;
+
+	  if (len <= 0)
+	    type_next = 1;
+	  else
+	    {
+	      len = 1;
+	      type_next = 0;
+	      *type = *offset;
+	    }
+	
+	  /* LS ID. */
+	  offset++;
+	  offsetlen--;
+	  len = offsetlen;
+
+	  if (len <= 0)
+	    ls_id_next = 1;
+	  else
+	    {
+	      ls_id_next = 0;
+	      if (len > IN_ADDR_SIZE)
+		len = IN_ADDR_SIZE;
+
+	      oid2in_addr (offset, len, ls_id);
+	    }
+
+	  /* Router ID. */
+	  offset += IN_ADDR_SIZE;
+	  offsetlen -= IN_ADDR_SIZE;
+	  len = offsetlen;
+
+	  if (len <= 0)
+	    router_id_next = 1;
+	  else
+	    {
+	      router_id_next = 0;
+	      if (len > IN_ADDR_SIZE)
+		len = IN_ADDR_SIZE;
+
+	      oid2in_addr (offset, len, router_id);
+	    }
+
+	  lsa = lsdb_lookup_next (area, type, type_next, ls_id, ls_id_next,
+				  router_id, router_id_next);
+
+	  if (lsa)
+	    {
+	      /* Fill in length. */
+	      *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET;
+
+	      /* Fill in value. */
+	      offset = name + v->namelen;
+	      oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
+	      offset += IN_ADDR_SIZE;
+	      *offset = lsa->data->type;
+	      offset++;
+	      oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
+	      offset += IN_ADDR_SIZE;
+	      oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
+	    
+	      return lsa;
+	    }
+	}
+      while ((area = ospf_area_lookup_next (area_id, 0)) != NULL);
+    }
+  return NULL;
+}
+
+static u_char *
+ospfLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
+	       size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_lsa *lsa;
+  struct lsa_header *lsah;
+  struct in_addr area_id;
+  u_char type;
+  struct in_addr ls_id;
+  struct in_addr router_id;
+
+  /* INDEX { ospfLsdbAreaId, ospfLsdbType,
+     ospfLsdbLsid, ospfLsdbRouterId } */
+
+  memset (&area_id, 0, sizeof (struct in_addr));
+  type = 0;
+  memset (&ls_id, 0, sizeof (struct in_addr));
+  memset (&router_id, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  lsa = ospfLsdbLookup (v, name, length, &area_id, &type, &ls_id, &router_id,
+			exact);
+  if (! lsa)
+    return NULL;
+
+  lsah = lsa->data;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFLSDBAREAID:	/* 1 */
+      return SNMP_IPADDRESS (lsa->area->area_id);
+      break;
+    case OSPFLSDBTYPE:		/* 2 */
+      return SNMP_INTEGER (lsah->type);
+      break;
+    case OSPFLSDBLSID:		/* 3 */
+      return SNMP_IPADDRESS (lsah->id);
+      break;
+    case OSPFLSDBROUTERID:	/* 4 */
+      return SNMP_IPADDRESS (lsah->adv_router);
+      break;
+    case OSPFLSDBSEQUENCE:	/* 5 */
+      return SNMP_INTEGER (lsah->ls_seqnum);
+      break;
+    case OSPFLSDBAGE:		/* 6 */
+      return SNMP_INTEGER (lsah->ls_age);
+      break;
+    case OSPFLSDBCHECKSUM:	/* 7 */
+      return SNMP_INTEGER (lsah->checksum);
+      break;
+    case OSPFLSDBADVERTISEMENT:	/* 8 */
+      *var_len = ntohs (lsah->length);
+      return (u_char *) lsah;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_area_range *
+ospfAreaRangeLookup (struct variable *v, oid *name, size_t *length,
+		     struct in_addr *area_id, struct in_addr *range_net,
+		     int exact)
+{
+  oid *offset;
+  int offsetlen;
+  int len;
+  struct ospf_area *area;
+  struct ospf_area_range *range;
+  struct prefix_ipv4 p;
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+
+  if (exact) 
+    {
+      /* Area ID + Range Network. */
+      if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length)
+	return NULL;
+
+      /* Set OID offset for Area ID. */
+      offset = name + v->namelen;
+
+      /* Lookup area first. */
+      oid2in_addr (offset, IN_ADDR_SIZE, area_id);
+
+      area = ospf_area_lookup_by_area_id (*area_id);
+      if (! area)
+	return NULL;
+
+      offset += IN_ADDR_SIZE;
+
+      /* Lookup area range. */
+      oid2in_addr (offset, IN_ADDR_SIZE, range_net);
+      p.prefix = *range_net;
+
+      return ospf_area_range_lookup (area, &p);
+    }
+  else
+    {
+      /* Set OID offset for Area ID. */
+      offset = name + v->namelen;
+      offsetlen = *length - v->namelen;
+
+      len = offsetlen;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, area_id);
+
+      /* First we search area. */
+      if (len == IN_ADDR_SIZE)
+	area = ospf_area_lookup_by_area_id (*area_id);
+      else
+	area = ospf_area_lookup_next (area_id, len == 0 ? 1 : 0);
+
+      if (area == NULL)
+	return NULL;
+
+      do 
+	{
+	  offset += IN_ADDR_SIZE;
+	  offsetlen -= IN_ADDR_SIZE;
+	  len = offsetlen;
+
+	  if (len < 0)
+	    len = 0;
+	  if (len > IN_ADDR_SIZE)
+	    len = IN_ADDR_SIZE;
+
+	  oid2in_addr (offset, len, range_net);
+
+	  range = ospf_area_range_lookup_next (area, range_net,
+					       len == 0 ? 1 : 0);
+
+	  if (range)
+	    {
+	      /* Fill in length. */
+	      *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
+
+	      /* Fill in value. */
+	      offset = name + v->namelen;
+	      oid_copy_addr (offset, area_id, IN_ADDR_SIZE);
+	      offset += IN_ADDR_SIZE;
+	      oid_copy_addr (offset, range_net, IN_ADDR_SIZE);
+
+	      return range;
+	    }
+	}
+      while ((area = ospf_area_lookup_next (area_id, 0)) != NULL);
+    }
+  return NULL;
+}
+
+static u_char *
+ospfAreaRangeEntry (struct variable *v, oid *name, size_t *length, int exact,
+		    size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_area_range *range;
+  struct in_addr area_id;
+  struct in_addr range_net;
+  struct in_addr mask;
+  
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  memset (&area_id, 0, IN_ADDR_SIZE);
+  memset (&range_net, 0, IN_ADDR_SIZE);
+
+  range = ospfAreaRangeLookup (v, name, length, &area_id, &range_net, exact);
+  if (! range)
+    return NULL;
+
+  /* Convert prefixlen to network mask format. */
+  masklen2ip (range->subst_masklen, &mask);
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFAREARANGEAREAID:	/* 1 */
+      return SNMP_IPADDRESS (area_id);
+      break;
+    case OSPFAREARANGENET:	/* 2 */
+      return SNMP_IPADDRESS (range_net);
+      break;
+    case OSPFAREARANGEMASK:	/* 3 */
+      return SNMP_IPADDRESS (mask);
+      break;
+    case OSPFAREARANGESTATUS:	/* 4 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFAREARANGEEFFECT:	/* 5 */
+#define OSPF_advertiseMatching      1
+#define OSPF_doNotAdvertiseMatching 2
+      return SNMP_INTEGER (OSPF_advertiseMatching);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_nbr_nbma *
+ospfHostLookup (struct variable *v, oid *name, size_t *length,
+		struct in_addr *addr, int exact)
+{
+  int len;
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  if (! ospf_top)
+    return NULL;
+
+  if (exact)
+    {
+      /* INDEX { ospfHostIpAddress, ospfHostTOS } */
+      if (*length != v->namelen + IN_ADDR_SIZE + 1)
+	return NULL;
+
+      /* Check ospfHostTOS. */
+      if (name[*length - 1] != 0)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
+
+      nbr_nbma = ospf_nbr_nbma_lookup (ospf_top, *addr);
+
+      return nbr_nbma;
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len > 4)
+	len = 4;
+      
+      oid2in_addr (name + v->namelen, len, addr);
+
+      nbr_nbma = ospf_nbr_nbma_lookup_next (addr, len == 0 ? 1 : 0);
+
+      if (nbr_nbma == NULL)
+	return NULL;
+
+      oid_copy_addr (name + v->namelen, addr, IN_ADDR_SIZE);
+
+      /* Set TOS 0. */
+      name[v->namelen + IN_ADDR_SIZE] = 0;
+
+      *length = v->namelen + IN_ADDR_SIZE + 1;
+
+      return nbr_nbma;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact,
+	       size_t *var_len, WriteMethod **write_method)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+  struct ospf_interface *oi;
+  struct in_addr addr;
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  nbr_nbma = ospfHostLookup (v, name, length, &addr, exact);
+  if (nbr_nbma == NULL)
+    return NULL;
+
+  oi = nbr_nbma->oi;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFHOSTIPADDRESS:	/* 1 */
+      return SNMP_IPADDRESS (nbr_nbma->addr);
+      break;
+    case OSPFHOSTTOS:		/* 2 */
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFHOSTMETRIC:	/* 3 */
+      if (oi)
+	return SNMP_INTEGER (oi->output_cost);
+      else
+	return SNMP_INTEGER (1);
+      break;
+    case OSPFHOSTSTATUS:	/* 4 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFHOSTAREAID:	/* 5 */
+      if (oi && oi->area)
+	return SNMP_IPADDRESS (oi->area->area_id);
+      else
+	return SNMP_IPADDRESS (ospf_empty_addr);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct list *ospf_snmp_iflist;
+
+struct ospf_snmp_if
+{
+  struct in_addr addr;
+  unsigned int ifindex;
+  struct interface *ifp;
+};
+
+struct ospf_snmp_if *
+ospf_snmp_if_new ()
+{
+  struct ospf_snmp_if *osif;
+
+  osif = XMALLOC (0, sizeof (struct ospf_snmp_if));
+  memset (osif, 0, sizeof (struct ospf_snmp_if));
+  return osif;
+}
+
+void
+ospf_snmp_if_free (struct ospf_snmp_if *osif)
+{
+  XFREE (0, osif);
+}
+
+void
+ospf_snmp_if_delete (struct interface *ifp)
+{
+  struct listnode *nn;
+  struct ospf_snmp_if *osif;
+
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {
+      if (osif->ifp == ifp)
+	{
+	  list_delete_node (ospf_snmp_iflist, nn);
+	  ospf_snmp_if_free (osif);
+	  return;
+	}
+    }
+}
+
+void
+ospf_snmp_if_update (struct interface *ifp)
+{
+  struct listnode *nn;
+  struct listnode *pn;
+  struct connected *ifc;
+  struct prefix *p;
+  struct ospf_snmp_if *osif;
+  struct in_addr *addr;
+  unsigned int ifindex;
+
+  ospf_snmp_if_delete (ifp);
+
+  p = NULL;
+  addr = NULL;
+  ifindex = 0;
+
+  /* Lookup first IPv4 address entry. */
+  LIST_LOOP (ifp->connected, ifc, nn)
+    {
+      if (if_is_pointopoint (ifp))
+	p = ifc->destination;
+      else
+	p = ifc->address;
+
+      if (p->family == AF_INET)
+	{
+	  addr = &p->u.prefix4;
+	  break;
+	}
+    }
+  if (! addr)
+    ifindex = ifp->ifindex;
+
+  /* Add interface to the list. */
+  pn = NULL;
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {
+      if (addr)
+	{
+	  if (ntohl (osif->addr.s_addr) > ntohl (addr->s_addr))
+	    break;
+	}
+      else
+	{
+	  /* Unnumbered interface. */
+	  if (osif->addr.s_addr != 0 || osif->ifindex > ifindex)
+	    break;
+	}
+      pn = nn;
+    }
+
+  osif = ospf_snmp_if_new ();
+  if (addr)
+    osif->addr = *addr;
+  else
+    osif->ifindex = ifindex;
+  osif->ifp = ifp;
+
+  listnode_add_after (ospf_snmp_iflist, pn, osif);
+}
+
+struct interface *
+ospf_snmp_if_lookup (struct in_addr *ifaddr, unsigned int *ifindex)
+{
+  struct listnode *nn;
+  struct ospf_snmp_if *osif;
+
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {  
+      if (ifaddr->s_addr)
+	{
+	  if (IPV4_ADDR_SAME (&osif->addr, ifaddr))
+	    return osif->ifp;
+	}
+      else
+	{
+	  if (osif->ifindex == *ifindex)
+	    return osif->ifp;
+	}
+    }
+  return NULL;
+}
+
+struct interface *
+ospf_snmp_if_lookup_next (struct in_addr *ifaddr, unsigned int *ifindex,
+			  int ifaddr_next, int ifindex_next)
+{
+  struct ospf_snmp_if *osif;
+  struct listnode *nn;
+
+  if (ifaddr_next)
+    {
+      nn = listhead (ospf_snmp_iflist);
+      if (nn)
+	{
+	  osif = getdata (nn);
+	  *ifaddr = osif->addr;
+	  *ifindex = osif->ifindex;
+	  return osif->ifp;
+	}
+      return NULL;
+    }
+
+  LIST_LOOP (ospf_snmp_iflist, osif, nn)
+    {
+      if (ifaddr->s_addr)
+	{
+	  if (ntohl (osif->addr.s_addr) > ntohl (ifaddr->s_addr))
+	    {
+	      *ifaddr = osif->addr;
+	      *ifindex = osif->ifindex;
+	      return osif->ifp;
+	    }
+	}
+      else
+	{
+	  if (osif->ifindex > *ifindex || osif->addr.s_addr)
+	    {
+	      *ifaddr = osif->addr;
+	      *ifindex = osif->ifindex;
+	      return osif->ifp;
+	    }
+	}
+    }
+  return NULL;
+}
+
+int
+ospf_snmp_iftype (struct interface *ifp)
+{
+#define ospf_snmp_iftype_broadcast         1
+#define ospf_snmp_iftype_nbma              2
+#define ospf_snmp_iftype_pointToPoint      3
+#define ospf_snmp_iftype_pointToMultipoint 5
+  if (if_is_broadcast (ifp))
+    return ospf_snmp_iftype_broadcast;
+  if (if_is_pointopoint (ifp))
+    return ospf_snmp_iftype_pointToPoint;
+  return ospf_snmp_iftype_broadcast;
+}
+
+struct interface *
+ospfIfLookup (struct variable *v, oid *name, size_t *length,
+	      struct in_addr *ifaddr, unsigned int *ifindex, int exact)
+{
+  int len;
+  int ifaddr_next = 0;
+  int ifindex_next = 0;
+  struct interface *ifp;
+  oid *offset;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + 1)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
+      *ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      return ospf_snmp_if_lookup (ifaddr, ifindex);
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len >= IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      if (len <= 0)
+	ifaddr_next = 1;
+
+      oid2in_addr (name + v->namelen, len, ifaddr);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len >= 1)
+	len = 1;
+      else
+	ifindex_next = 1;
+
+      if (len == 1)
+	*ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      ifp = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
+				      ifindex_next);
+      if (ifp)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + 1;
+	  offset = name + v->namelen;
+	  oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
+	  offset += IN_ADDR_SIZE;
+	  *offset = *ifindex;
+	  return ifp;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact,
+	     size_t  *var_len, WriteMethod **write_method)
+{
+  struct interface *ifp;
+  unsigned int ifindex;
+  struct in_addr ifaddr;
+  struct ospf_interface *oi;
+
+  ifindex = 0;
+  memset (&ifaddr, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  ifp = ospfIfLookup (v, name, length, &ifaddr, &ifindex, exact);
+  if (ifp == NULL)
+    return NULL;
+
+  oi = ospf_if_lookup_by_local_addr (ifp, ifaddr);
+  if (oi == NULL)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFIFIPADDRESS:	/* 1 */
+      return SNMP_IPADDRESS (ifaddr);
+      break;
+    case OSPFADDRESSLESSIF:	/* 2 */
+      return SNMP_INTEGER (ifindex);
+      break;
+    case OSPFIFAREAID:		/* 3 */
+      if (oi->area)
+	return SNMP_IPADDRESS (oi->area->area_id);
+      else
+	return SNMP_IPADDRESS (ospf_empty_addr);
+      break;
+    case OSPFIFTYPE:		/* 4 */
+      return SNMP_INTEGER (ospf_snmp_iftype (ifp));
+      break;
+    case OSPFIFADMINSTAT:	/* 5 */
+      if (oi)
+	return SNMP_INTEGER (OSPF_STATUS_ENABLED);
+      else
+	return SNMP_INTEGER (OSPF_STATUS_DISABLED);
+      break;
+    case OSPFIFRTRPRIORITY:	/* 6 */
+      return SNMP_INTEGER (PRIORITY (oi));
+      break;
+    case OSPFIFTRANSITDELAY:	/* 7 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
+      break;
+    case OSPFIFRETRANSINTERVAL:	/* 8 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
+      break;
+    case OSPFIFHELLOINTERVAL:	/* 9 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
+      break;
+    case OSPFIFRTRDEADINTERVAL:	/* 10 */
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
+      break;
+    case OSPFIFPOLLINTERVAL:	/* 11 */
+      return SNMP_INTEGER (OSPF_POLL_INTERVAL_DEFAULT);
+      break;
+    case OSPFIFSTATE:		/* 12 */
+      return SNMP_INTEGER (oi->state);
+      break;
+    case OSPFIFDESIGNATEDROUTER: /* 13 */
+      return SNMP_IPADDRESS (DR (oi));
+      break;
+    case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */
+      return SNMP_IPADDRESS (BDR (oi));
+      break;
+    case OSPFIFEVENTS:		/* 15 */
+      return SNMP_INTEGER (oi->state_change);
+      break;
+    case OSPFIFAUTHKEY:		/* 16 */
+      *var_len = 0;
+      return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
+      break;
+    case OSPFIFSTATUS:		/* 17 */
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFIFMULTICASTFORWARDING: /* 18 */
+#define ospf_snmp_multiforward_blocked    1
+#define ospf_snmp_multiforward_multicast  2
+#define ospf_snmp_multiforward_unicast    3
+      return SNMP_INTEGER (ospf_snmp_multiforward_blocked);
+      break;
+    case OSPFIFDEMAND:		/* 19 */
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    case OSPFIFAUTHTYPE:	/* 20 */
+      if (oi->area)
+	return SNMP_INTEGER (oi->area->auth_type);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+#define OSPF_SNMP_METRIC_VALUE 1
+
+struct interface *
+ospfIfMetricLookup (struct variable *v, oid *name, size_t *length,
+		    struct in_addr *ifaddr, unsigned int *ifindex, int exact)
+{
+  int len;
+  int ifaddr_next = 0;
+  int ifindex_next = 0;
+  struct interface *ifp;
+  oid *offset;
+  int metric;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr);
+      *ifindex = name[v->namelen + IN_ADDR_SIZE];
+      metric = name[v->namelen + IN_ADDR_SIZE + 1];
+
+      if (metric != OSPF_SNMP_METRIC_VALUE)
+	return NULL;
+
+      return ospf_snmp_if_lookup (ifaddr, ifindex);
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len >= IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      else
+	ifaddr_next = 1;
+
+      oid2in_addr (name + v->namelen, len, ifaddr);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len >= 1)
+	len = 1;
+      else
+	ifindex_next = 1;
+
+      if (len == 1)
+	*ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      ifp = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next,
+				      ifindex_next);
+      if (ifp)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + 1 + 1;
+	  offset = name + v->namelen;
+	  oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE);
+	  offset += IN_ADDR_SIZE;
+	  *offset = *ifindex;
+	  offset++;
+	  *offset = OSPF_SNMP_METRIC_VALUE;
+	  return ifp;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact,
+		   size_t *var_len, WriteMethod **write_method)
+{
+  /* Currently we support metric 1 only. */
+  struct interface *ifp;
+  unsigned int ifindex;
+  struct in_addr ifaddr;
+  struct ospf_interface *oi;
+
+  ifindex = 0;
+  memset (&ifaddr, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  ifp = ospfIfMetricLookup (v, name, length, &ifaddr, &ifindex, exact);
+  if (ifp == NULL)
+    return NULL;
+
+  oi = ospf_if_lookup_by_local_addr (ifp, ifaddr);
+  if (oi == NULL)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFIFMETRICIPADDRESS:
+      return SNMP_IPADDRESS (ifaddr);
+      break;
+    case OSPFIFMETRICADDRESSLESSIF:
+      return SNMP_INTEGER (ifindex);
+      break;
+    case OSPFIFMETRICTOS:
+      return SNMP_INTEGER (0);
+      break;
+    case OSPFIFMETRICVALUE:
+      return SNMP_INTEGER (OSPF_SNMP_METRIC_VALUE);
+      break;
+    case OSPFIFMETRICSTATUS:
+      return SNMP_INTEGER (1);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct route_table *ospf_snmp_vl_table;
+
+void
+ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = vl_data->vl_area_id;
+  lp.adv_router = vl_data->vl_peer;
+
+  rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
+  rn->info = vl_data;
+}
+
+void
+ospf_snmp_vl_delete (struct ospf_vl_data *vl_data)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = vl_data->vl_area_id;
+  lp.adv_router = vl_data->vl_peer;
+
+  rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
+  if (! rn)
+    return;
+  rn->info = NULL;
+  route_unlock_node (rn);
+  route_unlock_node (rn);
+}
+
+struct ospf_vl_data *
+ospf_snmp_vl_lookup (struct in_addr *area_id, struct in_addr *neighbor)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+  struct ospf_vl_data *vl_data;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = *area_id;
+  lp.adv_router = *neighbor;
+
+  rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
+  if (rn)
+    {
+      vl_data = rn->info;
+      route_unlock_node (rn);
+      return vl_data;
+    }
+  return NULL;
+}
+
+struct ospf_vl_data *
+ospf_snmp_vl_lookup_next (struct in_addr *area_id, struct in_addr *neighbor,
+			  int first)
+{
+  struct prefix_ls lp;
+  struct route_node *rn;
+  struct ospf_vl_data *vl_data;
+
+  memset (&lp, 0, sizeof (struct prefix_ls));
+  lp.family = 0;
+  lp.prefixlen = 64;
+  lp.id = *area_id;
+  lp.adv_router = *neighbor;
+
+  if (first)
+    rn = route_top (ospf_snmp_vl_table);
+  else
+    {
+      rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp);
+      rn = route_next (rn);
+    }
+
+  for (; rn; rn = route_next (rn))
+    if (rn->info)
+      break;
+
+  if (rn && rn->info)
+    {
+      vl_data = rn->info;
+      *area_id = vl_data->vl_area_id;
+      *neighbor = vl_data->vl_peer;
+      route_unlock_node (rn);
+      return vl_data;
+    }
+  return NULL;
+}
+
+struct ospf_vl_data *
+ospfVirtIfLookup (struct variable *v, oid *name, size_t *length,
+		  struct in_addr *area_id, struct in_addr *neighbor, int exact)
+{
+  int first;
+  int len;
+  struct ospf_vl_data *vl_data;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, area_id);
+      oid2in_addr (name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE, neighbor);
+
+      return ospf_snmp_vl_lookup (area_id, neighbor);
+    }
+  else
+    {
+      first = 0;
+
+      len = *length - v->namelen;
+      if (len <= 0)
+	first = 1;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      oid2in_addr (name + v->namelen, len, area_id);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+      oid2in_addr (name + v->namelen + IN_ADDR_SIZE, len, neighbor);
+
+      vl_data = ospf_snmp_vl_lookup_next (area_id, neighbor, first);
+
+      if (vl_data)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE;
+	  oid_copy_addr (name + v->namelen, area_id, IN_ADDR_SIZE);
+	  oid_copy_addr (name + v->namelen + IN_ADDR_SIZE, neighbor,
+			 IN_ADDR_SIZE);
+	  return vl_data;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact,
+		 size_t  *var_len, WriteMethod **write_method)
+{
+  struct ospf_vl_data *vl_data;
+  struct ospf_interface *oi;
+  struct in_addr area_id;
+  struct in_addr neighbor;
+
+  memset (&area_id, 0, sizeof (struct in_addr));
+  memset (&neighbor, 0, sizeof (struct in_addr));
+
+  vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
+  if (! vl_data)
+    return NULL;
+  oi = vl_data->vl_oi;
+  if (! oi)
+    return NULL;
+  
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFVIRTIFAREAID:
+      return SNMP_IPADDRESS (area_id);
+      break;
+    case OSPFVIRTIFNEIGHBOR:
+      return SNMP_IPADDRESS (neighbor);
+      break;
+    case OSPFVIRTIFTRANSITDELAY:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay));
+      break;
+    case OSPFVIRTIFRETRANSINTERVAL:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval));
+      break;
+    case OSPFVIRTIFHELLOINTERVAL:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello));
+      break;
+    case OSPFVIRTIFRTRDEADINTERVAL:
+      return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait));
+      break;
+    case OSPFVIRTIFSTATE:
+      return SNMP_INTEGER (oi->state);
+      break;
+    case OSPFVIRTIFEVENTS:
+      return SNMP_INTEGER (oi->state_change);
+      break;
+    case OSPFVIRTIFAUTHKEY:
+      *var_len = 0;
+      return (u_char *) OSPF_IF_PARAM (oi, auth_simple);
+      break;
+    case OSPFVIRTIFSTATUS:
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFVIRTIFAUTHTYPE:
+      if (oi->area)
+	return SNMP_INTEGER (oi->area->auth_type);
+      else
+	return SNMP_INTEGER (0);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_neighbor *
+ospf_snmp_nbr_lookup (struct in_addr *nbr_addr, unsigned int *ifindex)
+{
+  struct listnode *nn;
+  struct ospf_interface *oi;
+  struct ospf_neighbor *nbr;
+  struct route_node *rn;
+
+  LIST_LOOP (ospf_top->oiflist, oi, nn)
+    {
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info) != NULL
+	    && nbr != oi->nbr_self
+	    && nbr->state != NSM_Down
+	    && nbr->src.s_addr != 0)
+	  {
+	    if (IPV4_ADDR_SAME (&nbr->src, nbr_addr))
+	      {
+		route_unlock_node (rn);
+		return nbr;
+	      }
+	  }
+    }
+  return NULL;
+}
+
+struct ospf_neighbor *
+ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex,
+			   int first)
+{
+  struct listnode *nn;
+  struct ospf_interface *oi;
+  struct ospf_neighbor *nbr;
+  struct route_node *rn;
+  struct ospf_neighbor *min = NULL;
+
+  LIST_LOOP (ospf_top->oiflist, oi, nn)
+    {
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info) != NULL
+	    && nbr != oi->nbr_self
+	    && nbr->state != NSM_Down
+	    && nbr->src.s_addr != 0)
+	  {
+	    if (first)
+	      {
+		if (! min)
+		  min = nbr;
+		else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
+		  min = nbr;
+	      }
+	    else if (ntohl (nbr->src.s_addr) > ntohl (nbr_addr->s_addr))
+	      {
+		if (! min)
+		  min = nbr;
+		else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr))
+		  min = nbr;
+	      }
+	  }
+    }
+  if (min)
+    {
+      *nbr_addr = min->src;
+      *ifindex = 0;
+      return min;
+    }
+  return NULL;
+}
+
+struct ospf_neighbor *
+ospfNbrLookup (struct variable *v, oid *name, size_t *length,
+	       struct in_addr *nbr_addr, unsigned int *ifindex, int exact)
+{
+  int len;
+  int first;
+  struct ospf_neighbor *nbr;
+
+  if (exact)
+    {
+      if (*length != v->namelen + IN_ADDR_SIZE + 1)
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, nbr_addr);
+      *ifindex = name[v->namelen + IN_ADDR_SIZE];
+
+      return ospf_snmp_nbr_lookup (nbr_addr, ifindex);
+    }
+  else
+    {
+      first = 0;
+      len = *length - v->namelen;
+
+      if (len <= 0)
+	first = 1;
+
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (name + v->namelen, len, nbr_addr);
+
+      len = *length - v->namelen - IN_ADDR_SIZE;
+      if (len >= 1)
+	*ifindex = name[v->namelen + IN_ADDR_SIZE];
+      
+      nbr = ospf_snmp_nbr_lookup_next (nbr_addr, ifindex, first);
+
+      if (nbr)
+	{
+	  *length = v->namelen + IN_ADDR_SIZE + 1;
+	  oid_copy_addr (name + v->namelen, nbr_addr, IN_ADDR_SIZE);
+	  name[v->namelen + IN_ADDR_SIZE] = *ifindex;
+	  return nbr;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
+	      size_t  *var_len, WriteMethod **write_method)
+{
+  struct in_addr nbr_addr;
+  unsigned int ifindex;
+  struct ospf_neighbor *nbr;
+  struct ospf_interface *oi;
+
+  memset (&nbr_addr, 0, sizeof (struct in_addr));
+  ifindex = 0;
+  
+  nbr = ospfNbrLookup (v, name, length, &nbr_addr, &ifindex, exact);
+  if (! nbr)
+    return NULL;
+  oi = nbr->oi;
+  if (! oi)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFNBRIPADDR:
+      return SNMP_IPADDRESS (nbr_addr);
+      break;
+    case OSPFNBRADDRESSLESSINDEX:
+      return SNMP_INTEGER (ifindex);
+      break;
+    case OSPFNBRRTRID:
+      return SNMP_IPADDRESS (nbr->router_id);
+      break;
+    case OSPFNBROPTIONS:
+      return SNMP_INTEGER (oi->nbr_self->options);
+      break;
+    case OSPFNBRPRIORITY:
+      return SNMP_INTEGER (nbr->priority);
+      break;
+    case OSPFNBRSTATE:
+      return SNMP_INTEGER (nbr->state);
+      break;
+    case OSPFNBREVENTS:
+      return SNMP_INTEGER (nbr->state_change);
+      break;
+    case OSPFNBRLSRETRANSQLEN:
+      return SNMP_INTEGER (ospf_ls_retransmit_count (nbr));
+      break;
+    case OSPFNBMANBRSTATUS:
+      return SNMP_INTEGER (SNMP_VALID);
+      break;
+    case OSPFNBMANBRPERMANENCE:
+      return SNMP_INTEGER (2);
+      break;
+    case OSPFNBRHELLOSUPPRESSED:
+      return SNMP_INTEGER (SNMP_FALSE);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfVirtNbrEntry (struct variable *v, oid *name, size_t *length, int exact,
+		  size_t  *var_len, WriteMethod **write_method)
+{
+  struct ospf_vl_data *vl_data;
+  struct in_addr area_id;
+  struct in_addr neighbor;
+
+  memset (&area_id, 0, sizeof (struct in_addr));
+  memset (&neighbor, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact);
+  if (! vl_data)
+    return NULL;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFVIRTNBRAREA:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRRTRID:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRIPADDR:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBROPTIONS:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRSTATE:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBREVENTS:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRLSRETRANSQLEN:
+      return (u_char *) NULL;
+      break;
+    case OSPFVIRTNBRHELLOSUPPRESSED:
+      return (u_char *) NULL;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+struct ospf_lsa *
+ospfExtLsdbLookup (struct variable *v, oid *name, size_t *length, u_char *type,
+		   struct in_addr *ls_id, struct in_addr *router_id, int exact)
+{
+  int first;
+  oid *offset;
+  int offsetlen;
+  u_char lsa_type;
+  int len;
+  struct ospf_lsa *lsa;
+
+  if (exact)
+    {
+      if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
+	return NULL;
+      
+      offset = name + v->namelen;
+
+      /* Make it sure given value match to type. */
+      lsa_type = *offset;
+      offset++;
+
+      if (lsa_type != *type)
+	return NULL;
+      
+      /* LS ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, ls_id);
+      offset += IN_ADDR_SIZE;
+
+      /* Router ID. */
+      oid2in_addr (offset, IN_ADDR_SIZE, router_id);
+
+      return ospf_lsdb_lookup_by_id (ospf_top->lsdb, *type, *ls_id, *router_id);
+    }
+  else
+    {
+      /* Get variable length. */
+      first = 0;
+      offset = name + v->namelen;
+      offsetlen = *length - v->namelen;
+
+      /* LSA type value. */
+      lsa_type = *offset;
+      offset++;
+      offsetlen--;
+
+      if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA)
+	first = 1;
+
+      /* LS ID. */
+      len = offsetlen;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, ls_id);
+
+      offset += IN_ADDR_SIZE;
+      offsetlen -= IN_ADDR_SIZE;
+
+      /* Router ID. */
+      len = offsetlen;
+      if (len > IN_ADDR_SIZE)
+	len = IN_ADDR_SIZE;
+
+      oid2in_addr (offset, len, router_id);
+
+      lsa = ospf_lsdb_lookup_by_id_next (ospf_top->lsdb, *type, *ls_id,
+					*router_id, first);
+
+      if (lsa)
+	{
+	  /* Fill in length. */
+	  *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE;
+
+	  /* Fill in value. */
+	  offset = name + v->namelen;
+
+	  *offset = OSPF_AS_EXTERNAL_LSA;
+	  offset++;
+	  oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE);
+	  offset += IN_ADDR_SIZE;
+	  oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE);
+	    
+	  return lsa;
+	}
+    }
+  return NULL;
+}
+
+static u_char *
+ospfExtLsdbEntry (struct variable *v, oid *name, size_t *length, int exact,
+		  size_t  *var_len, WriteMethod **write_method)
+{
+  struct ospf_lsa *lsa;
+  struct lsa_header *lsah;
+  u_char type;
+  struct in_addr ls_id;
+  struct in_addr router_id;
+
+  type = OSPF_AS_EXTERNAL_LSA;
+  memset (&ls_id, 0, sizeof (struct in_addr));
+  memset (&router_id, 0, sizeof (struct in_addr));
+
+  /* Check OSPF instance. */
+  if (! ospf_top)
+    return NULL;
+
+  lsa = ospfExtLsdbLookup (v, name, length, &type, &ls_id, &router_id, exact);
+  if (! lsa)
+    return NULL;
+
+  lsah = lsa->data;
+
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFEXTLSDBTYPE:
+      return SNMP_INTEGER (OSPF_AS_EXTERNAL_LSA);
+      break;
+    case OSPFEXTLSDBLSID:
+      return SNMP_IPADDRESS (lsah->id);
+      break;
+    case OSPFEXTLSDBROUTERID:
+      return SNMP_IPADDRESS (lsah->adv_router);
+      break;
+    case OSPFEXTLSDBSEQUENCE:
+      return SNMP_INTEGER (lsah->ls_seqnum);
+      break;
+    case OSPFEXTLSDBAGE:
+      return SNMP_INTEGER (lsah->ls_age);
+      break;
+    case OSPFEXTLSDBCHECKSUM:
+      return SNMP_INTEGER (lsah->checksum);
+      break;
+    case OSPFEXTLSDBADVERTISEMENT:
+      *var_len = ntohs (lsah->length);
+      return (u_char *) lsah;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+static u_char *
+ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length,
+			int exact, size_t *var_len, WriteMethod **write_method)
+{
+  /* Return the current value of the variable */
+  switch (v->magic) 
+    {
+    case OSPFAREAAGGREGATEAREAID:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATELSDBTYPE:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATENET:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATEMASK:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATESTATUS:
+      return (u_char *) NULL;
+      break;
+    case OSPFAREAAGGREGATEEFFECT:
+      return (u_char *) NULL;
+      break;
+    default:
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+/* Register OSPF2-MIB. */
+void
+ospf_snmp_init ()
+{
+  ospf_snmp_iflist = list_new ();
+  ospf_snmp_vl_table = route_table_init ();
+  smux_init (ospfd_oid, sizeof (ospfd_oid) / sizeof (oid));
+  REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
+  smux_start ();
+}
+#endif /* HAVE_SNMP */
diff --git a/ospfd/ospf_snmp.h b/ospfd/ospf_snmp.h
new file mode 100644
index 0000000..d82f87b
--- /dev/null
+++ b/ospfd/ospf_snmp.h
@@ -0,0 +1,33 @@
+/* OSPFv2 SNMP support
+ * Copyright (C) 2000 IP Infusion Inc.
+ *
+ * Written by Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef _ZEBRA_OSPF_SNMP_H
+#define _ZEBRA_OSPF_SNMP_H
+
+void ospf_snmp_if_update (struct interface *);
+void ospf_snmp_if_delete (struct interface *);
+
+void ospf_snmp_vl_add (struct ospf_vl_data *);
+void ospf_snmp_vl_delete (struct ospf_vl_data *);
+
+#endif /* _ZEBRA_OSPF_SNMP_H */
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
new file mode 100644
index 0000000..d625471
--- /dev/null
+++ b/ospfd/ospf_spf.c
@@ -0,0 +1,1088 @@
+/* OSPF SPF calculation.
+   Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "hash.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "log.h"
+#include "sockunion.h"          /* for inet_ntop () */
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ia.h"
+#include "ospfd/ospf_ase.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_dump.h"
+
+#define DEBUG
+
+struct vertex_nexthop *
+vertex_nexthop_new (struct vertex *parent)
+{
+  struct vertex_nexthop *new;
+
+  new = XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
+  new->parent = parent;
+
+  return new;
+}
+
+void
+vertex_nexthop_free (struct vertex_nexthop *nh)
+{
+  XFREE (MTYPE_OSPF_NEXTHOP, nh);
+}
+
+struct vertex_nexthop *
+vertex_nexthop_dup (struct vertex_nexthop *nh)
+{
+  struct vertex_nexthop *new;
+
+  new = vertex_nexthop_new (nh->parent);
+
+  new->oi = nh->oi;
+  new->router = nh->router;
+
+  return new;
+}
+
+
+struct vertex *
+ospf_vertex_new (struct ospf_lsa *lsa)
+{
+  struct vertex *new;
+
+  new = XMALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
+  memset (new, 0, sizeof (struct vertex));
+
+  new->flags = 0;
+  new->type = lsa->data->type;
+  new->id = lsa->data->id;
+  new->lsa = lsa->data;
+  new->distance = 0;
+  new->child = list_new ();
+  new->nexthop = list_new ();
+
+  return new;
+}
+
+void
+ospf_vertex_free (struct vertex *v)
+{
+  listnode node;
+
+  list_delete (v->child);
+
+  if (listcount (v->nexthop) > 0)
+    for (node = listhead (v->nexthop); node; nextnode (node))
+      vertex_nexthop_free (node->data);
+
+  list_delete (v->nexthop);
+
+  XFREE (MTYPE_OSPF_VERTEX, v);
+}
+
+void
+ospf_vertex_add_parent (struct vertex *v)
+{
+  struct vertex_nexthop *nh;
+  listnode node;
+
+  for (node = listhead (v->nexthop); node; nextnode (node))
+    {
+      nh = (struct vertex_nexthop *) getdata (node);
+
+      /* No need to add two links from the same parent. */
+      if (listnode_lookup (nh->parent->child, v) == NULL)
+	listnode_add (nh->parent->child, v);
+    }
+}
+
+void
+ospf_spf_init (struct ospf_area *area)
+{
+  struct vertex *v;
+
+  /* Create root node. */
+  v = ospf_vertex_new (area->router_lsa_self);
+
+  area->spf = v;
+
+  /* Reset ABR and ASBR router counts. */
+  area->abr_count = 0;
+  area->asbr_count = 0;
+}
+
+int
+ospf_spf_has_vertex (struct route_table *rv, struct route_table *nv,
+                     struct lsa_header *lsa)
+{
+  struct prefix p;
+  struct route_node *rn;
+
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+  p.u.prefix4 = lsa->id;
+
+  if (lsa->type == OSPF_ROUTER_LSA)
+    rn = route_node_get (rv, &p);
+  else
+    rn = route_node_get (nv, &p);
+
+  if (rn->info != NULL)
+    {
+      route_unlock_node (rn);
+      return 1;
+    }
+  return 0;
+}
+
+listnode
+ospf_vertex_lookup (list vlist, struct in_addr id, int type)
+{
+  listnode node;
+  struct vertex *v;
+
+  for (node = listhead (vlist); node; nextnode (node))
+    {
+      v = (struct vertex *) getdata (node);
+      if (IPV4_ADDR_SAME (&id, &v->id) && type == v->type)
+        return node;
+    }
+
+  return NULL;
+}
+
+int
+ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
+{
+  int i;
+  int length;
+  struct router_lsa *rl;
+  struct network_lsa *nl;
+
+  /* In case of W is Network LSA. */
+  if (w->type == OSPF_NETWORK_LSA)
+    {
+      if (v->type == OSPF_NETWORK_LSA)
+        return 0;
+
+      nl = (struct network_lsa *) w;
+      length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
+      
+      for (i = 0; i < length; i++)
+        if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
+          return 1;
+      return 0;
+    }
+
+  /* In case of W is Router LSA. */
+  if (w->type == OSPF_ROUTER_LSA)
+    {
+      rl = (struct router_lsa *) w;
+
+      length = ntohs (w->length);
+
+      for (i = 0;
+	   i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
+	   i++, length -= 12)
+        {
+          switch (rl->link[i].type)
+            {
+            case LSA_LINK_TYPE_POINTOPOINT:
+            case LSA_LINK_TYPE_VIRTUALLINK:
+              /* Router LSA ID. */
+              if (v->type == OSPF_ROUTER_LSA &&
+                  IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
+                {
+                  return 1;
+                }
+              break;
+            case LSA_LINK_TYPE_TRANSIT:
+              /* Network LSA ID. */
+              if (v->type == OSPF_NETWORK_LSA &&
+                  IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
+                {
+                  return 1;
+		}
+              break;
+            case LSA_LINK_TYPE_STUB:
+              /* Not take into count? */
+              continue;
+            default:
+              break;
+            }
+        }
+    }
+  return 0;
+}
+
+/* Add the nexthop to the list, only if it is unique.
+ * If it's not unique, free the nexthop entry.
+ */
+void
+ospf_nexthop_add_unique (struct vertex_nexthop *new, list nexthop)
+{
+  struct vertex_nexthop *nh;
+  listnode node;
+  int match;
+
+  match = 0;
+  for (node = listhead (nexthop); node; nextnode (node))
+    {
+      nh = node->data;
+
+      /* Compare the two entries. */
+      /* XXX
+       * Comparing the parent preserves the shortest path tree
+       * structure even when the nexthops are identical.
+       */
+      if (nh->oi == new->oi &&
+	  IPV4_ADDR_SAME (&nh->router, &new->router) &&
+	  nh->parent == new->parent)
+	{
+	  match = 1;
+	  break;
+	}
+    }
+
+  if (!match)
+    listnode_add (nexthop, new);
+  else
+    vertex_nexthop_free (new);
+}
+
+/* Merge entries in list b into list a. */
+void
+ospf_nexthop_merge (list a, list b)
+{
+  struct listnode *n;
+
+  for (n = listhead (b); n; nextnode (n))
+    {
+      ospf_nexthop_add_unique (n->data, a);
+    }
+}
+
+#define ROUTER_LSA_MIN_SIZE 12
+#define ROUTER_LSA_TOS_SIZE 4
+
+struct router_lsa_link *
+ospf_get_next_link (struct vertex *v, struct vertex *w,
+		    struct router_lsa_link *prev_link)
+{
+  u_char *p;
+  u_char *lim;
+  struct router_lsa_link *l;
+
+  if (prev_link == NULL)
+    p = ((u_char *) v->lsa) + 24;
+  else
+    {
+      p = (u_char *)prev_link;
+      p += (ROUTER_LSA_MIN_SIZE +
+            (prev_link->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
+    }
+  
+  lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
+
+  while (p < lim)
+    {
+      l = (struct router_lsa_link *) p;
+
+      p += (ROUTER_LSA_MIN_SIZE +
+            (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
+
+      if (l->m[0].type == LSA_LINK_TYPE_STUB)
+        continue;
+
+      /* Defer NH calculation via VLs until summaries from
+         transit areas area confidered             */
+
+      if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
+        continue; 
+
+      if (IPV4_ADDR_SAME (&l->link_id, &w->id))
+          return l;
+    }
+
+  return NULL;
+}
+
+/* Calculate nexthop from root to vertex W. */
+void
+ospf_nexthop_calculation (struct ospf_area *area,
+                          struct vertex *v, struct vertex *w)
+{
+  listnode node;
+  struct vertex_nexthop *nh, *x;
+  struct ospf_interface *oi = NULL;
+  struct router_lsa_link *l = NULL;
+	  
+    
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_nexthop_calculation(): Start");
+
+  /* W's parent is root. */
+  if (v == area->spf)
+    {
+      if (w->type == OSPF_VERTEX_ROUTER)
+	{
+	  while ((l = ospf_get_next_link (v, w, l)))
+	    {
+	      struct router_lsa_link *l2 = NULL;
+	      
+	      if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
+		{
+		  while ((l2 = ospf_get_next_link (w, v, l2)))
+		    {
+		      oi = ospf_if_is_configured (&(l2->link_data));
+		      
+		      if (oi == NULL)
+			continue;
+		      
+		      if (! IPV4_ADDR_SAME (&oi->address->u.prefix4,
+					    &l->link_data))
+			continue;
+		      
+		      break;
+		    }
+		  
+		  if (oi && l2)
+		    {
+		      nh = vertex_nexthop_new (v);
+		      nh->oi = oi;
+		      nh->router = l2->link_data;
+		      listnode_add (w->nexthop, nh);
+		    }
+		}
+	    }
+	}
+      else
+	{
+	  while ((l = ospf_get_next_link (v, w, l)))
+	    {
+	      oi = ospf_if_is_configured (&(l->link_data));
+	      if (oi)
+		{
+		  nh = vertex_nexthop_new (v);
+		  nh->oi = oi;
+		  nh->router.s_addr = 0;
+		  listnode_add (w->nexthop, nh);
+		}
+	    }
+	}
+      return;
+    }
+  /* In case of W's parent is network connected to root. */
+  else if (v->type == OSPF_VERTEX_NETWORK)
+    {
+      for (node = listhead (v->nexthop); node; nextnode (node))
+        {
+          x = (struct vertex_nexthop *) getdata (node);
+          if (x->parent == area->spf)
+            {
+	      while ((l = ospf_get_next_link (w, v, l)))
+		{
+		  nh = vertex_nexthop_new (v);
+		  nh->oi = x->oi;
+		  nh->router = l->link_data;
+		  listnode_add (w->nexthop, nh);
+		}
+	      return;
+	    }
+        }
+    }
+
+  /* Inherit V's nexthop. */
+  for (node = listhead (v->nexthop); node; nextnode (node))
+    {
+      nh = vertex_nexthop_dup (node->data);
+      nh->parent = v;
+      ospf_nexthop_add_unique (nh, w->nexthop);
+    }
+}
+
+void
+ospf_install_candidate (list candidate, struct vertex *w)
+{
+  listnode node;
+  struct vertex *cw;
+
+  if (list_isempty (candidate))
+    {
+      listnode_add (candidate, w);
+      return;
+    }
+
+  /* Install vertex with sorting by distance. */
+  for (node = listhead (candidate); node; nextnode (node))
+    {
+      cw = (struct vertex *) getdata (node);
+      if (cw->distance > w->distance)
+        {
+          list_add_node_prev (candidate, node, w);
+          break;
+        }
+      else if (node->next == NULL)
+        {
+          list_add_node_next (candidate, node, w);
+          break;
+        }
+    }
+}
+
+/* RFC2328 Section 16.1 (2). */
+void
+ospf_spf_next (struct vertex *v, struct ospf_area *area,
+               list candidate, struct route_table *rv,
+               struct route_table *nv)
+{
+  struct ospf_lsa *w_lsa = NULL;
+  struct vertex *w, *cw;
+  u_char *p;
+  u_char *lim;
+  struct router_lsa_link *l = NULL;
+  struct in_addr *r;
+  listnode node;
+  int type = 0;
+
+  /* If this is a router-LSA, and bit V of the router-LSA (see Section
+     A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE.  */
+  if (v->type == OSPF_VERTEX_ROUTER)
+    {
+      if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
+        area->transit = OSPF_TRANSIT_TRUE;
+    }
+
+  p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
+  lim =  ((u_char *) v->lsa) + ntohs (v->lsa->length);
+    
+  while (p < lim)
+    {
+      /* In case of V is Router-LSA. */
+      if (v->lsa->type == OSPF_ROUTER_LSA)
+        {
+          l = (struct router_lsa_link *) p;
+
+          p += (ROUTER_LSA_MIN_SIZE + 
+                (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
+
+          /* (a) If this is a link to a stub network, examine the next
+             link in V's LSA.  Links to stub networks will be
+             considered in the second stage of the shortest path
+             calculation. */
+          if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
+            continue;
+
+          /* (b) Otherwise, W is a transit vertex (router or transit
+             network).  Look up the vertex W's LSA (router-LSA or
+             network-LSA) in Area A's link state database. */
+          switch (type)
+            {
+            case LSA_LINK_TYPE_POINTOPOINT:
+            case LSA_LINK_TYPE_VIRTUALLINK:
+              if (type == LSA_LINK_TYPE_VIRTUALLINK)
+		{
+		  if (IS_DEBUG_OSPF_EVENT)
+		    zlog_info ("looking up LSA through VL: %s",
+			       inet_ntoa (l->link_id));
+		}
+
+              w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
+                                       l->link_id);
+              if (w_lsa)
+		{
+		  if (IS_DEBUG_OSPF_EVENT)
+		  zlog_info("found the LSA");
+		}
+              break;
+            case LSA_LINK_TYPE_TRANSIT:
+		  if (IS_DEBUG_OSPF_EVENT)
+
+              zlog_info ("Looking up Network LSA, ID: %s",
+                         inet_ntoa(l->link_id));
+              w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
+					     l->link_id);
+              if (w_lsa)
+		  if (IS_DEBUG_OSPF_EVENT)
+                zlog_info("found the LSA");
+              break;
+            default:
+	      zlog_warn ("Invalid LSA link type %d", type);
+              continue;
+            }
+        }
+      else
+        {
+          /* In case of V is Network-LSA. */
+          r = (struct in_addr *) p ;
+          p += sizeof (struct in_addr);
+
+          /* Lookup the vertex W's LSA. */
+          w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
+        }
+
+      /* (b cont.) If the LSA does not exist, or its LS age is equal
+         to MaxAge, or it does not have a link back to vertex V,
+         examine the next link in V's LSA.[23] */
+      if (w_lsa == NULL)
+        continue;
+
+      if (IS_LSA_MAXAGE (w_lsa))
+        continue;
+
+      if (! ospf_lsa_has_link (w_lsa->data, v->lsa))
+        {
+		  if (IS_DEBUG_OSPF_EVENT)
+	  zlog_info ("The LSA doesn't have a link back");
+          continue;
+        }
+
+      /* (c) If vertex W is already on the shortest-path tree, examine
+         the next link in the LSA. */
+      if (ospf_spf_has_vertex (rv, nv, w_lsa->data))
+        {
+		  if (IS_DEBUG_OSPF_EVENT)
+          zlog_info ("The LSA is already in SPF");
+          continue;
+        }
+
+      /* (d) Calculate the link state cost D of the resulting path
+         from the root to vertex W.  D is equal to the sum of the link
+         state cost of the (already calculated) shortest path to
+         vertex V and the advertised cost of the link between vertices
+         V and W.  If D is: */
+
+      /* prepare vertex W. */
+      w = ospf_vertex_new (w_lsa);
+
+      /* calculate link cost D. */
+      if (v->lsa->type == OSPF_ROUTER_LSA)
+        w->distance = v->distance + ntohs (l->m[0].metric);
+      else
+        w->distance = v->distance;
+
+      /* Is there already vertex W in candidate list? */
+      node = ospf_vertex_lookup (candidate, w->id, w->type);
+      if (node == NULL)
+        {
+          /* Calculate nexthop to W. */
+          ospf_nexthop_calculation (area, v, w);
+
+          ospf_install_candidate (candidate, w);
+        }
+      else
+        {
+          cw = (struct vertex *) getdata (node);
+
+          /* if D is greater than. */
+          if (cw->distance < w->distance)
+            {
+              ospf_vertex_free (w);
+              continue;
+            }
+          /* equal to. */
+          else if (cw->distance == w->distance)
+            {
+              /* Calculate nexthop to W. */
+              ospf_nexthop_calculation (area, v, w);
+              ospf_nexthop_merge (cw->nexthop, w->nexthop);
+              list_delete_all_node (w->nexthop);
+              ospf_vertex_free (w);
+            }
+          /* less than. */
+          else
+            {
+              /* Calculate nexthop. */
+              ospf_nexthop_calculation (area, v, w);
+
+              /* Remove old vertex from candidate list. */
+              ospf_vertex_free (cw);
+              listnode_delete (candidate, cw);
+
+              /* Install new to candidate. */
+              ospf_install_candidate (candidate, w);
+            }
+        }
+    }
+}
+
+/* Add vertex V to SPF tree. */
+void
+ospf_spf_register (struct vertex *v, struct route_table *rv,
+		   struct route_table *nv)
+{
+  struct prefix p;
+  struct route_node *rn;
+
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+  p.u.prefix4 = v->id;
+
+  if (v->type == OSPF_VERTEX_ROUTER)
+    rn = route_node_get (rv, &p);
+  else
+    rn = route_node_get (nv, &p);
+
+  rn->info = v;
+}
+
+void
+ospf_spf_route_free (struct route_table *table)
+{
+  struct route_node *rn;
+  struct vertex *v;
+
+  for (rn = route_top (table); rn; rn = route_next (rn))
+    {
+      if ((v = rn->info))
+	{
+	  ospf_vertex_free (v);
+	  rn->info = NULL;
+	}
+
+      route_unlock_node (rn);
+    }
+
+  route_table_finish (table);
+}
+
+void
+ospf_spf_dump (struct vertex *v, int i)
+{
+  listnode cnode;
+  listnode nnode;
+  struct vertex_nexthop *nexthop;
+
+  if (v->type == OSPF_VERTEX_ROUTER)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
+    }
+  else
+    {
+      struct network_lsa *lsa = (struct network_lsa *) v->lsa;
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
+		   ip_masklen (lsa->mask));
+
+      for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
+        {
+          nexthop = getdata (nnode);
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info (" nexthop %s", inet_ntoa (nexthop->router));
+        }
+    }
+
+  i++;
+
+  for (cnode = listhead (v->child); cnode; nextnode (cnode))
+    {
+      v = getdata (cnode);
+      ospf_spf_dump (v, i);
+    }
+}
+
+/* Second stage of SPF calculation. */
+void
+ospf_spf_process_stubs (struct ospf_area *area, struct vertex * v,
+                        struct route_table *rt)
+{
+  listnode cnode;
+  struct vertex *child;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_process_stub():processing stubs for area %s",
+	       inet_ntoa (area->area_id));
+  if (v->type == OSPF_VERTEX_ROUTER)
+    {
+      u_char *p;
+      u_char *lim;
+      struct router_lsa_link *l;
+      struct router_lsa *rlsa;
+
+  if (IS_DEBUG_OSPF_EVENT)
+      zlog_info ("ospf_process_stub():processing router LSA, id: %s",
+                 inet_ntoa (v->lsa->id));
+      rlsa = (struct router_lsa *) v->lsa;
+
+
+  if (IS_DEBUG_OSPF_EVENT)
+      zlog_info ("ospf_process_stub(): we have %d links to process",
+                 ntohs (rlsa->links));
+      p = ((u_char *) v->lsa) + 24;
+      lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
+
+      while (p < lim)
+        {
+          l = (struct router_lsa_link *) p;
+
+          p += (ROUTER_LSA_MIN_SIZE +
+                (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE));
+
+          if (l->m[0].type == LSA_LINK_TYPE_STUB)
+            ospf_intra_add_stub (rt, l, v, area);
+        }
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+  zlog_info ("children of V:");
+  for (cnode = listhead (v->child); cnode; nextnode (cnode))
+    {
+      child = getdata (cnode);
+  if (IS_DEBUG_OSPF_EVENT)
+      zlog_info (" child : %s", inet_ntoa (child->id));
+    }
+
+  for (cnode = listhead (v->child); cnode; nextnode (cnode))
+    {
+      child = getdata (cnode);
+
+      if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
+	continue;
+
+      ospf_spf_process_stubs (area, child, rt);
+
+      SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
+    }
+}
+
+void
+ospf_rtrs_free (struct route_table *rtrs)
+{
+  struct route_node *rn;
+  list or_list;
+  listnode node;
+
+  if (IS_DEBUG_OSPF_EVENT)
+  zlog_info ("Route: Router Routing Table free");
+
+  for (rn = route_top (rtrs); rn; rn = route_next (rn))
+    if ((or_list = rn->info) != NULL)
+      {
+	for (node = listhead (or_list); node; nextnode (node))
+	  ospf_route_free (node->data);
+
+	list_delete (or_list);
+
+	/* Unlock the node. */
+	rn->info = NULL;
+	route_unlock_node (rn);
+      }
+  route_table_finish (rtrs);
+}
+
+void
+ospf_rtrs_print (struct route_table *rtrs)
+{
+  struct route_node *rn;
+  list or_list;
+  listnode ln;
+  listnode pnode;
+  struct ospf_route *or;
+  struct ospf_path *path;
+  char buf1[BUFSIZ];
+  char buf2[BUFSIZ];
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_rtrs_print() start");
+
+  for (rn = route_top (rtrs); rn; rn = route_next (rn))
+    if ((or_list = rn->info) != NULL)
+      for (ln = listhead (or_list); ln; nextnode (ln))
+        {
+          or = getdata (ln);
+
+          switch (or->path_type)
+            {
+            case OSPF_PATH_INTRA_AREA:
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("%s   [%d] area: %s", 
+			   inet_ntop (AF_INET, &or->id, buf1, BUFSIZ), or->cost,
+			   inet_ntop (AF_INET, &or->u.std.area_id,
+				      buf2, BUFSIZ));
+              break;
+            case OSPF_PATH_INTER_AREA:
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("%s IA [%d] area: %s", 
+			   inet_ntop (AF_INET, &or->id, buf1, BUFSIZ), or->cost,
+			   inet_ntop (AF_INET, &or->u.std.area_id,
+				      buf2, BUFSIZ));
+              break;
+            default:
+              break;
+            }
+
+          for (pnode = listhead (or->path); pnode; nextnode (pnode))
+            {
+              path = getdata (pnode);
+              if (path->nexthop.s_addr == 0)
+		{
+		  if (IS_DEBUG_OSPF_EVENT)
+		    zlog_info ("   directly attached to %s\r\n",
+			       IF_NAME (path->oi));
+		}
+              else 
+		{
+		  if (IS_DEBUG_OSPF_EVENT)
+		    zlog_info ("   via %s, %s\r\n",
+			       inet_ntoa (path->nexthop), IF_NAME (path->oi));
+		}
+            }
+        }
+
+  zlog_info ("ospf_rtrs_print() end");
+}
+
+/* Calculating the shortest-path tree for an area. */
+void
+ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table, 
+                    struct route_table *new_rtrs)
+{
+  list candidate;
+  listnode node;
+  struct vertex *v;
+  struct route_table *rv;
+  struct route_table *nv;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    {
+      zlog_info ("ospf_spf_calculate: Start");
+      zlog_info ("ospf_spf_calculate: running Dijkstra for area %s", 
+		 inet_ntoa (area->area_id));
+    }
+
+  /* Check router-lsa-self.  If self-router-lsa is not yet allocated,
+     return this area's calculation. */
+  if (! area->router_lsa_self)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_spf_calculate: "
+		   "Skip area %s's calculation due to empty router_lsa_self",
+		   inet_ntoa (area->area_id));
+      return;
+    }
+
+  /* RFC2328 16.1. (1). */
+  /* Initialize the algorithm's data structures. */ 
+  rv = route_table_init ();
+  nv = route_table_init ();
+
+  /* Clear the list of candidate vertices. */ 
+  candidate = list_new ();
+
+  /* Initialize the shortest-path tree to only the root (which is the
+     router doing the calculation). */
+  ospf_spf_init (area);
+  v = area->spf;
+  ospf_spf_register (v, rv, nv);
+
+  /* Set Area A's TransitCapability to FALSE. */
+  area->transit = OSPF_TRANSIT_FALSE;
+  area->shortcut_capability = 1;
+
+  for (;;)
+    {
+      /* RFC2328 16.1. (2). */
+      ospf_spf_next (v, area, candidate, rv, nv);
+
+      /* RFC2328 16.1. (3). */
+      /* If at this step the candidate list is empty, the shortest-
+         path tree (of transit vertices) has been completely built and
+         this stage of the procedure terminates. */
+      if (listcount (candidate) == 0)
+        break;
+
+      /* Otherwise, choose the vertex belonging to the candidate list
+         that is closest to the root, and add it to the shortest-path
+         tree (removing it from the candidate list in the
+         process). */ 
+      node = listhead (candidate);
+      v = getdata (node);
+      ospf_vertex_add_parent (v);
+
+      /* Reveve from the candidate list. */
+      listnode_delete (candidate, v);
+
+      /* Add to SPF tree. */
+      ospf_spf_register (v, rv, nv);
+
+      /* Note that when there is a choice of vertices closest to the
+         root, network vertices must be chosen before router vertices
+         in order to necessarily find all equal-cost paths. */
+      /* We don't do this at this moment, we should add the treatment
+         above codes. -- kunihiro. */
+
+      /* RFC2328 16.1. (4). */
+      if (v->type == OSPF_VERTEX_ROUTER)
+        ospf_intra_add_router (new_rtrs, v, area);
+      else 
+        ospf_intra_add_transit (new_table, v, area);
+
+      /* RFC2328 16.1. (5). */
+      /* Iterate the algorithm by returning to Step 2. */
+    }
+
+  if (IS_DEBUG_OSPF_EVENT)
+    {
+      ospf_spf_dump (area->spf, 0);
+      ospf_route_table_dump (new_table);
+    }
+
+  /* Second stage of SPF calculation procedure's  */
+  ospf_spf_process_stubs (area, area->spf, new_table);
+
+  /* Free all vertices which allocated for SPF calculation */
+  ospf_spf_route_free (rv);
+  ospf_spf_route_free (nv);
+
+  /* Free candidate list */
+  list_free (candidate);
+
+  /* Increment SPF Calculation Counter. */
+  area->spf_calculation++;
+
+  ospf_top->ts_spf = time (NULL);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_spf_calculate: Stop");
+}
+
+/* Timer for SPF calculation. */
+int
+ospf_spf_calculate_timer (struct thread *t)
+{
+  struct route_table *new_table, *new_rtrs;
+  struct ospf *ospf;
+  /* struct ospf_area *area; */
+  listnode node;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("SPF: Timer (SPF calculation expire)");
+  
+  ospf = THREAD_ARG (t);
+  ospf->t_spf_calc = NULL;
+
+  /* Allocate new table tree. */
+  new_table = route_table_init ();
+  new_rtrs  = route_table_init ();
+
+  ospf_vl_unapprove ();
+
+  /* Calculate SPF for each area. */
+  for (node = listhead (ospf->areas); node; node = nextnode (node))
+    ospf_spf_calculate (node->data, new_table, new_rtrs);
+
+  ospf_vl_shut_unapproved ();
+
+  ospf_ia_routing (new_table, new_rtrs);
+
+  ospf_prune_unreachable_networks (new_table);
+  ospf_prune_unreachable_routers (new_rtrs);
+
+  /* AS-external-LSA calculation should not be performed here. */
+
+  /* If new Router Route is installed,
+     then schedule re-calculate External routes. */
+  if (1)
+    ospf_ase_calculate_schedule ();
+
+  ospf_ase_calculate_timer_add ();
+
+  /* Update routing table. */
+  ospf_route_install (new_table);
+
+  /* Update ABR/ASBR routing table */
+  if (ospf_top->old_rtrs)
+    {
+      /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
+      /* ospf_route_delete (ospf_top->old_rtrs); */
+      ospf_rtrs_free (ospf_top->old_rtrs);
+    }
+
+  ospf_top->old_rtrs = ospf_top->new_rtrs;
+  ospf_top->new_rtrs = new_rtrs;
+
+  if (OSPF_IS_ABR) 
+    ospf_abr_task (new_table, new_rtrs);
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("SPF: calculation complete");
+
+  return 0;
+}
+
+/* Add schedule for SPF calculation.  To avoid frequenst SPF calc, we
+   set timer for SPF calc. */
+void
+ospf_spf_calculate_schedule ()
+{
+  time_t ht, delay;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("SPF: calculation timer scheduled");
+
+  /* OSPF instance does not exist. */
+  if (!ospf_top)
+    return;
+
+  /* SPF calculation timer is already scheduled. */
+  if (ospf_top->t_spf_calc)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("SPF: calculation timer is already scheduled: %p",
+		   ospf_top->t_spf_calc);
+      return;
+    }
+
+  ht = time (NULL) - ospf_top->ts_spf;
+
+  /* Get SPF calculation delay time. */
+  if (ht < ospf_top->spf_holdtime)
+    {
+      if (ospf_top->spf_holdtime - ht < ospf_top->spf_delay)
+	delay = ospf_top->spf_delay;
+      else
+	delay = ospf_top->spf_holdtime - ht;
+    }
+  else
+    delay = ospf_top->spf_delay;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("SPF: calculation timer delay = %ld", delay);
+  ospf_top->t_spf_calc =
+    thread_add_timer (master, ospf_spf_calculate_timer, ospf_top, delay);
+}
+
diff --git a/ospfd/ospf_spf.h b/ospfd/ospf_spf.h
new file mode 100644
index 0000000..7fe682e
--- /dev/null
+++ b/ospfd/ospf_spf.h
@@ -0,0 +1,50 @@
+/*
+ * OSPF calculation.
+ * Copyright (C) 1999 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#define OSPF_VERTEX_ROUTER  1
+#define OSPF_VERTEX_NETWORK 2
+
+#define OSPF_VERTEX_PROCESSED      0x01
+
+
+struct vertex
+{
+  u_char flags;
+  u_char type;
+  struct in_addr id;
+  struct lsa_header *lsa;
+  u_int32_t distance;
+  list child;
+  list nexthop;
+};
+
+struct vertex_nexthop
+{
+  struct ospf_interface *oi;
+  struct in_addr router;
+  struct vertex *parent;
+};
+
+void ospf_spf_calculate_schedule ();
+void ospf_rtrs_free (struct route_table *);
+
+/* void ospf_spf_calculate_timer_add (); */
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
new file mode 100644
index 0000000..aedac32
--- /dev/null
+++ b/ospfd/ospf_te.c
@@ -0,0 +1,1921 @@
+/*
+ * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt
+ * Copyright (C) 2001 KDD R&D Laboratories, Inc.
+ * http://www.kddlabs.co.jp/
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+/***** MTYPE definition is not reflected to "memory.h" yet. *****/
+#define MTYPE_OSPF_MPLS_TE_LINKPARAMS	0
+
+#include <zebra.h>
+
+#ifdef HAVE_OSPF_TE
+#ifndef HAVE_OPAQUE_LSA
+#error "Wrong configure option"
+#endif /* HAVE_OPAQUE_LSA */
+
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "table.h"
+#include "memory.h"
+#include "command.h"
+#include "vty.h"
+#include "stream.h"
+#include "log.h"
+#include "thread.h"
+#include "hash.h"
+#include "sockunion.h"		/* for inet_aton() */
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ase.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_te.h"
+
+/* Following structure are internal use only. */
+struct ospf_mpls_te
+{
+  enum { disabled, enabled } status;
+
+  /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
+  list iflist;
+
+  /* Store Router-TLV in network byte order. */
+  struct te_tlv_router_addr router_addr;
+};
+
+struct mpls_te_link
+{
+  /*
+   * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field
+   * is subdivided into 8-bit "unused" field and 16-bit "instance" field.
+   * In this implementation, each Link-TLV has its own instance.
+   */
+  u_int32_t instance;
+
+  /* Reference pointer to a Zebra-interface. */
+  struct interface *ifp;
+
+  /* Area info in which this MPLS-TE link belongs to. */
+  struct ospf_area *area;
+
+  /* Flags to manage this link parameters. */
+  u_int32_t flags;
+#define LPFLG_LOOKUP_DONE		0x1
+#define LPFLG_LSA_ENGAGED		0x2
+#define LPFLG_LSA_FORCED_REFRESH	0x4
+
+  /* Store Link-TLV in network byte order. */
+  struct te_tlv_link link_header;
+  struct te_link_subtlv_link_type link_type;
+  struct te_link_subtlv_link_id link_id;
+  struct te_link_subtlv_lclif_ipaddr *lclif_ipaddr;
+  struct te_link_subtlv_rmtif_ipaddr *rmtif_ipaddr;
+  struct te_link_subtlv_te_metric te_metric;
+  struct te_link_subtlv_max_bw max_bw;
+  struct te_link_subtlv_max_rsv_bw max_rsv_bw;
+  struct te_link_subtlv_unrsv_bw unrsv_bw;
+  struct te_link_subtlv_rsc_clsclr rsc_clsclr;
+};
+
+/*
+ * Global variable to manage Opaque-LSA/MPLS-TE on this node.
+ * Note that all parameter values are stored in network byte order.
+ */
+static struct ospf_mpls_te OspfMplsTE;
+
+enum oifstate {
+  OI_ANY, OI_DOWN, OI_UP
+};
+
+enum sched_opcode {
+  REORIGINATE_PER_AREA, REFRESH_THIS_LSA, FLUSH_THIS_LSA
+};
+
+/*------------------------------------------------------------------------*
+ * Followings are initialize/terminate functions for MPLS-TE handling.
+ *------------------------------------------------------------------------*/
+
+static int ospf_mpls_te_new_if (struct interface *ifp);
+static int ospf_mpls_te_del_if (struct interface *ifp);
+static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_status);
+static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);
+static void ospf_mpls_te_config_write_router (struct vty *vty);
+static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp);
+static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
+static int ospf_mpls_te_lsa_originate (void *arg);
+static void ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
+static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode);
+
+static void del_mpls_te_link (void *val);
+static void ospf_mpls_te_register_vty (void);
+
+int
+ospf_mpls_te_init (void)
+{
+  int rc;
+
+  rc = ospf_register_opaque_functab (
+                OSPF_OPAQUE_AREA_LSA,
+                OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
+		ospf_mpls_te_new_if,
+		ospf_mpls_te_del_if,
+		ospf_mpls_te_ism_change,
+		ospf_mpls_te_nsm_change,
+		ospf_mpls_te_config_write_router,
+		ospf_mpls_te_config_write_if,
+		NULL,/* ospf_mpls_te_config_write_debug */
+                ospf_mpls_te_show_info,
+                ospf_mpls_te_lsa_originate,
+                ospf_mpls_te_lsa_refresh,
+		NULL,/* ospf_mpls_te_new_lsa_hook */
+		NULL /* ospf_mpls_te_del_lsa_hook */);
+  if (rc != 0)
+    {
+      zlog_warn ("ospf_mpls_te_init: Failed to register functions");
+      goto out;
+    }
+
+  memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te));
+  OspfMplsTE.status = disabled;
+  OspfMplsTE.iflist = list_new ();
+  OspfMplsTE.iflist->del = del_mpls_te_link;
+
+  ospf_mpls_te_register_vty ();
+
+out:
+  return rc;
+}
+
+void
+ospf_mpls_te_term (void)
+{
+  list_delete (OspfMplsTE.iflist);
+
+  OspfMplsTE.iflist = NULL;
+  OspfMplsTE.status = disabled;
+
+  ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA,
+                              OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
+  return;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are control functions for MPLS-TE parameters management.
+ *------------------------------------------------------------------------*/
+
+static void
+del_mpls_te_link (void *val)
+{
+  XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, val);
+  return;
+}
+
+static u_int32_t
+get_mpls_te_instance_value ()
+{
+  static u_int32_t seqno = 0;
+
+  if (LEGAL_TE_INSTANCE_RANGE (seqno + 1))
+    seqno += 1;
+  else
+    seqno  = 1; /* Avoid zero. */
+
+  return seqno;
+}
+
+static struct ospf_interface *
+lookup_oi_by_ifp (struct interface *ifp,
+                  struct ospf_area *area, enum oifstate oifstate)
+{
+  struct ospf_interface *oi = NULL;
+  struct route_node *rn;
+
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      if ((oi = rn->info) == NULL)
+        continue;
+
+      switch (oifstate)
+        {
+        case OI_ANY:
+          break;
+        case OI_DOWN:
+          if (ospf_if_is_enable (oi))
+            continue;
+          break;
+        case OI_UP:
+          if (! ospf_if_is_enable (oi))
+            continue;
+          break;
+        default:
+          zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate);
+          goto out;
+        }
+
+      if (area == NULL || oi->area == area)
+        return oi;
+    }
+out:
+  return NULL;
+}
+
+static struct mpls_te_link *
+lookup_linkparams_by_ifp (struct interface *ifp)
+{
+  listnode node;
+  struct mpls_te_link *lp;
+
+  for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+    if ((lp = getdata (node)) != NULL)
+      if (lp->ifp == ifp)
+        return lp;
+
+  return NULL;
+}
+
+static struct mpls_te_link *
+lookup_linkparams_by_instance (struct ospf_lsa *lsa)
+{
+  listnode node;
+  struct mpls_te_link *lp;
+  int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
+
+  for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+    if ((lp = getdata (node)) != NULL)
+      if (lp->instance == key)
+        return lp;
+
+  zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key);
+  return NULL;
+}
+
+static void
+ospf_mpls_te_foreach_area (
+  void (*func)(struct mpls_te_link *lp, enum sched_opcode),
+  enum sched_opcode sched_opcode)
+{
+  listnode node, node2;
+  struct mpls_te_link *lp;
+  struct ospf_area *area;
+
+  for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+    {
+      if ((lp = getdata (node)) == NULL)
+        continue;
+      if ((area = lp->area) == NULL)
+        continue;
+      if (lp->flags & LPFLG_LOOKUP_DONE)
+        continue;
+
+      if (func != NULL)
+        (* func)(lp, sched_opcode);
+
+      for (node2 = nextnode (node); node2; nextnode (node2))
+        if ((lp = getdata (node2)) != NULL)
+          if (lp->area != NULL)
+            if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
+              lp->flags |= LPFLG_LOOKUP_DONE;
+    }
+
+  for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+    if ((lp = getdata (node)) != NULL)
+      if (lp->area != NULL)
+        lp->flags &= ~LPFLG_LOOKUP_DONE;
+
+  return;
+}
+
+static void
+set_mpls_te_router_addr (struct in_addr ipv4)
+{
+  OspfMplsTE.router_addr.header.type   = htons (TE_TLV_ROUTER_ADDR);
+  OspfMplsTE.router_addr.header.length = htons (sizeof (ipv4));
+  OspfMplsTE.router_addr.value = ipv4;
+  return;
+}
+
+static void
+set_linkparams_link_header (struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh;
+  u_int16_t length = 0;
+
+  /* TE_LINK_SUBTLV_LINK_TYPE */
+  if (ntohs (lp->link_type.header.type) != 0)
+    length += TLV_SIZE (&lp->link_type.header);
+
+  /* TE_LINK_SUBTLV_LINK_ID */
+  if (ntohs (lp->link_id.header.type) != 0)
+    length += TLV_SIZE (&lp->link_id.header);
+
+  /* TE_LINK_SUBTLV_LCLIF_IPADDR */
+  if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL
+  &&  ntohs (tlvh->type) != 0)
+    length += TLV_SIZE (tlvh);
+
+  /* TE_LINK_SUBTLV_RMTIF_IPADDR */
+  if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL
+  &&  ntohs (tlvh->type) != 0)
+    length += TLV_SIZE (tlvh);
+
+  /* TE_LINK_SUBTLV_TE_METRIC */
+  if (ntohs (lp->te_metric.header.type) != 0)
+    length += TLV_SIZE (&lp->te_metric.header);
+
+  /* TE_LINK_SUBTLV_MAX_BW */
+  if (ntohs (lp->max_bw.header.type) != 0)
+    length += TLV_SIZE (&lp->max_bw.header);
+
+  /* TE_LINK_SUBTLV_MAX_RSV_BW */
+  if (ntohs (lp->max_rsv_bw.header.type) != 0)
+    length += TLV_SIZE (&lp->max_rsv_bw.header);
+
+  /* TE_LINK_SUBTLV_UNRSV_BW */
+  if (ntohs (lp->unrsv_bw.header.type) != 0)
+    length += TLV_SIZE (&lp->unrsv_bw.header);
+
+  /* TE_LINK_SUBTLV_RSC_CLSCLR */
+  if (ntohs (lp->rsc_clsclr.header.type) != 0)
+    length += TLV_SIZE (&lp->rsc_clsclr.header);
+
+  lp->link_header.header.type   = htons (TE_TLV_LINK);
+  lp->link_header.header.length = htons (length);
+
+  return;
+}
+
+static void
+set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp)
+{
+  lp->link_type.header.type   = htons (TE_LINK_SUBTLV_LINK_TYPE);
+  lp->link_type.header.length = htons (sizeof (lp->link_type.link_type.value));
+
+  switch (oi->type)
+    {
+    case OSPF_IFTYPE_POINTOPOINT:
+      lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
+      break;
+    case OSPF_IFTYPE_BROADCAST:
+    case OSPF_IFTYPE_NBMA:
+      lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
+      break;
+    default:
+      /* Not supported yet. *//* XXX */
+      lp->link_type.header.type = htons (0);
+      break;
+    }
+  return;
+}
+
+static void
+set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
+{
+  struct ospf_neighbor *nbr;
+  int done = 0;
+
+  lp->link_id.header.type   = htons (TE_LINK_SUBTLV_LINK_ID);
+  lp->link_id.header.length = htons (sizeof (lp->link_id.value));
+
+  /*
+   * The Link ID is identical to the contents of the Link ID field
+   * in the Router LSA for these link types.
+   */
+  switch (oi->type)
+    {
+    case OSPF_IFTYPE_POINTOPOINT:
+      /* Take the router ID of the neighbor. */
+      if (((nbr = ospf_nbr_lookup_ptop (oi->nbrs, oi->area->top->router_id)))
+      &&  (nbr->state == NSM_Full))
+        {
+          lp->link_id.value = nbr->router_id;
+          done = 1;
+        }
+      break;
+    case OSPF_IFTYPE_BROADCAST:
+    case OSPF_IFTYPE_NBMA:
+      /* Take the interface address of the designated router. */
+      if ((nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi))) == NULL)
+        break;
+
+      if (nbr->state == NSM_Full
+      || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
+      &&  ospf_nbr_count (oi->nbrs, NSM_Full) > 0))
+        {
+          lp->link_id.value = DR (oi);
+          done = 1;
+        }
+      break;
+    default:
+      /* Not supported yet. *//* XXX */
+      lp->link_id.header.type = htons (0);
+      break;
+    }
+
+  if (! done)
+    {
+      struct in_addr mask;
+      masklen2ip (oi->address->prefixlen, &mask);
+      lp->link_id.value.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
+     }
+  return;
+}
+
+static void
+set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric)
+{
+  lp->te_metric.header.type   = htons (TE_LINK_SUBTLV_TE_METRIC);
+  lp->te_metric.header.length = htons (sizeof (lp->te_metric.value));
+  lp->te_metric.value = htonl (te_metric);
+  return;
+}
+
+static void
+set_linkparams_max_bw (struct mpls_te_link *lp, float *fp)
+{
+  lp->max_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_BW);
+  lp->max_bw.header.length = htons (sizeof (lp->max_bw.value));
+  htonf (fp, &lp->max_bw.value);
+  return;
+}
+
+static void
+set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float *fp)
+{
+  lp->max_rsv_bw.header.type   = htons (TE_LINK_SUBTLV_MAX_RSV_BW);
+  lp->max_rsv_bw.header.length = htons (sizeof (lp->max_rsv_bw.value));
+  htonf (fp, &lp->max_rsv_bw.value);
+  return;
+}
+
+static void
+set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float *fp)
+{
+  /* Note that TLV-length field is the size of array. */
+  lp->unrsv_bw.header.type   = htons (TE_LINK_SUBTLV_UNRSV_BW);
+  lp->unrsv_bw.header.length = htons (sizeof (lp->unrsv_bw.value));
+  htonf (fp, &lp->unrsv_bw.value [priority]);
+  return;
+}
+
+static void
+set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor)
+{
+  lp->rsc_clsclr.header.type   = htons (TE_LINK_SUBTLV_RSC_CLSCLR);
+  lp->rsc_clsclr.header.length = htons (sizeof (lp->rsc_clsclr.value));
+  lp->rsc_clsclr.value = htonl (classcolor);
+  return;
+}
+
+static void
+initialize_linkparams (struct mpls_te_link *lp)
+{
+  struct interface *ifp = lp->ifp;
+  struct ospf_interface *oi;
+  float fval;
+  int i;
+
+  if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL)
+    return;
+
+  /*
+   * Try to set initial values those can be derived from
+   * zebra-interface information.
+   */
+  set_linkparams_link_type (oi, lp);
+
+  /*
+   * Linux and *BSD kernel holds bandwidth parameter as an "int" type.
+   * We may have to reconsider, if "ifp->bandwidth" type changes to float.
+   */
+  fval = (float)((ifp->bandwidth ? ifp->bandwidth
+                                 : OSPF_DEFAULT_BANDWIDTH) * 1000 / 8);
+
+  set_linkparams_max_bw (lp, &fval);
+  set_linkparams_max_rsv_bw (lp, &fval);
+
+  for (i = 0; i < 8; i++)
+    set_linkparams_unrsv_bw (lp, i, &fval);
+
+  return;
+}
+
+static int
+is_mandated_params_set (struct mpls_te_link *lp)
+{
+  int rc = 0;
+
+  if (ntohs (OspfMplsTE.router_addr.header.type) == 0)
+    goto out;
+
+  if (ntohs (lp->link_type.header.type) == 0)
+    goto out;
+
+  if (ntohs (lp->link_id.header.type) == 0)
+    goto out;
+
+  rc = 1;
+out:
+  return rc;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are callback functions against generic Opaque-LSAs handling.
+ *------------------------------------------------------------------------*/
+
+static int
+ospf_mpls_te_new_if (struct interface *ifp)
+{
+  struct mpls_te_link *new;
+  int rc = -1;
+
+  if (lookup_linkparams_by_ifp (ifp) != NULL)
+    {
+      zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp);
+      rc = 0; /* Do nothing here. */
+      goto out;
+    }
+
+  if ((new = XMALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS,
+                  sizeof (struct mpls_te_link))) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", strerror (errno));
+      goto out;
+    }
+  memset (new, 0, sizeof (struct mpls_te_link));
+
+  new->area = NULL;
+  new->flags = 0;
+  new->instance = get_mpls_te_instance_value ();
+  new->ifp = ifp;
+
+  initialize_linkparams (new);
+
+  listnode_add (OspfMplsTE.iflist, new);
+
+  /* Schedule Opaque-LSA refresh. *//* XXX */
+
+  rc = 0;
+out:
+  return rc;
+}
+
+static int
+ospf_mpls_te_del_if (struct interface *ifp)
+{
+  struct mpls_te_link *lp;
+  int rc = -1;
+
+  if ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)
+    {
+      list iflist = OspfMplsTE.iflist;
+
+      /* Dequeue listnode entry from the list. */
+      listnode_delete (iflist, lp);
+
+      /* Avoid misjudgement in the next lookup. */
+      if (listcount (iflist) == 0)
+        iflist->head = iflist->tail = NULL;
+
+      XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, lp);
+    }
+
+  /* Schedule Opaque-LSA refresh. *//* XXX */
+
+  rc = 0;
+/*out:*/
+  return rc;
+}
+
+static void
+ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state)
+{
+  struct te_link_subtlv_link_type old_type;
+  struct te_link_subtlv_link_id   old_id;
+  struct mpls_te_link *lp;
+
+  if ((lp = lookup_linkparams_by_ifp (oi->ifp)) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi));
+      goto out;
+    }
+  if (oi->area == NULL || oi->area->top == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
+IF_NAME (oi));
+      goto out;
+    }
+#ifdef notyet
+  if ((lp->area != NULL
+  &&   ! IPV4_ADDR_SAME (&lp->area->area_id, &oi->area->area_id))
+  || (lp->area != NULL && oi->area == NULL))
+    {
+      /* How should we consider this case? */
+      zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A");
+      ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
+    }
+#endif
+  /* Keep Area information in conbination with linkparams. */
+  lp->area = oi->area;
+
+  switch (oi->state)
+    {
+    case ISM_PointToPoint:
+    case ISM_DROther:
+    case ISM_Backup:
+    case ISM_DR:
+      old_type = lp->link_type;
+      old_id   = lp->link_id;
+
+      set_linkparams_link_type (oi, lp);
+      set_linkparams_link_id (oi, lp);
+
+      if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type)
+      ||   old_type.link_type.value     != lp->link_type.link_type.value)
+      ||  (ntohs (old_id.header.type)   != ntohs (lp->link_id.header.type)
+      ||   ntohl (old_id.value.s_addr)  != ntohl (lp->link_id.value.s_addr)))
+        {
+          if (lp->flags & LPFLG_LSA_ENGAGED)
+            ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+          else
+            ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
+        }
+      break;
+    default:
+      lp->link_type.header.type = htons (0);
+      lp->link_id.header.type   = htons (0);
+
+      if (lp->flags & LPFLG_LSA_ENGAGED)
+        ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
+      break;
+    }
+
+out:
+  return;
+}
+
+static void
+ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state)
+{
+  /* So far, nothing to do here. */
+  return;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are OSPF protocol processing functions for MPLS-TE.
+ *------------------------------------------------------------------------*/
+
+static void
+build_tlv_header (struct stream *s, struct te_tlv_header *tlvh)
+{
+  stream_put (s, tlvh, sizeof (struct te_tlv_header));
+  return;
+}
+
+static void
+build_router_tlv (struct stream *s)
+{
+  struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_link_type (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = &lp->link_type.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = &lp->link_id.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_lclif_ipaddr (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->lclif_ipaddr;
+  if (tlvh != NULL && ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_rmtif_ipaddr (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr;
+  if (tlvh != NULL && ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_te_metric (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = &lp->te_metric.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_max_bw (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = &lp->max_bw.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_max_rsv_bw (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = &lp->max_rsv_bw.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_unrsv_bw (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = &lp->unrsv_bw.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_subtlv_rsc_clsclr (struct stream *s, struct mpls_te_link *lp)
+{
+  struct te_tlv_header *tlvh = &lp->rsc_clsclr.header;
+  if (ntohs (tlvh->type) != 0)
+    {
+      build_tlv_header (s, tlvh);
+      stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
+    }
+  return;
+}
+
+static void
+build_link_tlv (struct stream *s, struct mpls_te_link *lp)
+{
+  set_linkparams_link_header (lp);
+  build_tlv_header (s, &lp->link_header.header);
+
+  build_link_subtlv_link_type (s, lp);
+  build_link_subtlv_link_id (s, lp);
+  build_link_subtlv_lclif_ipaddr (s, lp);
+  build_link_subtlv_rmtif_ipaddr (s, lp);
+  build_link_subtlv_te_metric (s, lp);
+  build_link_subtlv_max_bw (s, lp);
+  build_link_subtlv_max_rsv_bw (s, lp);
+  build_link_subtlv_unrsv_bw (s, lp);
+  build_link_subtlv_rsc_clsclr (s, lp);
+  return;
+}
+
+static void
+ospf_mpls_te_lsa_body_set (struct stream *s, struct mpls_te_link *lp)
+{
+  /*
+   * The router address TLV is type 1, and ...
+   *                                      It must appear in exactly one
+   * Traffic Engineering LSA originated by a router.
+   */
+  build_router_tlv (s);
+
+  /*
+   * Only one Link TLV shall be carried in each LSA, allowing for fine
+   * granularity changes in topology.
+   */
+  build_link_tlv (s, lp);
+  return;
+}
+
+/* Create new opaque-LSA. */
+static struct ospf_lsa *
+ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp)
+{
+  struct stream *s;
+  struct lsa_header *lsah;
+  struct ospf_lsa *new = NULL;
+  u_char options, lsa_type;
+  struct in_addr lsa_id;
+  u_int32_t tmp;
+  u_int16_t length;
+
+  /* Create a stream for LSA. */
+  if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
+      goto out;
+    }
+  lsah = (struct lsa_header *) STREAM_DATA (s);
+
+  options  = LSA_OPTIONS_GET (area);
+#ifdef HAVE_NSSA
+  options |= LSA_NSSA_GET (area);
+#endif /* HAVE_NSSA */
+  options |= OSPF_OPTION_O; /* Don't forget this :-) */
+
+  lsa_type = OSPF_OPAQUE_AREA_LSA;
+  tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
+  lsa_id.s_addr = htonl (tmp);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    zlog_info ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id));
+
+  /* Set opaque-LSA header fields. */
+  lsa_header_set (s, options, lsa_type, lsa_id);
+
+  /* Set opaque-LSA body fields. */
+  ospf_mpls_te_lsa_body_set (s, lp);
+
+  /* Set length. */
+  length = stream_get_endp (s);
+  lsah->length = htons (length);
+
+  /* Now, create an OSPF LSA instance. */
+  if ((new = ospf_lsa_new ()) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
+      stream_free (s);
+      goto out;
+    }
+  if ((new->data = ospf_lsa_data_new (length)) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
+      ospf_lsa_free (new);
+      new = NULL;
+      stream_free (s);
+      goto out;
+    }
+
+  new->area = area;
+  SET_FLAG (new->flags, OSPF_LSA_SELF);
+  memcpy (new->data, lsah, length);
+  stream_free (s);
+
+out:
+  return new;
+}
+
+static int
+ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp)
+{
+  struct ospf_lsa *new;
+  int rc = -1;
+
+  /* Create new Opaque-LSA/MPLS-TE instance. */
+  if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
+      goto out;
+    }
+
+  /* Install this LSA into LSDB. */
+  if (ospf_lsa_install (NULL/*oi*/, new) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
+      ospf_lsa_free (new);
+      goto out;
+    }
+
+  /* Now this linkparameter entry has associated LSA. */
+  lp->flags |= LPFLG_LSA_ENGAGED;
+
+  /* Update new LSA origination count. */
+  area->top->lsa_originate_count++;
+
+  /* Flood new LSA through area. */
+  ospf_flood_through_area (area, NULL/*nbr*/, new);
+
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      char area_id[INET_ADDRSTRLEN];
+      strcpy (area_id, inet_ntoa (area->area_id));
+      zlog_info ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name);
+      ospf_lsa_header_dump (new->data);
+    }
+
+  rc = 0;
+out:
+  return rc;
+}
+
+static int
+ospf_mpls_te_lsa_originate (void *arg)
+{
+  struct ospf_area *area = (struct ospf_area *) arg;
+  listnode node;
+  struct mpls_te_link *lp;
+  int rc = -1;
+
+  if (OspfMplsTE.status == disabled)
+    {
+      zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
+      rc = 0; /* This is not an error case. */
+      goto out;
+    }
+
+  for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+    {
+      if ((lp = getdata (node)) == NULL)
+        continue;
+      if (lp->area == NULL)
+        continue;
+      if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
+        continue;
+
+      if (lp->flags & LPFLG_LSA_ENGAGED)
+        {
+          if (lp->flags & LPFLG_LSA_FORCED_REFRESH)
+            {
+              lp->flags &= ~LPFLG_LSA_FORCED_REFRESH;
+              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            }
+          continue;
+        }
+      if (! is_mandated_params_set (lp))
+        {
+          zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp->ifp ? lp->ifp->name : "?");
+          continue;
+        }
+
+      /* Ok, let's try to originate an LSA for this area and Link. */
+      if (ospf_mpls_te_lsa_originate1 (area, lp) != 0)
+        goto out;
+    }
+
+  rc = 0;
+out:
+  return rc;
+}
+
+static void
+ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
+{
+  struct mpls_te_link *lp;
+  struct ospf_area *area = lsa->area;
+  struct ospf_lsa *new = NULL;
+
+  if (OspfMplsTE.status == disabled)
+    {
+      /*
+       * This LSA must have flushed before due to MPLS-TE status change.
+       * It seems a slip among routers in the routing domain.
+       */
+      zlog_info ("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
+      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
+    }
+
+  /* At first, resolve lsa/lp relationship. */
+  if ((lp = lookup_linkparams_by_instance (lsa)) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?");
+      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
+    }
+
+  /* If the lsa's age reached to MaxAge, start flushing procedure. */
+  if (IS_LSA_MAXAGE (lsa))
+    {
+      lp->flags &= ~LPFLG_LSA_ENGAGED;
+      ospf_opaque_lsa_flush_schedule (lsa);
+      goto out;
+    }
+
+  /* Create new Opaque-LSA/MPLS-TE instance. */
+  if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
+      goto out;
+    }
+  new->data->ls_seqnum = lsa_seqnum_increment (lsa);
+
+  /* Install this LSA into LSDB. */
+  /* Given "lsa" will be freed in the next function. */
+  if (ospf_lsa_install (NULL/*oi*/, new) == NULL)
+    {
+      zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
+      ospf_lsa_free (new);
+      goto out;
+    }
+
+  /* Flood updated LSA through area. */
+  ospf_flood_through_area (area, NULL/*nbr*/, new);
+
+  /* Debug logging. */
+  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+    {
+      zlog_info ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
+		 new->data->type, inet_ntoa (new->data->id));
+      ospf_lsa_header_dump (new->data);
+    }
+
+out:
+  return;
+}
+
+static void
+ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp,
+                           enum sched_opcode opcode)
+{
+  struct ospf_lsa lsa;
+  struct lsa_header lsah;
+  u_int32_t tmp;
+
+  memset (&lsa, 0, sizeof (lsa));
+  memset (&lsah, 0, sizeof (lsah));
+
+  lsa.area = lp->area;
+  lsa.data = &lsah;
+  lsah.type = OSPF_OPAQUE_AREA_LSA;
+  tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
+  lsah.id.s_addr = htonl (tmp);
+
+  switch (opcode)
+    {
+    case REORIGINATE_PER_AREA:
+      ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area,
+          OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
+      break;
+    case REFRESH_THIS_LSA:
+      ospf_opaque_lsa_refresh_schedule (&lsa);
+      break;
+    case FLUSH_THIS_LSA:
+      lp->flags &= ~LPFLG_LSA_ENGAGED;
+      ospf_opaque_lsa_flush_schedule (&lsa);
+      break;
+    default:
+      zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode);
+      break;
+    }
+
+  return;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are vty session control functions.
+ *------------------------------------------------------------------------*/
+
+static u_int16_t
+show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh;
+
+  if (vty != NULL)
+    vty_out (vty, "  Router-Address: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
+  else
+    zlog_info ("    Router-Address: %s", inet_ntoa (top->value));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_tlv_link *top = (struct te_tlv_link *) tlvh;
+
+  if (vty != NULL)
+    vty_out (vty, "  Link: %u octets of data%s", ntohs (top->header.length), VTY_NEWLINE);
+  else
+    zlog_info ("    Link: %u octets of data", ntohs (top->header.length));
+
+  return TLV_HDR_SIZE;	/* Here is special, not "TLV_SIZE". */
+}
+
+static u_int16_t
+show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_link_type *top;
+  const char *cp = "Unknown";
+
+  top = (struct te_link_subtlv_link_type *) tlvh;
+  switch (top->link_type.value)
+    {
+    case LINK_TYPE_SUBTLV_VALUE_PTP:
+      cp = "Point-to-point";
+      break;
+    case LINK_TYPE_SUBTLV_VALUE_MA:
+      cp = "Multiaccess";
+      break;
+    default:
+      break;
+    }
+
+  if (vty != NULL)
+    vty_out (vty, "  Link-Type: %s (%u)%s", cp, top->link_type.value, VTY_NEWLINE);
+  else
+    zlog_info ("    Link-Type: %s (%u)", cp, top->link_type.value);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_link_id *top;
+
+  top = (struct te_link_subtlv_link_id *) tlvh;
+  if (vty != NULL)
+    vty_out (vty, "  Link-ID: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
+  else
+    zlog_info ("    Link-ID: %s", inet_ntoa (top->value));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_lclif_ipaddr *top;
+  int i, n;
+
+  top = (struct te_link_subtlv_lclif_ipaddr *) tlvh;
+  n = ntohs (tlvh->length) / sizeof (top->value[0]);
+
+  if (vty != NULL)
+    vty_out (vty, "  Local Interface IP Address(es): %d%s", n, VTY_NEWLINE);
+  else
+    zlog_info ("    Local Interface IP Address(es): %d", n);
+
+  for (i = 0; i < n; i++)
+    {
+      if (vty != NULL)
+        vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
+      else
+        zlog_info ("      #%d: %s", i, inet_ntoa (top->value[i]));
+    }
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_rmtif_ipaddr *top;
+  int i, n;
+
+  top = (struct te_link_subtlv_rmtif_ipaddr *) tlvh;
+  n = ntohs (tlvh->length) / sizeof (top->value[0]);
+  if (vty != NULL)
+    vty_out (vty, "  Remote Interface IP Address(es): %d%s", n, VTY_NEWLINE);
+  else
+    zlog_info ("    Remote Interface IP Address(es): %d", n);
+
+  for (i = 0; i < n; i++)
+    {
+      if (vty != NULL)
+        vty_out (vty, "    #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
+      else
+        zlog_info ("      #%d: %s", i, inet_ntoa (top->value[i]));
+    }
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_te_metric *top;
+
+  top = (struct te_link_subtlv_te_metric *) tlvh;
+  if (vty != NULL)
+    vty_out (vty, "  Traffic Engineering Metric: %u%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
+  else
+    zlog_info ("    Traffic Engineering Metric: %u", (u_int32_t) ntohl (top->value));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_max_bw *top;
+  float fval;
+
+  top = (struct te_link_subtlv_max_bw *) tlvh;
+  ntohf (&top->value, &fval);
+
+  if (vty != NULL)
+    vty_out (vty, "  Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
+  else
+    zlog_info ("    Maximum Bandwidth: %g (Bytes/sec)", fval);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_max_rsv_bw *top;
+  float fval;
+
+  top = (struct te_link_subtlv_max_rsv_bw *) tlvh;
+  ntohf (&top->value, &fval);
+
+  if (vty != NULL)
+    vty_out (vty, "  Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
+  else
+    zlog_info ("    Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_unrsv_bw *top;
+  float fval;
+  int i;
+
+  top = (struct te_link_subtlv_unrsv_bw *) tlvh;
+  for (i = 0; i < 8; i++)
+    {
+      ntohf (&top->value[i], &fval);
+      if (vty != NULL)
+        vty_out (vty, "  Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i, fval, VTY_NEWLINE);
+      else
+        zlog_info ("    Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i, fval);
+    }
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  struct te_link_subtlv_rsc_clsclr *top;
+
+  top = (struct te_link_subtlv_rsc_clsclr *) tlvh;
+  if (vty != NULL)
+    vty_out (vty, "  Resource class/color: 0x%x%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
+  else
+    zlog_info ("    Resource Class/Color: 0x%x", (u_int32_t) ntohl (top->value));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh)
+{
+  if (vty != NULL)
+    vty_out (vty, "  Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
+  else
+    zlog_info ("    Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh->type), ntohs (tlvh->length));
+
+  return TLV_SIZE (tlvh);
+}
+
+static u_int16_t
+ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0,
+                               u_int16_t subtotal, u_int16_t total)
+{
+  struct te_tlv_header *tlvh, *next;
+  u_int16_t sum = subtotal;
+
+  for (tlvh = tlvh0; sum < total; tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
+    {
+      next = NULL;
+      switch (ntohs (tlvh->type))
+        {
+        case TE_LINK_SUBTLV_LINK_TYPE:
+          sum += show_vty_link_subtlv_link_type (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_LINK_ID:
+          sum += show_vty_link_subtlv_link_id (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_LCLIF_IPADDR:
+          sum += show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_RMTIF_IPADDR:
+          sum += show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_TE_METRIC:
+          sum += show_vty_link_subtlv_te_metric (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_MAX_BW:
+          sum += show_vty_link_subtlv_max_bw (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_MAX_RSV_BW:
+          sum += show_vty_link_subtlv_max_rsv_bw (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_UNRSV_BW:
+          sum += show_vty_link_subtlv_unrsv_bw (vty, tlvh);
+          break;
+        case TE_LINK_SUBTLV_RSC_CLSCLR:
+          sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh);
+          break;
+        default:
+          sum += show_vty_unknown_tlv (vty, tlvh);
+          break;
+        }
+    }
+  return sum;
+}
+
+static void
+ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa)
+{
+  struct lsa_header *lsah = (struct lsa_header *) lsa->data;
+  struct te_tlv_header *tlvh, *next;
+  u_int16_t sum, total;
+  u_int16_t (* subfunc)(struct vty *vty, struct te_tlv_header *tlvh,
+                        u_int16_t subtotal, u_int16_t total) = NULL;
+
+  sum = 0;
+  total = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
+
+  for (tlvh = TLV_HDR_TOP (lsah); sum < total;
+			tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
+    {
+      if (subfunc != NULL)
+        {
+          sum = (* subfunc)(vty, tlvh, sum, total);
+	  next = (struct te_tlv_header *)((char *) tlvh + sum);
+          subfunc = NULL;
+          continue;
+        }
+
+      next = NULL;
+      switch (ntohs (tlvh->type))
+        {
+        case TE_TLV_ROUTER_ADDR:
+          sum += show_vty_router_addr (vty, tlvh);
+          break;
+        case TE_TLV_LINK:
+          sum += show_vty_link_header (vty, tlvh);
+	  subfunc = ospf_mpls_te_show_link_subtlv;
+	  next = tlvh + 1;
+          break;
+        default:
+          sum += show_vty_unknown_tlv (vty, tlvh);
+          break;
+        }
+    }
+  return;
+}
+
+static void
+ospf_mpls_te_config_write_router (struct vty *vty)
+{
+  if (OspfMplsTE.status == enabled)
+    {
+      vty_out (vty, "  mpls-te%s", VTY_NEWLINE);
+      vty_out (vty, "  mpls-te router-address %s%s",
+               inet_ntoa (OspfMplsTE.router_addr.value), VTY_NEWLINE);
+    }
+  return;
+}
+
+static void
+ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp)
+{
+  struct mpls_te_link *lp;
+
+  if ((OspfMplsTE.status == enabled)
+  &&  (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
+  &&  ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
+    {
+      float fval;
+      int i;
+
+      vty_out (vty, " mpls-te link metric %u%s",
+               (u_int32_t) ntohl (lp->te_metric.value), VTY_NEWLINE);
+
+      ntohf (&lp->max_bw.value, &fval);
+      if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
+        vty_out (vty, " mpls-te link max-bw %g%s", fval, VTY_NEWLINE);
+
+      ntohf (&lp->max_rsv_bw.value, &fval);
+      if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
+        vty_out (vty, " mpls-te link max-rsv-bw %g%s", fval, VTY_NEWLINE);
+
+      for (i = 0; i < 8; i++)
+        {
+          ntohf (&lp->unrsv_bw.value[i], &fval);
+          if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
+            vty_out (vty, " mpls-te link unrsv-bw %d %g%s",
+                     i, fval, VTY_NEWLINE);
+        }
+
+      vty_out (vty, " mpls-te link rsc-clsclr 0x%x%s",
+               (u_int32_t) ntohl (lp->rsc_clsclr.value), VTY_NEWLINE);
+    }
+  return;
+}
+
+/*------------------------------------------------------------------------*
+ * Followings are vty command functions.
+ *------------------------------------------------------------------------*/
+
+DEFUN (mpls_te,
+       mpls_te_cmd,
+       "mpls-te",
+       "Configure MPLS-TE parameters\n"
+       "Enable the MPLS-TE functionality\n")
+{
+  listnode node;
+  struct mpls_te_link *lp;
+
+  if (OspfMplsTE.status == enabled)
+    return CMD_SUCCESS;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("MPLS-TE: OFF -> ON");
+
+  OspfMplsTE.status = enabled;
+
+  /*
+   * Following code is intended to handle two cases;
+   *
+   * 1) MPLS-TE was disabled at startup time, but now become enabled.
+   * 2) MPLS-TE was once enabled then disabled, and now enabled again.
+   */
+  for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+    if ((lp = getdata (node)) != NULL)
+      initialize_linkparams (lp);
+
+  ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (mpls_te,
+       mpls_te_on_cmd,
+       "mpls-te on",
+       "Configure MPLS-TE parameters\n"
+       "Enable the MPLS-TE functionality\n")
+
+DEFUN (no_mpls_te,
+       no_mpls_te_cmd,
+       "no mpls-te",
+       NO_STR
+       "Configure MPLS-TE parameters\n"
+       "Disable the MPLS-TE functionality\n")
+{
+  listnode node;
+  struct mpls_te_link *lp;
+
+  if (OspfMplsTE.status == disabled)
+    return CMD_SUCCESS;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("MPLS-TE: ON -> OFF");
+
+  OspfMplsTE.status = disabled;
+
+  for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+    if ((lp = getdata (node)) != NULL)
+      if (lp->area != NULL)
+        if (lp->flags & LPFLG_LSA_ENGAGED)
+          ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (mpls_te_router_addr,
+       mpls_te_router_addr_cmd,
+       "mpls-te router-address A.B.C.D",
+       "MPLS-TE specific commands\n"
+       "Stable IP address of the advertising router\n"
+       "MPLS-TE router address in IPv4 address format\n")
+{
+  struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
+  struct in_addr value;
+
+  if (! inet_aton (argv[0], &value))
+    {
+      vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (ntohs (ra->header.type) == 0
+  ||  ntohl (ra->value.s_addr) != ntohl (value.s_addr))
+    {
+      listnode node;
+      struct mpls_te_link *lp;
+      int need_to_reoriginate = 0;
+
+      set_mpls_te_router_addr (value);
+
+      if (OspfMplsTE.status == disabled)
+        goto out;
+
+      for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+        {
+          if ((lp = getdata (node)) == NULL)
+            continue;
+          if (lp->area == NULL)
+            continue;
+
+          if ((lp->flags & LPFLG_LSA_ENGAGED) == 0)
+            {
+              need_to_reoriginate = 1;
+              break;
+            }
+        }
+      for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
+        {
+          if ((lp = getdata (node)) == NULL)
+            continue;
+          if (lp->area == NULL)
+            continue;
+
+          if (need_to_reoriginate)
+            lp->flags |= LPFLG_LSA_FORCED_REFRESH;
+          else
+            ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+        }
+
+      if (need_to_reoriginate)
+        ospf_mpls_te_foreach_area (
+            ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
+    }
+out:
+  return CMD_SUCCESS;
+}
+
+DEFUN (mpls_te_link_metric,
+       mpls_te_link_metric_cmd,
+       "mpls-te link metric <0-4294967295>",
+       "MPLS-TE specific commands\n"
+       "Configure MPLS-TE link parameters\n"
+       "Link metric for MPLS-TE purpose\n"
+       "Metric\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct mpls_te_link *lp;
+  u_int32_t value;
+
+  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
+    {
+      vty_out (vty, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  value = strtoul (argv[0], NULL, 10);
+
+  if (ntohs (lp->te_metric.header.type) == 0
+  ||  ntohl (lp->te_metric.value) != value)
+    {
+      set_linkparams_te_metric (lp, value);
+
+      if (OspfMplsTE.status == enabled)
+        if (lp->area != NULL)
+          {
+            if (lp->flags & LPFLG_LSA_ENGAGED)
+              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            else
+              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
+          }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (mpls_te_link_maxbw,
+       mpls_te_link_maxbw_cmd,
+       "mpls-te link max-bw BANDWIDTH",
+       "MPLS-TE specific commands\n"
+       "Configure MPLS-TE link parameters\n"
+       "Maximum bandwidth that can be used\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct mpls_te_link *lp;
+  float f1, f2;
+
+  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
+    {
+      vty_out (vty, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ntohf (&lp->max_bw.value, &f1);
+  if (sscanf (argv[0], "%g", &f2) != 1)
+    {
+      vty_out (vty, "mpls_te_link_maxbw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (ntohs (lp->max_bw.header.type) == 0
+  ||  f1 != f2)
+    {
+      set_linkparams_max_bw (lp, &f2);
+
+      if (OspfMplsTE.status == enabled)
+        if (lp->area != NULL)
+          {
+            if (lp->flags & LPFLG_LSA_ENGAGED)
+              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            else
+              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
+          }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (mpls_te_link_max_rsv_bw,
+       mpls_te_link_max_rsv_bw_cmd,
+       "mpls-te link max-rsv-bw BANDWIDTH",
+       "MPLS-TE specific commands\n"
+       "Configure MPLS-TE link parameters\n"
+       "Maximum bandwidth that may be reserved\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct mpls_te_link *lp;
+  float f1, f2;
+
+  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
+    {
+      vty_out (vty, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ntohf (&lp->max_rsv_bw.value, &f1);
+  if (sscanf (argv[0], "%g", &f2) != 1)
+    {
+      vty_out (vty, "mpls_te_link_max_rsv_bw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (ntohs (lp->max_rsv_bw.header.type) == 0
+  ||  f1 != f2)
+    {
+      set_linkparams_max_rsv_bw (lp, &f2);
+
+      if (OspfMplsTE.status == enabled)
+        if (lp->area != NULL)
+          {
+            if (lp->flags & LPFLG_LSA_ENGAGED)
+              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            else
+              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
+          }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (mpls_te_link_unrsv_bw,
+       mpls_te_link_unrsv_bw_cmd,
+       "mpls-te link unrsv-bw <0-7> BANDWIDTH",
+       "MPLS-TE specific commands\n"
+       "Configure MPLS-TE link parameters\n"
+       "Unreserved bandwidth at each priority level\n"
+       "Priority\n"
+       "Bytes/second (IEEE floating point format)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct mpls_te_link *lp;
+  int priority;
+  float f1, f2;
+
+  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
+    {
+      vty_out (vty, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* We don't have to consider about range check here. */
+  if (sscanf (argv[0], "%d", &priority) != 1)
+    {
+      vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ntohf (&lp->unrsv_bw.value [priority], &f1);
+  if (sscanf (argv[1], "%g", &f2) != 1)
+    {
+      vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (ntohs (lp->unrsv_bw.header.type) == 0
+  ||  f1 != f2)
+    {
+      set_linkparams_unrsv_bw (lp, priority, &f2);
+
+      if (OspfMplsTE.status == enabled)
+        if (lp->area != NULL)
+          {
+            if (lp->flags & LPFLG_LSA_ENGAGED)
+              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            else
+              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
+          }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (mpls_te_link_rsc_clsclr,
+       mpls_te_link_rsc_clsclr_cmd,
+       "mpls-te link rsc-clsclr BITPATTERN",
+       "MPLS-TE specific commands\n"
+       "Configure MPLS-TE link parameters\n"
+       "Administrative group membership\n"
+       "32-bit Hexadecimal value (ex. 0xa1)\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  struct mpls_te_link *lp;
+  unsigned long value;
+
+  if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
+    {
+      vty_out (vty, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (sscanf (argv[0], "0x%lx", &value) != 1)
+    {
+      vty_out (vty, "mpls_te_link_rsc_clsclr: fscanf: %s%s", strerror (errno), VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (ntohs (lp->rsc_clsclr.header.type) == 0
+  ||  ntohl (lp->rsc_clsclr.value) != value)
+    {
+      set_linkparams_rsc_clsclr (lp, value);
+
+      if (OspfMplsTE.status == enabled)
+        if (lp->area != NULL)
+          {
+            if (lp->flags & LPFLG_LSA_ENGAGED)
+              ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
+            else
+              ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
+          }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_mpls_te_router,
+       show_mpls_te_router_cmd,
+       "show mpls-te router",
+       SHOW_STR
+       "MPLS-TE information\n"
+       "Router information\n")
+{
+  if (OspfMplsTE.status == enabled)
+    {
+      vty_out (vty, "--- MPLS-TE router parameters ---%s",
+               VTY_NEWLINE);
+
+      if (ntohs (OspfMplsTE.router_addr.header.type) != 0)
+        show_vty_router_addr (vty, &OspfMplsTE.router_addr.header);
+      else if (vty != NULL)
+        vty_out (vty, "  N/A%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+static void
+show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
+{
+  struct mpls_te_link *lp;
+  struct te_tlv_header *tlvh;
+
+  if ((OspfMplsTE.status == enabled)
+  &&  (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
+  &&  ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
+    {
+      vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
+               ifp->name, VTY_NEWLINE);
+
+      show_vty_link_subtlv_link_type (vty, &lp->link_type.header);
+      show_vty_link_subtlv_link_id (vty, &lp->link_id.header);
+
+      if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL)
+        show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
+      if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL)
+        show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
+
+      show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header);
+
+      show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header);
+      show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header);
+      show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header);
+      show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header);
+    }
+  else
+    {
+      vty_out (vty, "  %s: MPLS-TE is disabled on this interface%s",
+               ifp->name, VTY_NEWLINE);
+    }
+
+  return;
+}
+
+DEFUN (show_mpls_te_link,
+       show_mpls_te_link_cmd,
+       "show mpls-te interface [INTERFACE]",
+       SHOW_STR
+       "MPLS-TE information\n"
+       "Interface information\n"
+       "Interface name\n")
+{
+  struct interface *ifp;
+  listnode node;
+
+  /* Show All Interfaces. */
+  if (argc == 0)
+    for (node = listhead (iflist); node; nextnode (node))
+      show_mpls_te_link_sub (vty, node->data);
+  /* Interface name is specified. */
+  else
+    {
+      if ((ifp = if_lookup_by_name (argv[0])) == NULL)
+        vty_out (vty, "No such interface name%s", VTY_NEWLINE);
+      else
+        show_mpls_te_link_sub (vty, ifp);
+    }
+
+  return CMD_SUCCESS;
+}
+
+static void
+ospf_mpls_te_register_vty (void)
+{
+  install_element (VIEW_NODE, &show_mpls_te_router_cmd);
+  install_element (VIEW_NODE, &show_mpls_te_link_cmd);
+  install_element (ENABLE_NODE, &show_mpls_te_router_cmd);
+  install_element (ENABLE_NODE, &show_mpls_te_link_cmd);
+
+  install_element (OSPF_NODE, &mpls_te_cmd);
+  install_element (OSPF_NODE, &no_mpls_te_cmd);
+  install_element (OSPF_NODE, &mpls_te_on_cmd);
+  install_element (OSPF_NODE, &mpls_te_router_addr_cmd);
+
+  install_element (INTERFACE_NODE, &mpls_te_link_metric_cmd);
+  install_element (INTERFACE_NODE, &mpls_te_link_maxbw_cmd);
+  install_element (INTERFACE_NODE, &mpls_te_link_max_rsv_bw_cmd);
+  install_element (INTERFACE_NODE, &mpls_te_link_unrsv_bw_cmd);
+  install_element (INTERFACE_NODE, &mpls_te_link_rsc_clsclr_cmd);
+
+  return;
+}
+
+#endif /* HAVE_OSPF_TE */
diff --git a/ospfd/ospf_te.h b/ospfd/ospf_te.h
new file mode 100644
index 0000000..8a7a98c
--- /dev/null
+++ b/ospfd/ospf_te.h
@@ -0,0 +1,193 @@
+/*
+ * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt
+ * Copyright (C) 2001 KDD R&D Laboratories, Inc.
+ * http://www.kddlabs.co.jp/
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_MPLS_TE_H
+#define _ZEBRA_OSPF_MPLS_TE_H
+
+/*
+ * Opaque LSA's link state ID for Traffic Engineering is
+ * structured as follows.
+ *
+ *        24       16        8        0
+ * +--------+--------+--------+--------+
+ * |    1   |  MBZ   |........|........|
+ * +--------+--------+--------+--------+
+ * |<-Type->|<Resv'd>|<-- Instance --->|
+ *
+ *
+ * Type:      IANA has assigned '1' for Traffic Engineering.
+ * MBZ:       Reserved, must be set to zero.
+ * Instance:  User may select an arbitrary 16-bit value.
+ *
+ */
+
+#define	LEGAL_TE_INSTANCE_RANGE(i)	(0 <= (i) && (i) <= 0xffff)
+
+/*
+ *        24       16        8        0
+ * +--------+--------+--------+--------+ ---
+ * |   LS age        |Options |   10   |  A
+ * +--------+--------+--------+--------+  |
+ * |    1   |   0    |    Instance     |  |
+ * +--------+--------+--------+--------+  |
+ * |        Advertising router         |  |  Standard (Opaque) LSA header;
+ * +--------+--------+--------+--------+  |  Only type-10 is used.
+ * |        LS sequence number         |  |
+ * +--------+--------+--------+--------+  |
+ * |   LS checksum   |     Length      |  V
+ * +--------+--------+--------+--------+ ---
+ * |      Type       |     Length      |  A
+ * +--------+--------+--------+--------+  |  TLV part for TE; Values might be
+ * |              Values ...           |  V  structured as a set of sub-TLVs.
+ * +--------+--------+--------+--------+ ---
+ */
+
+/*
+ * Following section defines TLV (tag, length, value) structures,
+ * used for Traffic Engineering.
+ */
+struct te_tlv_header
+{
+  u_int16_t	type;			/* TE_TLV_XXX (see below) */
+  u_int16_t	length;			/* Value portion only, in octets */
+};
+
+#define TLV_HDR_SIZE \
+	sizeof (struct te_tlv_header)
+
+#define TLV_BODY_SIZE(tlvh) \
+	ROUNDUP (ntohs ((tlvh)->length), sizeof (u_int32_t))
+
+#define TLV_SIZE(tlvh) \
+	(TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
+
+#define TLV_HDR_TOP(lsah) \
+	(struct te_tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE)
+
+#define TLV_HDR_NEXT(tlvh) \
+	(struct te_tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh))
+
+/*
+ * Following section defines TLV body parts.
+ */
+/* Router Address TLV *//* Mandatory */
+#define	TE_TLV_ROUTER_ADDR		1
+struct te_tlv_router_addr
+{
+  struct te_tlv_header	header;		/* Value length is 4 octets. */
+  struct in_addr	value;
+};
+
+/* Link TLV */
+#define	TE_TLV_LINK			2
+struct te_tlv_link
+{
+  struct te_tlv_header	header;
+  /* A set of link-sub-TLVs will follow. */
+};
+
+/* Link Type Sub-TLV *//* Mandatory */
+#define	TE_LINK_SUBTLV_LINK_TYPE		1
+struct te_link_subtlv_link_type
+{
+  struct te_tlv_header	header;		/* Value length is 1 octet. */
+  struct {
+#define	LINK_TYPE_SUBTLV_VALUE_PTP	1
+#define	LINK_TYPE_SUBTLV_VALUE_MA	2
+      u_char	value;
+      u_char	padding[3];
+  } link_type;
+};
+
+/* Link Sub-TLV: Link ID *//* Mandatory */
+#define	TE_LINK_SUBTLV_LINK_ID			2
+struct te_link_subtlv_link_id
+{
+  struct te_tlv_header	header;		/* Value length is 4 octets. */
+  struct in_addr	value;		/* Same as router-lsa's link-id. */
+};
+
+/* Link Sub-TLV: Local Interface IP Address *//* Optional */
+#define	TE_LINK_SUBTLV_LCLIF_IPADDR		3
+struct te_link_subtlv_lclif_ipaddr
+{
+  struct te_tlv_header	header;		/* Value length is 4 x N octets. */
+  struct in_addr	value[1];	/* Local IP address(es). */
+};
+
+/* Link Sub-TLV: Remote Interface IP Address *//* Optional */
+#define	TE_LINK_SUBTLV_RMTIF_IPADDR		4
+struct te_link_subtlv_rmtif_ipaddr
+{
+  struct te_tlv_header	header;		/* Value length is 4 x N octets. */
+  struct in_addr	value[1];	/* Neighbor's IP address(es). */
+};
+
+/* Link Sub-TLV: Traffic Engineering Metric *//* Optional */
+#define	TE_LINK_SUBTLV_TE_METRIC		5
+struct te_link_subtlv_te_metric
+{
+  struct te_tlv_header	header;		/* Value length is 4 octets. */
+  u_int32_t		value;		/* Link metric for TE purpose. */
+};
+
+/* Link Sub-TLV: Maximum Bandwidth *//* Optional */
+#define	TE_LINK_SUBTLV_MAX_BW			6
+struct te_link_subtlv_max_bw
+{
+  struct te_tlv_header	header;		/* Value length is 4 octets. */
+  float			value;		/* bytes/sec */
+};
+
+/* Link Sub-TLV: Maximum Reservable Bandwidth *//* Optional */
+#define	TE_LINK_SUBTLV_MAX_RSV_BW		7
+struct te_link_subtlv_max_rsv_bw
+{
+  struct te_tlv_header	header;		/* Value length is 4 octets. */
+  float			value;		/* bytes/sec */
+};
+
+/* Link Sub-TLV: Unreserved Bandwidth *//* Optional */
+#define	TE_LINK_SUBTLV_UNRSV_BW			8
+struct te_link_subtlv_unrsv_bw
+{
+  struct te_tlv_header	header;		/* Value length is 32 octets. */
+  float			value[8];	/* One for each priority level. */
+};
+
+/* Link Sub-TLV: Resource Class/Color *//* Optional */
+#define	TE_LINK_SUBTLV_RSC_CLSCLR		9
+struct te_link_subtlv_rsc_clsclr
+{
+  struct te_tlv_header	header;		/* Value length is 4 octets. */
+  u_int32_t		value;		/* Admin. group membership. */
+};
+
+/* Here are "non-official" architechtual constants. */
+#define MPLS_TE_MINIMUM_BANDWIDTH	1.0	/* Reasonable? *//* XXX */
+
+/* Prototypes. */
+extern int ospf_mpls_te_init (void);
+extern void ospf_mpls_te_term (void);
+
+#endif /* _ZEBRA_OSPF_MPLS_TE_H */
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
new file mode 100644
index 0000000..73215fa
--- /dev/null
+++ b/ospfd/ospf_vty.c
@@ -0,0 +1,7571 @@
+/* OSPF VTY interface.
+ * Copyright (C) 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include <zebra.h>
+
+#include "memory.h"
+#include "thread.h"
+#include "prefix.h"
+#include "table.h"
+#include "vty.h"
+#include "command.h"
+#include "plist.h"
+#include "log.h"
+#include "zclient.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_zebra.h"
+/*#include "ospfd/ospf_routemap.h" */
+#include "ospfd/ospf_vty.h"
+#include "ospfd/ospf_dump.h"
+
+
+static char *ospf_network_type_str[] =
+{
+  "Null",
+  "POINTOPOINT",
+  "BROADCAST",
+  "NBMA",
+  "POINTOMULTIPOINT",
+  "VIRTUALLINK",
+  "LOOPBACK"
+};
+
+
+/* Utility functions. */
+int
+ospf_str2area_id (char *str, struct in_addr *area_id, int *format)
+{
+  char *endptr = NULL;
+  unsigned long ret;
+
+  /* match "A.B.C.D". */
+  if (strchr (str, '.') != NULL)
+    {
+      ret = inet_aton (str, area_id);
+      if (!ret)
+        return -1;
+      *format = OSPF_AREA_ID_FORMAT_ADDRESS;
+    }
+  /* match "<0-4294967295>". */
+  else
+    {
+      ret = strtoul (str, &endptr, 10);
+      if (*endptr != '\0' || (ret == ULONG_MAX && errno == ERANGE))
+        return -1;
+
+      area_id->s_addr = htonl (ret);
+      *format = OSPF_AREA_ID_FORMAT_DECIMAL;
+    }
+
+  return 0;
+}
+
+
+int
+str2distribute_source (char *str, int *source)
+{
+  /* Sanity check. */
+  if (str == NULL)
+    return 0;
+
+  if (strncmp (str, "k", 1) == 0)
+    *source = ZEBRA_ROUTE_KERNEL;
+  else if (strncmp (str, "c", 1) == 0)
+    *source = ZEBRA_ROUTE_CONNECT;
+  else if (strncmp (str, "s", 1) == 0)
+    *source = ZEBRA_ROUTE_STATIC;
+  else if (strncmp (str, "r", 1) == 0)
+    *source = ZEBRA_ROUTE_RIP;
+  else if (strncmp (str, "b", 1) == 0)
+    *source = ZEBRA_ROUTE_BGP;
+  else
+    return 0;
+
+  return 1;
+}
+
+int
+str2metric (char *str, int *metric)
+{
+  /* Sanity check. */
+  if (str == NULL)
+    return 0;
+
+  *metric = strtol (str, NULL, 10);
+  if (*metric < 0 && *metric > 16777214)
+    {
+      /* vty_out (vty, "OSPF metric value is invalid%s", VTY_NEWLINE); */
+      return 0;
+    }
+
+  return 1;
+}
+
+int
+str2metric_type (char *str, int *metric_type)
+{
+  /* Sanity check. */
+  if (str == NULL)
+    return 0;
+
+  if (strncmp (str, "1", 1) == 0)
+    *metric_type = EXTERNAL_METRIC_TYPE_1;
+  else if (strncmp (str, "2", 1) == 0)
+    *metric_type = EXTERNAL_METRIC_TYPE_2;
+  else
+    return 0;
+
+  return 1;
+}
+
+int
+ospf_oi_count (struct interface *ifp)
+{
+  struct route_node *rn;
+  int i = 0;
+
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    if (rn->info)
+      i++;
+
+  return i;
+}
+
+
+DEFUN (router_ospf,
+       router_ospf_cmd,
+       "router ospf",
+       "Enable a routing process\n"
+       "Start OSPF configuration\n")
+{
+  vty->node = OSPF_NODE;
+  vty->index = ospf_get ();
+ 
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_router_ospf,
+       no_router_ospf_cmd,
+       "no router ospf",
+       NO_STR
+       "Enable a routing process\n"
+       "Start OSPF configuration\n")
+{
+  if (ospf_top == NULL)
+    {
+      vty_out (vty, "There isn't active ospf instance.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ospf_finish (ospf_top);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_router_id,
+       ospf_router_id_cmd,
+       "ospf router-id A.B.C.D",
+       "OSPF specific commands\n"
+       "router-id for the OSPF process\n"
+       "OSPF router-id in IP address format\n")
+{
+  int ret;
+  struct in_addr router_id;
+
+  ret = inet_aton (argv[0], &router_id);
+  if (!ret)
+    {
+      vty_out (vty, "Please specify Router ID by A.B.C.D%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* ospf_top->router_id = router_id; */
+  ospf_top->router_id_static = router_id;
+
+  if (ospf_top->t_router_id_update == NULL)
+    ospf_top->t_router_id_update =
+      thread_add_timer (master, ospf_router_id_update_timer, NULL,
+			OSPF_ROUTER_ID_UPDATE_DELAY);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ospf_router_id,
+       router_id_cmd,
+       "router-id A.B.C.D",
+       "router-id for the OSPF process\n"
+       "OSPF router-id in IP address format\n")
+
+DEFUN (no_ospf_router_id,
+       no_ospf_router_id_cmd,
+       "no ospf router-id",
+       NO_STR
+       "OSPF specific commands\n"
+       "router-id for the OSPF process\n")
+{
+  ospf_top->router_id_static.s_addr = 0;
+
+  ospf_router_id_update ();
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_ospf_router_id,
+       no_router_id_cmd,
+       "no router-id",
+       NO_STR
+       "router-id for the OSPF process\n")
+
+DEFUN (passive_interface,
+       passive_interface_addr_cmd,
+       "passive-interface IFNAME A.B.C.D",
+       "Suppress routing updates on an interface\n"
+       "Interface's name\n")
+{
+ struct interface *ifp;
+ struct in_addr addr;
+ int ret;
+ struct ospf_if_params *params;
+
+ ifp = if_lookup_by_name (argv[0]);
+ 
+ if (ifp == NULL)
+   {
+     vty_out (vty, "Please specify an existing interface%s", VTY_NEWLINE);
+     return CMD_WARNING;
+   }
+
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+  SET_IF_PARAM (params, passive_interface);
+  params->passive_interface = OSPF_IF_PASSIVE;
+ 
+ return CMD_SUCCESS;
+}
+
+ALIAS (passive_interface,
+       passive_interface_cmd,
+       "passive-interface IFNAME",
+       "Suppress routing updates on an interface\n"
+       "Interface's name\n")
+
+DEFUN (no_passive_interface,
+       no_passive_interface_addr_cmd,
+       "no passive-interface IFNAME A.B.C.D",
+       NO_STR
+       "Allow routing updates on an interface\n"
+       "Interface's name\n")
+{
+  struct interface *ifp;
+  struct in_addr addr;
+  struct ospf_if_params *params;
+  int ret;
+    
+  ifp = if_lookup_by_name (argv[0]);
+  
+  if (ifp == NULL)
+    {
+      vty_out (vty, "Please specify an existing interface%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &addr);
+      if (!ret)
+	{
+	  vty_out (vty, "Please specify interface address by A.B.C.D%s",
+		   VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+
+      params = ospf_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  UNSET_IF_PARAM (params, passive_interface);
+  params->passive_interface = OSPF_IF_ACTIVE;
+  
+  if (params != IF_DEF_PARAMS (ifp))
+    {
+      ospf_free_if_params (ifp, addr);
+      ospf_if_update_params (ifp, addr);
+    }
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_passive_interface,
+       no_passive_interface_cmd,
+       "no passive-interface IFNAME",
+       NO_STR
+       "Allow routing updates on an interface\n"
+       "Interface's name\n")
+
+DEFUN (network_area,
+       network_area_cmd,
+       "network A.B.C.D/M area (A.B.C.D|<0-4294967295>)",
+       "Enable routing on an IP network\n"
+       "OSPF network prefix\n"
+       "Set the OSPF area ID\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n")
+{
+  struct ospf *ospf= vty->index;
+  struct prefix_ipv4 p;
+  struct in_addr area_id;
+  int ret, format;
+
+  /* Get network prefix and Area ID. */
+  VTY_GET_IPV4_PREFIX ("network prefix", p, argv[0]);
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]);
+
+  ret = ospf_network_set (ospf, &p, area_id);
+  if (ret == 0)
+    {
+      vty_out (vty, "There is already same network statement.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_network_area,
+       no_network_area_cmd,
+       "no network A.B.C.D/M area (A.B.C.D|<0-4294967295>)",
+       NO_STR
+       "Enable routing on an IP network\n"
+       "OSPF network prefix\n"
+       "Set the OSPF area ID\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n")
+{
+  struct ospf *ospf = (struct ospf *) vty->index;
+  struct prefix_ipv4 p;
+  struct in_addr area_id;
+  int ret, format;
+
+  /* Get network prefix and Area ID. */
+  VTY_GET_IPV4_PREFIX ("network prefix", p, argv[0]);
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]);
+
+  ret = ospf_network_unset (ospf, &p, area_id);
+  if (ret == 0)
+    {
+      vty_out (vty, "Can't find specified network area configuration.%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (area_range,
+       area_range_cmd,
+       "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n")
+{
+  struct ospf *ospf = vty->index;
+  struct prefix_ipv4 p;
+  struct in_addr area_id;
+  int format;
+  u_int32_t cost;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+  VTY_GET_IPV4_PREFIX ("area range", p, argv[1]);
+
+  ospf_area_range_set (ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE);
+  if (argc > 2)
+    {
+      VTY_GET_UINT32 ("range cost", cost, argv[2]);
+      ospf_area_range_cost_set (ospf, area_id, &p, cost);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (area_range,
+       area_range_advertise_cmd,
+       "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M advertise",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "OSPF area range for route advertise (default)\n"
+       "Area range prefix\n"
+       "Advertise this range (default)\n")
+
+ALIAS (area_range,
+       area_range_cost_cmd,
+       "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M cost <0-16777215>",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "User specified metric for this range\n"
+       "Advertised metric for this range\n")
+
+ALIAS (area_range,
+       area_range_advertise_cost_cmd,
+       "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M advertise cost <0-16777215>",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "Advertise this range (default)\n"
+       "User specified metric for this range\n"
+       "Advertised metric for this range\n")
+
+DEFUN (area_range_not_advertise,
+       area_range_not_advertise_cmd,
+       "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M not-advertise",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "DoNotAdvertise this range\n")
+{
+  struct ospf *ospf = vty->index;
+  struct prefix_ipv4 p;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+  VTY_GET_IPV4_PREFIX ("area range", p, argv[1]);
+
+  ospf_area_range_set (ospf, area_id, &p, 0);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_range,
+       no_area_range_cmd,
+       "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n")
+{
+  struct ospf *ospf = vty->index;
+  struct prefix_ipv4 p;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+  VTY_GET_IPV4_PREFIX ("area range", p, argv[1]);
+
+  ospf_area_range_unset (ospf, area_id, &p);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_area_range,
+       no_area_range_advertise_cmd,
+       "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M (advertise|not-advertise)",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "Advertise this range (default)\n"
+       "DoNotAdvertise this range\n")
+
+ALIAS (no_area_range,
+       no_area_range_cost_cmd,
+       "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M cost <0-16777215>",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "User specified metric for this range\n"
+       "Advertised metric for this range\n")
+
+ALIAS (no_area_range,
+       no_area_range_advertise_cost_cmd,
+       "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M advertise cost <0-16777215>",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "Advertise this range (default)\n"
+       "User specified metric for this range\n"
+       "Advertised metric for this range\n")
+
+DEFUN (area_range_substitute,
+       area_range_substitute_cmd,
+       "area (A.B.C.D|<0-4294967295>) range A.B.C.D/M substitute A.B.C.D/M",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "Announce area range as another prefix\n"
+       "Network prefix to be announced instead of range\n")
+{
+  struct ospf *ospf = vty->index;
+  struct prefix_ipv4 p, s;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+  VTY_GET_IPV4_PREFIX ("area range", p, argv[1]);
+  VTY_GET_IPV4_PREFIX ("substituted network prefix", s, argv[2]);
+
+  ospf_area_range_substitute_set (ospf, area_id, &p, &s);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_range_substitute,
+       no_area_range_substitute_cmd,
+       "no area (A.B.C.D|<0-4294967295>) range A.B.C.D/M substitute A.B.C.D/M",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Summarize routes matching address/mask (border routers only)\n"
+       "Area range prefix\n"
+       "Announce area range as another prefix\n"
+       "Network prefix to be announced instead of range\n")
+{
+  struct ospf *ospf = vty->index;
+  struct prefix_ipv4 p, s;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+  VTY_GET_IPV4_PREFIX ("area range", p, argv[1]);
+  VTY_GET_IPV4_PREFIX ("substituted network prefix", s, argv[2]);
+
+  ospf_area_range_substitute_unset (ospf, area_id, &p);
+
+  return CMD_SUCCESS;
+}
+
+
+/* Command Handler Logic in VLink stuff is delicate!!
+
+	ALTER AT YOUR OWN RISK!!!!
+
+	Various dummy values are used to represent 'NoChange' state for
+	VLink configuration NOT being changed by a VLink command, and
+	special syntax is used within the command strings so that the
+	typed in command verbs can be seen in the configuration command
+	bacckend handler.  This is to drastically reduce the verbeage
+	required to coe up with a reasonably compatible Cisco VLink command
+
+	- Matthew Grant <grantma@anathoth.gen.nz> 
+	Wed, 21 Feb 2001 15:13:52 +1300
+ */
+
+
+/* Configuration data for virtual links 
+ */ 
+struct ospf_vl_config_data {
+  struct vty *vty;		/* vty stuff */
+  struct in_addr area_id;	/* area ID from command line */
+  int format;			/* command line area ID format */
+  struct in_addr vl_peer;	/* command line vl_peer */
+  int auth_type;		/* Authehntication type, if given */
+  char *auth_key;		/* simple password if present */
+  int crypto_key_id;		/* Cryptographic key ID */
+  char *md5_key;		/* MD5 authentication key */
+  int hello_interval;	        /* Obvious what these are... */
+  int retransmit_interval; 
+  int transmit_delay;
+  int dead_interval;
+};
+
+void
+ospf_vl_config_data_init (struct ospf_vl_config_data *vl_config, 
+			  struct vty *vty)
+{
+  memset (vl_config, 0, sizeof (struct ospf_vl_config_data));
+  vl_config->auth_type = OSPF_AUTH_CMD_NOTSEEN;
+  vl_config->vty = vty;
+}
+
+struct ospf_vl_data *
+ospf_find_vl_data (struct ospf_vl_config_data *vl_config)
+{
+  struct ospf_area *area;
+  struct ospf_vl_data *vl_data;
+  struct vty *vty;
+  struct in_addr area_id;
+
+  vty = vl_config->vty;
+  area_id = vl_config->area_id;
+
+  if (area_id.s_addr == OSPF_AREA_BACKBONE)
+    {
+      vty_out (vty, 
+	       "Configuring VLs over the backbone is not allowed%s",
+               VTY_NEWLINE);
+      return NULL;
+    }
+  area = ospf_area_get (area_id, vl_config->format);
+
+  if (area->external_routing != OSPF_AREA_DEFAULT)
+    {
+      if (vl_config->format == OSPF_AREA_ID_FORMAT_ADDRESS)
+	vty_out (vty, "Area %s is %s%s",
+		 inet_ntoa (area_id),
+#ifdef HAVE_NSSA
+		 area->external_routing == OSPF_AREA_NSSA?"nssa":"stub",
+#else
+		 "stub",
+#endif /* HAVE_NSSA */		 
+		 VTY_NEWLINE);
+      else
+	vty_out (vty, "Area %ld is %s%s",
+		 (u_long)ntohl (area_id.s_addr),
+#ifdef HAVE_NSSA
+		 area->external_routing == OSPF_AREA_NSSA?"nssa":"stub",
+#else
+		 "stub",
+#endif /* HAVE_NSSA */		 
+		 VTY_NEWLINE);	
+      return NULL;
+    }
+  
+  if ((vl_data = ospf_vl_lookup (area, vl_config->vl_peer)) == NULL)
+    {
+      vl_data = ospf_vl_data_new (area, vl_config->vl_peer);
+      if (vl_data->vl_oi == NULL)
+	{
+	  vl_data->vl_oi = ospf_vl_new (vl_data);
+	  ospf_vl_add (vl_data);
+	  ospf_spf_calculate_schedule ();
+	}
+    }
+  return vl_data;
+}
+
+
+int
+ospf_vl_set_security (struct ospf_vl_data *vl_data,
+		      struct ospf_vl_config_data *vl_config)
+{
+  struct crypt_key *ck;
+  struct vty *vty;
+  struct interface *ifp = vl_data->vl_oi->ifp;
+
+  vty = vl_config->vty;
+
+  if (vl_config->auth_type != OSPF_AUTH_CMD_NOTSEEN)
+    {
+      SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
+      IF_DEF_PARAMS (ifp)->auth_type = vl_config->auth_type;
+    }
+
+  if (vl_config->auth_key)
+    {
+      memset(IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE+1);
+      strncpy (IF_DEF_PARAMS (ifp)->auth_simple, vl_config->auth_key, 
+	       OSPF_AUTH_SIMPLE_SIZE);
+    }
+  else if (vl_config->md5_key)
+    {
+      if (ospf_crypt_key_lookup (IF_DEF_PARAMS (ifp)->auth_crypt, vl_config->crypto_key_id) 
+	  != NULL)
+	{
+	  vty_out (vty, "OSPF: Key %d already exists%s",
+		   vl_config->crypto_key_id, VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+      ck = ospf_crypt_key_new ();
+      ck->key_id = vl_config->crypto_key_id;
+      memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE+1);
+      strncpy (ck->auth_key, vl_config->md5_key, OSPF_AUTH_MD5_SIZE);
+      
+      ospf_crypt_key_add (IF_DEF_PARAMS (ifp)->auth_crypt, ck);
+    }
+  else if (vl_config->crypto_key_id != 0)
+    {
+      /* Delete a key */
+
+      if (ospf_crypt_key_lookup (IF_DEF_PARAMS (ifp)->auth_crypt, 
+				 vl_config->crypto_key_id) == NULL)
+	{
+	  vty_out (vty, "OSPF: Key %d does not exist%s", 
+		   vl_config->crypto_key_id, VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+      
+      ospf_crypt_key_delete (IF_DEF_PARAMS (ifp)->auth_crypt, vl_config->crypto_key_id);
+
+    }
+  
+  return CMD_SUCCESS;
+}
+
+
+
+int
+ospf_vl_set_timers (struct ospf_vl_data *vl_data,
+		    struct ospf_vl_config_data *vl_config)
+{
+  struct interface *ifp = ifp = vl_data->vl_oi->ifp;
+  /* Virtual Link data initialised to defaults, so only set
+     if a value given */
+  if (vl_config->hello_interval)
+    {
+      SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
+      IF_DEF_PARAMS (ifp)->v_hello = vl_config->hello_interval;
+    }
+
+  if (vl_config->dead_interval)
+    {
+      SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
+      IF_DEF_PARAMS (ifp)->v_wait = vl_config->dead_interval;
+    }
+
+  if (vl_config->retransmit_interval)
+    {
+      SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval);
+      IF_DEF_PARAMS (ifp)->retransmit_interval = vl_config->retransmit_interval;
+    }
+  
+  if (vl_config->transmit_delay)
+    {
+      SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay);
+      IF_DEF_PARAMS (ifp)->transmit_delay = vl_config->transmit_delay;
+    }
+  
+  return CMD_SUCCESS;
+}
+
+
+
+/* The business end of all of the above */
+int
+ospf_vl_set (struct ospf_vl_config_data *vl_config)
+{
+  struct ospf_vl_data *vl_data;
+  int ret;
+
+  vl_data = ospf_find_vl_data (vl_config);
+  if (!vl_data)
+    return CMD_WARNING;
+  
+  /* Process this one first as it can have a fatal result, which can
+     only logically occur if the virtual link exists already
+     Thus a command error does not result in a change to the
+     running configuration such as unexpectedly altered timer 
+     values etc.*/
+  ret = ospf_vl_set_security (vl_data, vl_config);
+  if (ret != CMD_SUCCESS)
+    return ret;
+
+  /* Set any time based parameters, these area already range checked */
+
+  ret = ospf_vl_set_timers (vl_data, vl_config);
+  if (ret != CMD_SUCCESS)
+    return ret;
+
+  return CMD_SUCCESS;
+
+}
+
+/* This stuff exists to make specifying all the alias commands A LOT simpler
+ */
+#define VLINK_HELPSTR_IPADDR \
+       "OSPF area parameters\n" \
+       "OSPF area ID in IP address format\n" \
+       "OSPF area ID as a decimal value\n" \
+       "Configure a virtual link\n" \
+       "Router ID of the remote ABR\n"
+
+#define VLINK_HELPSTR_AUTHTYPE_SIMPLE \
+       "Enable authentication on this virtual link\n" \
+       "dummy string \n" 
+
+#define VLINK_HELPSTR_AUTHTYPE_ALL \
+       VLINK_HELPSTR_AUTHTYPE_SIMPLE \
+       "Use null authentication\n" \
+       "Use message-digest authentication\n"
+
+#define VLINK_HELPSTR_TIME_PARAM_NOSECS \
+       "Time between HELLO packets\n" \
+       "Time between retransmitting lost link state advertisements\n" \
+       "Link state transmit delay\n" \
+       "Interval after which a neighbor is declared dead\n"
+
+#define VLINK_HELPSTR_TIME_PARAM \
+       VLINK_HELPSTR_TIME_PARAM_NOSECS \
+       "Seconds\n"
+
+#define VLINK_HELPSTR_AUTH_SIMPLE \
+       "Authentication password (key)\n" \
+       "The OSPF password (key)"
+
+#define VLINK_HELPSTR_AUTH_MD5 \
+       "Message digest authentication password (key)\n" \
+       "dummy string \n" \
+       "Key ID\n" \
+       "Use MD5 algorithm\n" \
+       "The OSPF password (key)"
+
+DEFUN (area_vlink,
+       area_vlink_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D",
+       VLINK_HELPSTR_IPADDR)
+{
+  struct ospf_vl_config_data vl_config;
+  char auth_key[OSPF_AUTH_SIMPLE_SIZE+1];
+  char md5_key[OSPF_AUTH_MD5_SIZE+1]; 
+  int i;
+  int ret;
+  
+  ospf_vl_config_data_init(&vl_config, vty);
+
+  /* Read off first 2 parameters and check them */
+  ret = ospf_str2area_id (argv[0], &vl_config.area_id, &vl_config.format);
+  if (ret < 0)
+    {
+      vty_out (vty, "OSPF area ID is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = inet_aton (argv[1], &vl_config.vl_peer);
+  if (! ret)
+    {
+      vty_out (vty, "Please specify valid Router ID as a.b.c.d%s",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc <=2)
+    {
+      /* Thats all folks! - BUGS B. strikes again!!!*/
+
+      return  ospf_vl_set (&vl_config);
+    }
+
+  /* Deal with other parameters */
+  for (i=2; i < argc; i++)
+    {
+
+      /* vty_out (vty, "argv[%d] - %s%s", i, argv[i], VTY_NEWLINE); */
+
+      switch (argv[i][0])
+	{
+
+	case 'a':
+	  if (i > 2 || strncmp (argv[i], "authentication-", 15) == 0)
+	    {
+	      /* authentication-key - this option can occur anywhere on 
+		                      command line.  At start of command line
+				      must check for authentication option. */
+	      memset (auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1);
+	      strncpy (auth_key, argv[i+1], OSPF_AUTH_SIMPLE_SIZE);
+	      vl_config.auth_key = auth_key;
+	      i++;
+	    }
+	  else if (strncmp (argv[i], "authentication", 14) == 0)
+	    {
+	      /* authentication  - this option can only occur at start
+		                   of command line */
+	      vl_config.auth_type = OSPF_AUTH_SIMPLE;
+	      if ((i+1) < argc)
+		{
+		  if (strncmp (argv[i+1], "n", 1) == 0)
+		    {
+		      /* "authentication null" */
+		      vl_config.auth_type = OSPF_AUTH_NULL;
+		      i++;
+		    }
+		  else if (strncmp (argv[i+1], "m", 1) == 0
+			   && strcmp (argv[i+1], "message-digest-") != 0)
+		    {
+		      /* "authentication message-digest" */ 
+		      vl_config.auth_type = OSPF_AUTH_CRYPTOGRAPHIC;
+		      i++;
+		    }
+		}
+	    }
+	  break;
+
+	case 'm':
+	  /* message-digest-key */
+	  i++;
+	  vl_config.crypto_key_id = strtol (argv[i], NULL, 10);
+	  if (vl_config.crypto_key_id < 0)
+	    return CMD_WARNING;
+	  i++;
+	  memset(md5_key, 0, OSPF_AUTH_MD5_SIZE+1);
+	  strncpy (md5_key, argv[i], OSPF_AUTH_MD5_SIZE);
+	  vl_config.md5_key = md5_key; 
+	  break;
+
+	case 'h':
+	  /* Hello interval */
+	  i++;
+	  vl_config.hello_interval = strtol (argv[i], NULL, 10);
+	  if (vl_config.hello_interval < 0) 
+	    return CMD_WARNING;
+	  break;
+
+	case 'r':
+	  /* Retransmit Interval */
+	  i++;
+	  vl_config.retransmit_interval = strtol (argv[i], NULL, 10);
+	  if (vl_config.retransmit_interval < 0)
+	    return CMD_WARNING;
+	  break;
+
+	case 't':
+	  /* Transmit Delay */
+	  i++;
+	  vl_config.transmit_delay = strtol (argv[i], NULL, 10);
+	  if (vl_config.transmit_delay < 0)
+	    return CMD_WARNING;
+	  break;
+
+	case 'd':
+	  /* Dead Interval */
+	  i++;
+	  vl_config.dead_interval = strtol (argv[i], NULL, 10);
+	  if (vl_config.dead_interval < 0)
+	    return CMD_WARNING;
+	  break;
+	}
+    }
+
+
+  /* Action configuration */
+
+  return ospf_vl_set (&vl_config);
+
+}
+
+DEFUN (no_area_vlink,
+       no_area_vlink_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D",
+       NO_STR
+       VLINK_HELPSTR_IPADDR)
+{
+  struct ospf_area *area;
+  struct ospf_vl_config_data vl_config;
+  struct ospf_vl_data *vl_data = NULL;
+  char auth_key[OSPF_AUTH_SIMPLE_SIZE+1];
+  int i;
+  int ret, format;
+
+  ospf_vl_config_data_init(&vl_config, vty);
+
+  ret = ospf_str2area_id (argv[0], &vl_config.area_id, &format);
+  if (ret < 0)
+    {
+      vty_out (vty, "OSPF area ID is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  area = ospf_area_lookup_by_area_id (vl_config.area_id);
+  if (!area)
+    {
+      vty_out (vty, "Area does not exist%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = inet_aton (argv[1], &vl_config.vl_peer);
+  if (! ret)
+    {
+      vty_out (vty, "Please specify valid Router ID as a.b.c.d%s",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc <=2)
+    {
+      /* Basic VLink no command */
+      /* Thats all folks! - BUGS B. strikes again!!!*/
+      if ((vl_data = ospf_vl_lookup (area, vl_config.vl_peer)))
+	ospf_vl_delete (vl_data);
+
+      ospf_area_check_free (vl_config.area_id);
+      
+      return CMD_SUCCESS;
+    }
+
+  /* If we are down here, we are reseting parameters */
+
+  /* Deal with other parameters */
+  for (i=2; i < argc; i++)
+    {
+
+      /* vty_out (vty, "argv[%d] - %s%s", i, argv[i], VTY_NEWLINE); */
+
+      switch (argv[i][0])
+	{
+
+	case 'a':
+	  if (i > 2 || strncmp (argv[i], "authentication-", 15) == 0)
+	    {
+	      /* authentication-key - this option can occur anywhere on 
+		                      command line.  At start of command line
+				      must check for authentication option. */
+	      memset (auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1);
+	      vl_config.auth_key = auth_key;
+	    }
+	  else if (strncmp (argv[i], "authentication", 14) == 0)
+	    {
+	      /* authentication  - this option can only occur at start
+		                   of command line */
+	      vl_config.auth_type = OSPF_AUTH_NOTSET;
+	    }
+	  break;
+
+	case 'm':
+	  /* message-digest-key */
+	  /* Delete one key */
+	  i++;
+	  vl_config.crypto_key_id = strtol (argv[i], NULL, 10);
+	  if (vl_config.crypto_key_id < 0)
+	    return CMD_WARNING;
+	  vl_config.md5_key = NULL; 
+	  break;
+
+	case 'h':
+	  /* Hello interval */
+	  vl_config.hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
+	  break;
+
+	case 'r':
+	  /* Retransmit Interval */
+	  vl_config.retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
+	  break;
+
+	case 't':
+	  /* Transmit Delay */
+	  vl_config.transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
+	  break;
+
+	case 'd':
+	  /* Dead Interval */
+	  i++;
+	  vl_config.dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
+	  break;
+	}
+    }
+
+
+  /* Action configuration */
+
+  return ospf_vl_set (&vl_config);
+}
+
+ALIAS (area_vlink,
+       area_vlink_param1_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535>",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_param1_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (area_vlink,
+       area_vlink_param2_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535>",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_param2_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (area_vlink,
+       area_vlink_param3_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535>",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_param3_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (area_vlink,
+       area_vlink_param4_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535> "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) <1-65535>",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_param4_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval) "
+       "(hello-interval|retransmit-interval|transmit-delay|dead-interval)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM
+       VLINK_HELPSTR_TIME_PARAM)
+
+ALIAS (area_vlink,
+       area_vlink_authtype_args_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|) (message-digest|null)",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_ALL)
+
+ALIAS (area_vlink,
+       area_vlink_authtype_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|)",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_SIMPLE)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_authtype_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_SIMPLE)
+
+ALIAS (area_vlink,
+       area_vlink_md5_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(message-digest-key|) <1-255> md5 KEY",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTH_MD5)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_md5_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(message-digest-key|) <1-255>",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTH_MD5)
+
+ALIAS (area_vlink,
+       area_vlink_authkey_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication-key|) AUTH_KEY",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTH_SIMPLE)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_authkey_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication-key|)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTH_SIMPLE)
+
+ALIAS (area_vlink,
+       area_vlink_authtype_args_authkey_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|) (message-digest|null) "
+       "(authentication-key|) AUTH_KEY",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_ALL
+       VLINK_HELPSTR_AUTH_SIMPLE)
+
+ALIAS (area_vlink,
+       area_vlink_authtype_authkey_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|) "
+       "(authentication-key|) AUTH_KEY",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_SIMPLE
+       VLINK_HELPSTR_AUTH_SIMPLE)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_authtype_authkey_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|) "
+       "(authentication-key|)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_SIMPLE
+       VLINK_HELPSTR_AUTH_SIMPLE)
+
+ALIAS (area_vlink,
+       area_vlink_authtype_args_md5_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|) (message-digest|null) "
+       "(message-digest-key|) <1-255> md5 KEY",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_ALL
+       VLINK_HELPSTR_AUTH_MD5)
+
+ALIAS (area_vlink,
+       area_vlink_authtype_md5_cmd,
+       "area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|) "
+       "(message-digest-key|) <1-255> md5 KEY",
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_SIMPLE
+       VLINK_HELPSTR_AUTH_MD5)
+
+ALIAS (no_area_vlink,
+       no_area_vlink_authtype_md5_cmd,
+       "no area (A.B.C.D|<0-4294967295>) virtual-link A.B.C.D "
+       "(authentication|) "
+       "(message-digest-key|)",
+       NO_STR
+       VLINK_HELPSTR_IPADDR
+       VLINK_HELPSTR_AUTHTYPE_SIMPLE
+       VLINK_HELPSTR_AUTH_MD5)
+
+
+DEFUN (area_shortcut,
+       area_shortcut_cmd,
+       "area (A.B.C.D|<0-4294967295>) shortcut (default|enable|disable)",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure the area's shortcutting mode\n"
+       "Set default shortcutting behavior\n"
+       "Enable shortcutting through the area\n"
+       "Disable shortcutting through the area\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int mode;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("shortcut", area_id, format, argv[0]);
+
+  area = ospf_area_get (area_id, format);
+
+  if (strncmp (argv[1], "de", 2) == 0)
+    mode = OSPF_SHORTCUT_DEFAULT;
+  else if (strncmp (argv[1], "di", 2) == 0)
+    mode = OSPF_SHORTCUT_DISABLE;
+  else if (strncmp (argv[1], "e", 1) == 0)
+    mode = OSPF_SHORTCUT_ENABLE;
+  else
+    return CMD_WARNING;
+
+  ospf_area_shortcut_set (area, mode);
+
+  if (ospf_top->abr_type != OSPF_ABR_SHORTCUT)
+    vty_out (vty, "Shortcut area setting will take effect "
+	     "only when the router is configured as Shortcut ABR%s",
+	     VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_shortcut,
+       no_area_shortcut_cmd,
+       "no area (A.B.C.D|<0-4294967295>) shortcut (enable|disable)",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Deconfigure the area's shortcutting mode\n"
+       "Deconfigure enabled shortcutting through the area\n"
+       "Deconfigure disabled shortcutting through the area\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("shortcut", area_id, format, argv[0]);
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (!area)
+    return CMD_SUCCESS;
+
+  ospf_area_shortcut_unset (area);
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (area_stub,
+       area_stub_cmd,
+       "area (A.B.C.D|<0-4294967295>) stub",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as stub\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int ret, format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[0]);
+
+  ret = ospf_area_stub_set (ospf, area_id);
+  if (ret == 0)
+    {
+      vty_out (vty, "First deconfigure all virtual link through this area%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ospf_area_no_summary_unset (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (area_stub_no_summary,
+       area_stub_no_summary_cmd,
+       "area (A.B.C.D|<0-4294967295>) stub no-summary",
+       "OSPF stub parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as stub\n"
+       "Do not inject inter-area routes into stub\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int ret, format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[0]);
+
+  ret = ospf_area_stub_set (ospf, area_id);
+  if (ret == 0)
+    {
+      vty_out (vty, "%% Area cannot be nssa as it contains a virtual link%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ospf_area_no_summary_set (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_stub,
+       no_area_stub_cmd,
+       "no area (A.B.C.D|<0-4294967295>) stub",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as stub\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[0]);
+
+  ospf_area_stub_unset (ospf, area_id);
+  ospf_area_no_summary_unset (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_stub_no_summary,
+       no_area_stub_no_summary_cmd,
+       "no area (A.B.C.D|<0-4294967295>) stub no-summary",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as stub\n"
+       "Do not inject inter-area routes into area\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[0]);
+  ospf_area_no_summary_unset (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+#ifdef HAVE_NSSA
+DEFUN (area_nssa,
+       area_nssa_cmd,
+       "area (A.B.C.D|<0-4294967295>) nssa",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as nssa\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int ret, format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("NSSA", area_id, format, argv[0]);
+
+  ret = ospf_area_nssa_set (ospf, area_id);
+  if (ret == 0)
+    {
+      vty_out (vty, "%% Area cannot be nssa as it contains a virtual link%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc > 1)
+    {
+      if (strncmp (argv[1], "translate-c", 11) == 0)
+	ospf_area_nssa_translator_role_set (ospf, area_id,
+					    OSPF_NSSA_ROLE_CANDIDATE);
+      else if (strncmp (argv[1], "translate-n", 11) == 0)
+	ospf_area_nssa_translator_role_set (ospf, area_id,
+					    OSPF_NSSA_ROLE_NEVER);
+      else if (strncmp (argv[1], "translate-a", 11) == 0)
+	ospf_area_nssa_translator_role_set (ospf, area_id,
+					    OSPF_NSSA_ROLE_ALWAYS);
+    }
+
+  if (argc > 2)
+    ospf_area_no_summary_set (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (area_nssa,
+       area_nssa_translate_no_summary_cmd,
+       "area (A.B.C.D|<0-4294967295>) nssa (translate-candidate|translate-never|translate-always) (no-summary|)",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as nssa\n"
+       "Configure NSSA-ABR for translate election (default)\n"
+       "Configure NSSA-ABR to never translate\n"
+       "Configure NSSA-ABR to always translate\n"
+       "Do not inject inter-area routes into nssa\n"
+       "dummy\n")
+
+ALIAS (area_nssa,
+       area_nssa_translate_cmd,
+       "area (A.B.C.D|<0-4294967295>) nssa (translate-candidate|translate-never|translate-always)",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as nssa\n"
+       "Configure NSSA-ABR for translate election (default)\n"
+       "Configure NSSA-ABR to never translate\n"
+       "Configure NSSA-ABR to always translate\n")
+
+DEFUN (area_nssa_no_summary,
+       area_nssa_no_summary_cmd,
+       "area (A.B.C.D|<0-4294967295>) nssa no-summary",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as nssa\n"
+       "Do not inject inter-area routes into nssa\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int ret, format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("NSSA", area_id, format, argv[0]);
+
+  ret = ospf_area_nssa_set (ospf, area_id);
+  if (ret == 0)
+    {
+      vty_out (vty, "%% Area cannot be nssa as it contains a virtual link%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ospf_area_no_summary_set (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_nssa,
+       no_area_nssa_cmd,
+       "no area (A.B.C.D|<0-4294967295>) nssa",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as nssa\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("NSSA", area_id, format, argv[0]);
+
+  ospf_area_nssa_unset (ospf, area_id);
+  ospf_area_no_summary_unset (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_nssa_no_summary,
+       no_area_nssa_no_summary_cmd,
+       "no area (A.B.C.D|<0-4294967295>) nssa no-summary",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Configure OSPF area as nssa\n"
+       "Do not inject inter-area routes into nssa\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("NSSA", area_id, format, argv[0]);
+  ospf_area_no_summary_unset (ospf, area_id);
+
+  return CMD_SUCCESS;
+}
+
+#endif /* HAVE_NSSA */
+
+DEFUN (area_default_cost,
+       area_default_cost_cmd,
+       "area (A.B.C.D|<0-4294967295>) default-cost <0-16777215>",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Set the summary-default cost of a NSSA or stub area\n"
+       "Stub's advertised default summary cost\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  u_int32_t cost;
+  int format;
+
+  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);
+
+  area = ospf_area_get (area_id, format);
+
+  if (area->external_routing == OSPF_AREA_DEFAULT)
+    {
+      vty_out (vty, "The area is neither stub, nor NSSA%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  area->default_cost = cost;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_default_cost,
+       no_area_default_cost_cmd,
+       "no area (A.B.C.D|<0-4294967295>) default-cost <0-16777215>",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Set the summary-default cost of a NSSA or stub area\n"
+       "Stub's advertised default summary cost\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  u_int32_t cost;
+  int format;
+
+  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);
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return CMD_SUCCESS;
+
+  if (area->external_routing == OSPF_AREA_DEFAULT)
+    {
+      vty_out (vty, "The area is neither stub, nor NSSA%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  area->default_cost = 1;
+
+  ospf_area_check_free (area_id);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (area_export_list,
+       area_export_list_cmd,
+       "area (A.B.C.D|<0-4294967295>) export-list NAME",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Set the filter for networks announced to other areas\n"
+       "Name of the access-list\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("export-list", area_id, format, argv[0]);
+
+  area = ospf_area_get (area_id, format);
+  ospf_area_export_list_set (area, argv[1]);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_export_list,
+       no_area_export_list_cmd,
+       "no area (A.B.C.D|<0-4294967295>) export-list NAME",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Unset the filter for networks announced to other areas\n"
+       "Name of the access-list\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("export-list", area_id, format, argv[0]);
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return CMD_SUCCESS;
+
+  ospf_area_export_list_unset (area);
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (area_import_list,
+       area_import_list_cmd,
+       "area (A.B.C.D|<0-4294967295>) import-list NAME",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Set the filter for networks from other areas announced to the specified one\n"
+       "Name of the access-list\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("import-list", area_id, format, argv[0]);
+
+  area = ospf_area_get (area_id, format);
+  ospf_area_import_list_set (area, argv[1]);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_import_list,
+       no_area_import_list_cmd,
+       "no area (A.B.C.D|<0-4294967295>) import-list NAME",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Unset the filter for networks announced to other areas\n"
+       "Name of the access-list\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID_NO_BB ("import-list", area_id, format, argv[0]);
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return CMD_SUCCESS;
+
+  ospf_area_import_list_unset (area);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (area_filter_list,
+       area_filter_list_cmd,
+       "area (A.B.C.D|<0-4294967295>) filter-list prefix WORD (in|out)",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Filter networks between OSPF areas\n"
+       "Filter prefixes between OSPF areas\n"
+       "Name of an IP prefix-list\n"
+       "Filter networks sent to this area\n"
+       "Filter networks sent from this area\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  struct prefix_list *plist;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+
+  area = ospf_area_get (area_id, format);
+  plist = prefix_list_lookup (AFI_IP, argv[1]);
+  if (strncmp (argv[2], "in", 2) == 0)
+    {
+      PREFIX_LIST_IN (area) = plist;
+      if (PREFIX_NAME_IN (area))
+	free (PREFIX_NAME_IN (area));
+
+      PREFIX_NAME_IN (area) = strdup (argv[1]);
+      ospf_schedule_abr_task ();
+    }
+  else
+    {
+      PREFIX_LIST_OUT (area) = plist;
+      if (PREFIX_NAME_OUT (area))
+	free (PREFIX_NAME_OUT (area));
+
+      PREFIX_NAME_OUT (area) = strdup (argv[1]);
+      ospf_schedule_abr_task ();
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_filter_list,
+       no_area_filter_list_cmd,
+       "no area (A.B.C.D|<0-4294967295>) filter-list prefix WORD (in|out)",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Filter networks between OSPF areas\n"
+       "Filter prefixes between OSPF areas\n"
+       "Name of an IP prefix-list\n"
+       "Filter networks sent to this area\n"
+       "Filter networks sent from this area\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  struct prefix_list *plist;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  plist = prefix_list_lookup (AFI_IP, argv[1]);
+  if (strncmp (argv[2], "in", 2) == 0)
+    {
+      if (PREFIX_NAME_IN (area))
+	if (strcmp (PREFIX_NAME_IN (area), argv[1]) != 0)
+	  return CMD_SUCCESS;
+
+      PREFIX_LIST_IN (area) = NULL;
+      if (PREFIX_NAME_IN (area))
+	free (PREFIX_NAME_IN (area));
+
+      PREFIX_NAME_IN (area) = NULL;
+
+      ospf_schedule_abr_task ();
+    }
+  else
+    {
+      if (PREFIX_NAME_OUT (area))
+	if (strcmp (PREFIX_NAME_OUT (area), argv[1]) != 0)
+	  return CMD_SUCCESS;
+
+      PREFIX_LIST_OUT (area) = NULL;
+      if (PREFIX_NAME_OUT (area))
+	free (PREFIX_NAME_OUT (area));
+
+      PREFIX_NAME_OUT (area) = NULL;
+
+      ospf_schedule_abr_task ();
+    }
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (area_authentication_message_digest,
+       area_authentication_message_digest_cmd,
+       "area (A.B.C.D|<0-4294967295>) authentication message-digest",
+       "OSPF area parameters\n"
+       "Enable authentication\n"
+       "Use message-digest authentication\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+
+  area = ospf_area_get (area_id, format);
+  area->auth_type = OSPF_AUTH_CRYPTOGRAPHIC;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (area_authentication,
+       area_authentication_cmd,
+       "area (A.B.C.D|<0-4294967295>) authentication",
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Enable authentication\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+
+  area = ospf_area_get (area_id, format);
+  area->auth_type = OSPF_AUTH_SIMPLE;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_authentication,
+       no_area_authentication_cmd,
+       "no area (A.B.C.D|<0-4294967295>) authentication",
+       NO_STR
+       "OSPF area parameters\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Enable authentication\n")
+{
+  struct ospf_area *area;
+  struct in_addr area_id;
+  int format;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return CMD_SUCCESS;
+
+  area->auth_type = OSPF_AUTH_NULL;
+
+  ospf_area_check_free (area_id);
+  
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (ospf_abr_type,
+       ospf_abr_type_cmd,
+       "ospf abr-type (cisco|ibm|shortcut|standard)",
+       "OSPF specific commands\n"
+       "Set OSPF ABR type\n"
+       "Alternative ABR, cisco implementation\n"
+       "Alternative ABR, IBM implementation\n"
+       "Shortcut ABR\n"
+       "Standard behavior (RFC2328)\n")
+{
+  u_char abr_type = OSPF_ABR_UNKNOWN;
+
+  if (strncmp (argv[0], "c", 1) == 0)
+    abr_type = OSPF_ABR_CISCO;
+  else if (strncmp (argv[0], "i", 1) == 0)
+    abr_type = OSPF_ABR_IBM;
+  else if (strncmp (argv[0], "sh", 2) == 0)
+    abr_type = OSPF_ABR_SHORTCUT;
+  else if (strncmp (argv[0], "st", 2) == 0)
+    abr_type = OSPF_ABR_STAND;
+  else
+    return CMD_WARNING;
+
+  /* If ABR type value is changed, schedule ABR task. */
+  if (ospf_top->abr_type != abr_type)
+    {
+      ospf_top->abr_type = abr_type;
+      ospf_schedule_abr_task ();
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_abr_type,
+       no_ospf_abr_type_cmd,
+       "no ospf abr-type (cisco|ibm|shortcut)",
+       NO_STR
+       "OSPF specific commands\n"
+       "Set OSPF ABR type\n"
+       "Alternative ABR, cisco implementation\n"
+       "Alternative ABR, IBM implementation\n"
+       "Shortcut ABR\n")
+{
+  u_char abr_type = OSPF_ABR_UNKNOWN;
+
+  if (strncmp (argv[0], "c", 1) == 0)
+    abr_type = OSPF_ABR_CISCO;
+  else if (strncmp (argv[0], "i", 1) == 0)
+    abr_type = OSPF_ABR_IBM;
+  else if (strncmp (argv[0], "s", 1) == 0)
+    abr_type = OSPF_ABR_SHORTCUT;
+  else
+    return CMD_WARNING;
+
+  /* If ABR type value is changed, schedule ABR task. */
+  if (ospf_top->abr_type == abr_type)
+    {
+      ospf_top->abr_type = OSPF_ABR_STAND;
+      ospf_schedule_abr_task ();
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_compatible_rfc1583,
+       ospf_compatible_rfc1583_cmd,
+       "compatible rfc1583",
+       "OSPF compatibility list\n"
+       "compatible with RFC 1583\n")
+{
+  struct ospf *ospf = vty->index;
+
+  if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
+    {
+      SET_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE);
+      ospf_spf_calculate_schedule ();
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_compatible_rfc1583,
+       no_ospf_compatible_rfc1583_cmd,
+       "no compatible rfc1583",
+       NO_STR
+       "OSPF compatibility list\n"
+       "compatible with RFC 1583\n")
+{
+  struct ospf *ospf = vty->index;
+
+  if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
+    {
+      UNSET_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE);
+      ospf_spf_calculate_schedule ();
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (ospf_compatible_rfc1583,
+       ospf_rfc1583_flag_cmd,
+       "ospf rfc1583compatibility",
+       "OSPF specific commands\n"
+       "Enable the RFC1583Compatibility flag\n")
+
+ALIAS (no_ospf_compatible_rfc1583,
+       no_ospf_rfc1583_flag_cmd,
+       "no ospf rfc1583compatibility",
+       NO_STR
+       "OSPF specific commands\n"
+       "Disable the RFC1583Compatibility flag\n")
+
+DEFUN (timers_spf,
+       timers_spf_cmd,
+       "timers spf <0-4294967295> <0-4294967295>",
+       "Adjust routing timers\n"
+       "OSPF SPF timers\n"
+       "Delay between receiving a change to SPF calculation\n"
+       "Hold time between consecutive SPF calculations\n")
+{
+  struct ospf *ospf = vty->index;
+  u_int32_t delay, hold;
+
+  VTY_GET_UINT32 ("SPF delay timer", delay, argv[0]);
+  VTY_GET_UINT32 ("SPF hold timer", hold, argv[1]);
+
+  ospf_timers_spf_set (ospf, delay, hold);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_timers_spf,
+       no_timers_spf_cmd,
+       "no timers spf",
+       NO_STR
+       "Adjust routing timers\n"
+       "OSPF SPF timers\n")
+{
+  ospf_top->spf_delay = OSPF_SPF_DELAY_DEFAULT;
+  ospf_top->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (neighbor,
+       neighbor_cmd,
+       "neighbor A.B.C.D",
+       NEIGHBOR_STR
+       "Neighbor IP address\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr nbr_addr;
+  int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
+  int interval = OSPF_POLL_INTERVAL_DEFAULT;
+
+  VTY_GET_IPV4_ADDRESS ("neighbor address", nbr_addr, argv[0]);
+
+  if (argc > 1)
+    VTY_GET_INTEGER_RANGE ("neighbor priority", priority, argv[1], 0, 255);
+
+  if (argc > 2)
+    VTY_GET_INTEGER_RANGE ("poll interval", interval, argv[2], 1, 65535);
+
+  ospf_nbr_nbma_set (ospf, nbr_addr);
+  if (argc > 1)
+    ospf_nbr_nbma_priority_set (ospf, nbr_addr, priority);
+  if (argc > 2)
+    ospf_nbr_nbma_poll_interval_set (ospf, nbr_addr, priority);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (neighbor,
+       neighbor_priority_poll_interval_cmd,
+       "neighbor A.B.C.D priority <0-255> poll-interval <1-65535>",
+       NEIGHBOR_STR
+       "Neighbor IP address\n"
+       "Neighbor Priority\n"
+       "Priority\n"
+       "Dead Neighbor Polling interval\n"
+       "Seconds\n")
+
+ALIAS (neighbor,
+       neighbor_priority_cmd,
+       "neighbor A.B.C.D priority <0-255>",
+       NEIGHBOR_STR
+       "Neighbor IP address\n"
+       "Neighbor Priority\n"
+       "Seconds\n")
+
+DEFUN (neighbor_poll_interval,
+       neighbor_poll_interval_cmd,
+       "neighbor A.B.C.D poll-interval <1-65535>",
+       NEIGHBOR_STR
+       "Neighbor IP address\n"
+       "Dead Neighbor Polling interval\n"
+       "Seconds\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr nbr_addr;
+  int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
+  int interval = OSPF_POLL_INTERVAL_DEFAULT;
+
+  VTY_GET_IPV4_ADDRESS ("neighbor address", nbr_addr, argv[0]);
+
+  if (argc > 1)
+    VTY_GET_INTEGER_RANGE ("poll interval", interval, argv[1], 1, 65535);
+
+  if (argc > 2)
+    VTY_GET_INTEGER_RANGE ("neighbor priority", priority, argv[2], 0, 255);
+
+  ospf_nbr_nbma_set (ospf, nbr_addr);
+  if (argc > 1)
+    ospf_nbr_nbma_poll_interval_set (ospf, nbr_addr, interval);
+  if (argc > 2)
+    ospf_nbr_nbma_priority_set (ospf, nbr_addr, priority);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (neighbor_poll_interval,
+       neighbor_poll_interval_priority_cmd,
+       "neighbor A.B.C.D poll-interval <1-65535> priority <0-255>",
+       NEIGHBOR_STR
+       "Neighbor address\n"
+       "OSPF dead-router polling interval\n"
+       "Seconds\n"
+       "OSPF priority of non-broadcast neighbor\n"
+       "Priority\n")
+
+DEFUN (no_neighbor,
+       no_neighbor_cmd,
+       "no neighbor A.B.C.D",
+       NO_STR
+       NEIGHBOR_STR
+       "Neighbor IP address\n")
+{
+  struct ospf *ospf = vty->index;
+  struct in_addr nbr_addr;
+  int ret;
+
+  VTY_GET_IPV4_ADDRESS ("neighbor address", nbr_addr, argv[0]);
+
+  ret = ospf_nbr_nbma_unset (ospf, nbr_addr);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_neighbor,
+       no_neighbor_priority_cmd,
+       "no neighbor A.B.C.D priority <0-255>",
+       NO_STR
+       NEIGHBOR_STR
+       "Neighbor IP address\n"
+       "Neighbor Priority\n"
+       "Priority\n")
+
+ALIAS (no_neighbor,
+       no_neighbor_poll_interval_cmd,
+       "no neighbor A.B.C.D poll-interval <1-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       "Neighbor IP address\n"
+       "Dead Neighbor Polling interval\n"
+       "Seconds\n")
+
+ALIAS (no_neighbor,
+       no_neighbor_priority_pollinterval_cmd,
+       "no neighbor A.B.C.D priority <0-255> poll-interval <1-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       "Neighbor IP address\n"
+       "Neighbor Priority\n"
+       "Priority\n"
+       "Dead Neighbor Polling interval\n"
+       "Seconds\n")
+
+
+DEFUN (refresh_timer, refresh_timer_cmd,
+       "refresh timer <10-1800>",
+       "Adjust refresh parameters\n"
+       "Set refresh timer\n"
+       "Timer value in seconds\n")
+{
+  struct ospf *ospf = vty->index;
+  int interval;
+  
+  VTY_GET_INTEGER_RANGE ("refresh timer", interval, argv[0], 10, 1800);
+  interval = (interval / 10) * 10;
+
+  ospf_timers_refresh_set (ospf, interval);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_refresh_timer, no_refresh_timer_val_cmd,
+       "no refresh timer <10-1800>",
+       "Adjust refresh parameters\n"
+       "Unset refresh timer\n"
+       "Timer value in seconds\n")
+{
+  struct ospf *ospf = vty->index;
+  int interval;
+
+  if (argc == 1)
+    {
+      VTY_GET_INTEGER_RANGE ("refresh timer", interval, argv[0], 10, 1800);
+  
+      if (ospf->lsa_refresh_interval != interval ||
+	  interval == OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
+	return CMD_SUCCESS;
+    }
+
+  ospf_timers_refresh_unset (ospf);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_refresh_timer,
+       no_refresh_timer_cmd,
+       "no refresh timer",
+       "Adjust refresh parameters\n"
+       "Unset refresh timer\n")
+
+DEFUN (auto_cost_reference_bandwidth,
+       auto_cost_reference_bandwidth_cmd,
+       "auto-cost reference-bandwidth <1-4294967>",
+       "Calculate OSPF interface cost according to bandwidth\n"
+       "Use reference bandwidth method to assign OSPF cost\n"
+       "The reference bandwidth in terms of Mbits per second\n")
+{
+  u_int32_t refbw;
+  listnode node;
+
+  refbw = strtol (argv[0], NULL, 10);
+  if (refbw < 1 || refbw > 4294967)
+    {
+      vty_out (vty, "reference-bandwidth value is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* If reference bandwidth is changed. */
+  if ((refbw * 1000) == ospf_top->ref_bandwidth)
+    return CMD_SUCCESS;
+  
+  ospf_top->ref_bandwidth = refbw * 1000;
+  vty_out (vty, "%% OSPF: Reference bandwidth is changed.%s", VTY_NEWLINE);
+  vty_out (vty, "        Please ensure reference bandwidth is consistent across all routers%s", VTY_NEWLINE);
+      
+  for (node = listhead (ospf_top->iflist); node; nextnode (node))
+      ospf_if_recalculate_output_cost (getdata (node));
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_auto_cost_reference_bandwidth,
+       no_auto_cost_reference_bandwidth_cmd,
+       "no auto-cost reference-bandwidth",
+       NO_STR
+       "Calculate OSPF interface cost according to bandwidth\n"
+       "Use reference bandwidth method to assign OSPF cost\n")
+{
+  listnode node;
+
+  if (ospf_top->ref_bandwidth == OSPF_DEFAULT_REF_BANDWIDTH)
+    return CMD_SUCCESS;
+  
+  ospf_top->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
+  vty_out (vty, "%% OSPF: Reference bandwidth is changed.%s", VTY_NEWLINE);
+  vty_out (vty, "        Please ensure reference bandwidth is consistent across all routers%s", VTY_NEWLINE);
+
+  
+    for (node = listhead (ospf_top->iflist); node; nextnode (node))
+      ospf_if_recalculate_output_cost (getdata (node));
+      
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (clear_ip_ospf_neighbor,
+       clear_ip_ospf_neighbor_cmd,
+       "clear ip ospf neighbor A.B.C.D",
+       "Reset functions\n"
+       "IP\n"
+       "Clear OSPF\n"
+       "Neighbor list\n"
+       "Neighbor ID\n")
+{
+  listnode node;
+  struct ospf_neighbor *nbr;
+  struct in_addr router_id;
+  int ret;
+
+  ret = inet_aton (argv[0], &router_id);
+  if (!ret)
+    {
+      vty_out (vty, "Please specify Neighbor ID by A.B.C.D%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+
+      nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &router_id);
+
+      if (nbr)
+	{
+	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
+	  vty_out (vty, "clear neighbor %s%s", argv[0], VTY_NEWLINE);
+	  break;
+	}
+    }
+
+  return CMD_SUCCESS;
+}
+
+char *ospf_abr_type_descr_str[] = 
+{
+  "Unknown",
+  "Standard (RFC2328)",
+  "Alternative IBM",
+  "Alternative Cisco",
+  "Alternative Shortcut"
+};
+
+char *ospf_shortcut_mode_descr_str[] = 
+{
+  "Default",
+  "Enabled",
+  "Disabled"
+};
+
+
+
+void
+show_ip_ospf_area (struct vty *vty, struct ospf_area *area)
+{
+  /* Show Area ID. */
+  vty_out (vty, " Area ID: %s", inet_ntoa (area->area_id));
+
+  /* Show Area type/mode. */
+  if (OSPF_IS_AREA_BACKBONE (area))
+    vty_out (vty, " (Backbone)%s", VTY_NEWLINE);
+  else
+    {
+      if (area->external_routing == OSPF_AREA_STUB)
+	vty_out (vty, " (Stub%s%s)",
+		 area->no_summary ? ", no summary" : "",
+		 area->shortcut_configured ? "; " : "");
+
+#ifdef HAVE_NSSA
+
+      else
+      if (area->external_routing == OSPF_AREA_NSSA)
+	vty_out (vty, " (NSSA%s%s)",
+		 area->no_summary ? ", no summary" : "",
+		 area->shortcut_configured ? "; " : "");
+#endif /* HAVE_NSSA */
+
+      vty_out (vty, "%s", VTY_NEWLINE);
+      vty_out (vty, "   Shortcutting mode: %s",
+	       ospf_shortcut_mode_descr_str[area->shortcut_configured]);
+      vty_out (vty, ", S-bit consensus: %s%s",
+	       area->shortcut_capability ? "ok" : "no", VTY_NEWLINE);
+    }
+
+  /* Show number of interfaces. */
+  vty_out (vty, "   Number of interfaces in this area: Total: %d, "
+	   "Active: %d%s", listcount (area->oiflist),
+	   area->act_ints, VTY_NEWLINE);
+
+#ifdef HAVE_NSSA
+  if (area->external_routing == OSPF_AREA_NSSA)
+    {
+      vty_out (vty, "   It is an NSSA configuration. %s   Elected NSSA/ABR performs type-7/type-5 LSA translation. %s", VTY_NEWLINE, VTY_NEWLINE);
+      if (! OSPF_IS_ABR)
+	vty_out (vty, "   It is not ABR, therefore not Translator. %s",
+		 VTY_NEWLINE);
+      else
+	{
+	  if (area->NSSATranslator)
+	    vty_out (vty, "   We are an ABR and the NSSA Elected Translator. %s", VTY_NEWLINE);
+	  else
+	    vty_out (vty, "   We are an ABR, but not the NSSA Elected Translator. %s", VTY_NEWLINE);
+	}
+    }
+#endif /* HAVE_NSSA */
+
+  /* Show number of fully adjacent neighbors. */
+  vty_out (vty, "   Number of fully adjacent neighbors in this area:"
+	   " %d%s", area->full_nbrs, VTY_NEWLINE);
+
+  /* Show authentication type. */
+  vty_out (vty, "   Area has ");
+  if (area->auth_type == OSPF_AUTH_NULL)
+    vty_out (vty, "no authentication%s", VTY_NEWLINE);
+  else if (area->auth_type == OSPF_AUTH_SIMPLE)
+    vty_out (vty, "simple password authentication%s", VTY_NEWLINE);
+  else if (area->auth_type == OSPF_AUTH_CRYPTOGRAPHIC)
+    vty_out (vty, "message digest authentication%s", VTY_NEWLINE);
+
+  if (!OSPF_IS_AREA_BACKBONE (area))
+    vty_out (vty, "   Number of full virtual adjacencies going through"
+	     " this area: %d%s", area->full_vls, VTY_NEWLINE);
+
+  /* Show SPF calculation times. */
+  vty_out (vty, "   SPF algorithm executed %d times%s",
+	   area->spf_calculation, VTY_NEWLINE);
+
+  /* Show number of LSA. */
+  vty_out (vty, "   Number of LSA %ld%s", area->lsdb->total, VTY_NEWLINE);
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+DEFUN (show_ip_ospf,
+       show_ip_ospf_cmd,
+       "show ip ospf",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n")
+{
+  listnode node;
+  struct ospf_area * area;
+
+  /* Check OSPF is enable. */
+  if (ospf_top == NULL)
+    {
+      vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* Show Router ID. */
+  vty_out (vty, " OSPF Routing Process, Router ID: %s%s",
+           inet_ntoa (ospf_top->router_id),
+           VTY_NEWLINE);
+
+  /* Show capability. */
+  vty_out (vty, " Supports only single TOS (TOS0) routes%s", VTY_NEWLINE);
+  vty_out (vty, " This implementation conforms to RFC2328%s", VTY_NEWLINE);
+  vty_out (vty, " RFC1583Compatibility flag is %s%s",
+	   CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE) ?
+	   "enabled" : "disabled", VTY_NEWLINE);
+#ifdef HAVE_OPAQUE_LSA
+  vty_out (vty, " OpaqueCapability flag is %s%s%s",
+	   CHECK_FLAG (ospf_top->config, OSPF_OPAQUE_CAPABLE) ?
+           "enabled" : "disabled",
+           IS_OPAQUE_LSA_ORIGINATION_BLOCKED (ospf_top->opaque) ?
+           " (origination blocked)" : "",
+           VTY_NEWLINE);
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* Show SPF timers. */
+  vty_out (vty, " SPF schedule delay %d secs, Hold time between two SPFs %d secs%s",
+	   ospf_top->spf_delay, ospf_top->spf_holdtime, VTY_NEWLINE);
+
+  /* Show refresh parameters. */
+  vty_out (vty, " Refresh timer %d secs%s",
+	   ospf_top->lsa_refresh_interval, VTY_NEWLINE);
+	   
+  /* Show ABR/ASBR flags. */
+  if (CHECK_FLAG (ospf_top->flags, OSPF_FLAG_ABR))
+    vty_out (vty, " This router is an ABR, ABR type is: %s%s",
+             ospf_abr_type_descr_str[ospf_top->abr_type], VTY_NEWLINE);
+
+  if (CHECK_FLAG (ospf_top->flags, OSPF_FLAG_ASBR))
+    vty_out (vty, " This router is an ASBR "
+             "(injecting external routing information)%s", VTY_NEWLINE);
+
+  /* Show Number of AS-external-LSAs. */
+  vty_out (vty, " Number of external LSA %ld%s",
+	   ospf_lsdb_count_all (ospf_top->lsdb), VTY_NEWLINE);
+
+  /* Show number of areas attached. */
+  vty_out (vty, " Number of areas attached to this router: %d%s%s",
+           listcount (ospf_top->areas), VTY_NEWLINE, VTY_NEWLINE);
+
+  /* Show each area status. */
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    if ((area = getdata (node)) != NULL)
+      show_ip_ospf_area (vty, area);
+
+  return CMD_SUCCESS;
+}
+
+
+void
+show_ip_ospf_interface_sub (struct vty *vty, struct interface *ifp)
+{
+  struct ospf_neighbor *nbr;
+  int oi_count;
+  struct route_node *rn;
+  char buf[9];
+
+  oi_count = ospf_oi_count (ifp);
+  
+  /* Is interface up? */
+  if (if_is_up (ifp))
+    vty_out (vty, "%s is up, line protocol is up%s", ifp->name, VTY_NEWLINE);
+  else
+    {
+      vty_out (vty, "%s is down, line protocol is down%s", ifp->name,
+	       VTY_NEWLINE);
+
+      
+      if (oi_count == 0)
+	vty_out (vty, "  OSPF not enabled on this interface%s", VTY_NEWLINE);
+      else
+	vty_out (vty, "  OSPF is enabled, but not running on this interface%s",
+		 VTY_NEWLINE);
+      return;
+    }
+
+  /* Is interface OSPF enabled? */
+  if (oi_count == 0)
+    {
+      vty_out (vty, "  OSPF not enabled on this interface%s", VTY_NEWLINE);
+      return;
+    }
+  
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi = rn->info;
+      
+      if (oi == NULL)
+	continue;
+      
+      /* Show OSPF interface information. */
+      vty_out (vty, "  Internet Address %s/%d,",
+	       inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen);
+
+      vty_out (vty, " Area %s%s", ospf_area_desc_string (oi->area),
+	       VTY_NEWLINE);
+
+      vty_out (vty, "  Router ID %s, Network Type %s, Cost: %d%s",
+	       inet_ntoa (ospf_top->router_id), ospf_network_type_str[oi->type],
+	       oi->output_cost, VTY_NEWLINE);
+
+      vty_out (vty, "  Transmit Delay is %d sec, State %s, Priority %d%s",
+	       OSPF_IF_PARAM (oi,transmit_delay), LOOKUP (ospf_ism_state_msg, oi->state),
+	       PRIORITY (oi), VTY_NEWLINE);
+
+  /* Show DR information. */
+      if (DR (oi).s_addr == 0)
+	vty_out (vty, "  No designated router on this network%s", VTY_NEWLINE);
+      else
+	{
+	  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi));
+	  if (nbr == NULL)
+	    vty_out (vty, "  No designated router on this network%s", VTY_NEWLINE);
+	  else
+	    {
+	      vty_out (vty, "  Designated Router (ID) %s,",
+		       inet_ntoa (nbr->router_id));
+	      vty_out (vty, " Interface Address %s%s",
+		       inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE);
+	    }
+	}
+
+      /* Show BDR information. */
+      if (BDR (oi).s_addr == 0)
+	vty_out (vty, "  No backup designated router on this network%s",
+		 VTY_NEWLINE);
+      else
+	{
+	  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &BDR (oi));
+	  if (nbr == NULL)
+	    vty_out (vty, "  No backup designated router on this network%s",
+		     VTY_NEWLINE);
+	  else
+	    {
+	      vty_out (vty, "  Backup Designated Router (ID) %s,",
+		       inet_ntoa (nbr->router_id));
+	      vty_out (vty, " Interface Address %s%s",
+		       inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE);
+	    }
+	}
+      vty_out (vty, "  Timer intervals configured,");
+      vty_out (vty, " Hello %d, Dead %d, Wait %d, Retransmit %d%s",
+	       OSPF_IF_PARAM (oi, v_hello), OSPF_IF_PARAM (oi, v_wait),
+	       OSPF_IF_PARAM (oi, v_wait),
+	       OSPF_IF_PARAM (oi, retransmit_interval),
+	       VTY_NEWLINE);
+      
+      if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_ACTIVE)
+	vty_out (vty, "    Hello due in %s%s",
+		 ospf_timer_dump (oi->t_hello, buf, 9), VTY_NEWLINE);
+      else /* OSPF_IF_PASSIVE is set */
+	vty_out (vty, "    No Hellos (Passive interface)%s", VTY_NEWLINE);
+      
+      vty_out (vty, "  Neighbor Count is %d, Adjacent neighbor count is %d%s",
+	       ospf_nbr_count (oi->nbrs, 0), ospf_nbr_count (oi->nbrs, NSM_Full),
+	       VTY_NEWLINE);
+    }
+}
+
+DEFUN (show_ip_ospf_interface,
+       show_ip_ospf_interface_cmd,
+       "show ip ospf interface [INTERFACE]",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Interface information\n"
+       "Interface name\n")
+{
+  struct interface *ifp;
+  listnode node;
+
+  /* Show All Interfaces. */
+  if (argc == 0)
+    for (node = listhead (iflist); node; nextnode (node))
+      show_ip_ospf_interface_sub (vty, node->data);
+  /* Interface name is specified. */
+  else
+    {
+      if ((ifp = if_lookup_by_name (argv[0])) == NULL)
+        vty_out (vty, "No such interface name%s", VTY_NEWLINE);
+      else
+        show_ip_ospf_interface_sub (vty, ifp);
+    }
+
+  return CMD_SUCCESS;
+}
+
+void
+show_ip_ospf_neighbor_sub (struct vty *vty, struct ospf_interface *oi)
+{
+  struct route_node *rn;
+  struct ospf_neighbor *nbr;
+  char msgbuf[16];
+  char timebuf[9];
+
+  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+    if ((nbr = rn->info))
+      /* Do not show myself. */
+      if (nbr != oi->nbr_self)
+	/* Down state is not shown. */
+	if (nbr->state != NSM_Down)
+	  {
+	    ospf_nbr_state_message (nbr, msgbuf, 16);
+
+	    if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0)
+	    vty_out (vty, "%-15s %3d   %-15s %8s    ",
+		     "-", nbr->priority,
+		     msgbuf, ospf_timer_dump (nbr->t_inactivity, timebuf, 9));
+	    else
+	    vty_out (vty, "%-15s %3d   %-15s %8s    ",
+		     inet_ntoa (nbr->router_id), nbr->priority,
+		     msgbuf, ospf_timer_dump (nbr->t_inactivity, timebuf, 9));
+	    vty_out (vty, "%-15s ", inet_ntoa (nbr->src));
+	    vty_out (vty, "%-15s %5ld %5ld %5d%s",
+		     IF_NAME (oi), ospf_ls_retransmit_count (nbr),
+		     ospf_ls_request_count (nbr), ospf_db_summary_count (nbr),
+		     VTY_NEWLINE);
+	  }
+}
+
+DEFUN (show_ip_ospf_neighbor,
+       show_ip_ospf_neighbor_cmd,
+       "show ip ospf neighbor",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Neighbor list\n")
+{
+  listnode node;
+
+  if (!ospf_top)
+    {
+      vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* Show All neighbors. */
+  vty_out (vty, "%sNeighbor ID     Pri   State           Dead "
+           "Time   Address         Interface           RXmtL "
+           "RqstL DBsmL%s", VTY_NEWLINE, VTY_NEWLINE);
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+      show_ip_ospf_neighbor_sub (vty, getdata (node));
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_ospf_neighbor_all,
+       show_ip_ospf_neighbor_all_cmd,
+       "show ip ospf neighbor all",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Neighbor list\n"
+       "include down status neighbor\n")
+{
+  listnode node;
+
+  if (!ospf_top)
+    {
+      vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* Show All neighbors. */
+  vty_out (vty, "%sNeighbor ID     Pri   State           Dead "
+           "Time   Address         Interface           RXmtL "
+           "RqstL DBsmL%s", VTY_NEWLINE, VTY_NEWLINE);
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      listnode nbr_node;
+
+      show_ip_ospf_neighbor_sub (vty, oi);
+
+    /* print Down neighbor status */
+    for (nbr_node = listhead (oi->nbr_nbma); nbr_node; nextnode (nbr_node))
+      {
+	struct ospf_nbr_nbma *nbr_nbma;
+
+	nbr_nbma = getdata (nbr_node);
+
+	if (nbr_nbma->nbr == NULL
+	    || nbr_nbma->nbr->state == NSM_Down)
+	  {
+	    vty_out (vty, "%-15s %3d   %-15s %8s    ",
+		     "-", nbr_nbma->priority, "Down", "-");
+	    vty_out (vty, "%-15s %-15s %5d %5d %5d%s", 
+		     inet_ntoa (nbr_nbma->addr), IF_NAME (oi),
+		     0, 0, 0, VTY_NEWLINE);
+	  }
+      }
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_ospf_neighbor_int,
+       show_ip_ospf_neighbor_int_cmd,
+       "show ip ospf neighbor A.B.C.D",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Neighbor list\n"
+       "Interface name\n")
+{
+  struct ospf_interface *oi;
+  struct in_addr addr;
+  int ret;
+  
+  if (!ospf_top)
+    {
+      vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  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;
+    }
+
+  if ((oi = ospf_if_is_configured (&addr)) == NULL)
+    vty_out (vty, "No such interface address%s", VTY_NEWLINE);
+  else
+    {
+      vty_out (vty, "%sNeighbor ID     Pri   State           Dead "
+               "Time   Address         Interface           RXmtL "
+               "RqstL DBsmL%s", VTY_NEWLINE, VTY_NEWLINE);
+      show_ip_ospf_neighbor_sub (vty, oi);
+    }
+
+  return CMD_SUCCESS;
+}
+
+void
+show_ip_ospf_nbr_nbma_detail_sub (struct vty *vty, struct ospf_interface *oi,
+				  struct ospf_nbr_nbma *nbr_nbma)
+{
+  char timebuf[9];
+
+  /* Show neighbor ID. */
+  vty_out (vty, " Neighbor %s,", "-");
+
+  /* Show interface address. */
+  vty_out (vty, " interface address %s%s",
+	   inet_ntoa (nbr_nbma->addr), VTY_NEWLINE);
+  /* Show Area ID. */
+  vty_out (vty, "    In the area %s via interface %s%s",
+	   ospf_area_desc_string (oi->area), IF_NAME (oi), VTY_NEWLINE);
+  /* Show neighbor priority and state. */
+  vty_out (vty, "    Neighbor priority is %d, State is %s,",
+	   nbr_nbma->priority, "Down");
+  /* Show state changes. */
+  vty_out (vty, " %d state changes%s", nbr_nbma->state_change, VTY_NEWLINE);
+
+  /* Show PollInterval */
+  vty_out (vty, "    Poll interval %d%s", nbr_nbma->v_poll, VTY_NEWLINE);
+
+  /* Show poll-interval timer. */
+  vty_out (vty, "    Poll timer due in %s%s",
+	   ospf_timer_dump (nbr_nbma->t_poll, timebuf, 9), VTY_NEWLINE);
+
+  /* Show poll-interval timer thread. */
+  vty_out (vty, "    Thread Poll Timer %s%s", 
+	   nbr_nbma->t_poll != NULL ? "on" : "off", VTY_NEWLINE);
+}
+
+void
+show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi,
+				  struct ospf_neighbor *nbr)
+{
+  char timebuf[9];
+
+  /* Show neighbor ID. */
+  if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0)
+    vty_out (vty, " Neighbor %s,", "-");
+  else
+  vty_out (vty, " Neighbor %s,", inet_ntoa (nbr->router_id));
+
+  /* Show interface address. */
+  vty_out (vty, " interface address %s%s",
+	   inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE);
+  /* Show Area ID. */
+  vty_out (vty, "    In the area %s via interface %s%s",
+	   ospf_area_desc_string (oi->area), oi->ifp->name, VTY_NEWLINE);
+  /* Show neighbor priority and state. */
+  vty_out (vty, "    Neighbor priority is %d, State is %s,",
+	   nbr->priority, LOOKUP (ospf_nsm_state_msg, nbr->state));
+  /* Show state changes. */
+  vty_out (vty, " %d state changes%s", nbr->state_change, VTY_NEWLINE);
+
+  /* Show Designated Rotuer ID. */
+  vty_out (vty, "    DR is %s,", inet_ntoa (nbr->d_router));
+  /* Show Backup Designated Rotuer ID. */
+  vty_out (vty, " BDR is %s%s", inet_ntoa (nbr->bd_router), VTY_NEWLINE);
+  /* Show options. */
+  vty_out (vty, "    Options %d %s%s", nbr->options,
+	   ospf_options_dump (nbr->options), VTY_NEWLINE);
+  /* Show Router Dead interval timer. */
+  vty_out (vty, "    Dead timer due in %s%s",
+	   ospf_timer_dump (nbr->t_inactivity, timebuf, 9), VTY_NEWLINE);
+  /* Show Database Summary list. */
+  vty_out (vty, "    Database Summary List %d%s",
+	   ospf_db_summary_count (nbr), VTY_NEWLINE);
+  /* Show Link State Request list. */
+  vty_out (vty, "    Link State Request List %ld%s",
+	   ospf_ls_request_count (nbr), VTY_NEWLINE);
+  /* Show Link State Retransmission list. */
+  vty_out (vty, "    Link State Retransmission List %ld%s",
+	   ospf_ls_retransmit_count (nbr), VTY_NEWLINE);
+  /* Show inactivity timer thread. */
+  vty_out (vty, "    Thread Inactivity Timer %s%s", 
+	   nbr->t_inactivity != NULL ? "on" : "off", VTY_NEWLINE);
+  /* Show Database Description retransmission thread. */
+  vty_out (vty, "    Thread Database Description Retransmision %s%s",
+	   nbr->t_db_desc != NULL ? "on" : "off", VTY_NEWLINE);
+  /* Show Link State Request Retransmission thread. */
+  vty_out (vty, "    Thread Link State Request Retransmission %s%s",
+	   nbr->t_ls_req != NULL ? "on" : "off", VTY_NEWLINE);
+  /* Show Link State Update Retransmission thread. */
+  vty_out (vty, "    Thread Link State Update Retransmission %s%s%s",
+	   nbr->t_ls_upd != NULL ? "on" : "off", VTY_NEWLINE, VTY_NEWLINE);
+}
+
+DEFUN (show_ip_ospf_neighbor_id,
+       show_ip_ospf_neighbor_id_cmd,
+       "show ip ospf neighbor A.B.C.D",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Neighbor list\n"
+       "Neighbor ID\n")
+{
+  listnode node;
+  struct ospf_neighbor *nbr;
+  struct in_addr router_id;
+  int ret;
+
+  ret = inet_aton (argv[0], &router_id);
+  if (!ret)
+    {
+      vty_out (vty, "Please specify Neighbor ID by A.B.C.D%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+
+      if ((nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &router_id)))
+	{
+	  show_ip_ospf_neighbor_detail_sub (vty, oi, nbr);
+	  return CMD_SUCCESS;
+	}
+    }
+
+  /* Nothing to show. */
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_ospf_neighbor_detail,
+       show_ip_ospf_neighbor_detail_cmd,
+       "show ip ospf neighbor detail",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Neighbor list\n"
+       "detail of all neighbors\n")
+{
+  listnode node;
+
+  if (!ospf_top)
+    return CMD_SUCCESS;
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info))
+	  if (nbr != oi->nbr_self)
+	    if (nbr->state != NSM_Down)
+	      show_ip_ospf_neighbor_detail_sub (vty, oi, nbr);
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_ospf_neighbor_detail_all,
+       show_ip_ospf_neighbor_detail_all_cmd,
+       "show ip ospf neighbor detail all",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Neighbor list\n"
+       "detail of all neighbors\n"
+       "include down status neighbor\n")
+{
+  listnode node;
+
+  if (!ospf_top)
+    return CMD_SUCCESS;
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info))
+	  if (nbr != oi->nbr_self)
+	    if (oi->type == OSPF_IFTYPE_NBMA && nbr->state != NSM_Down)
+	      show_ip_ospf_neighbor_detail_sub (vty, oi, rn->info);
+
+      if (oi->type == OSPF_IFTYPE_NBMA)
+	{
+	  listnode nd;
+
+	  for (nd = listhead (oi->nbr_nbma); nd; nextnode (nd))
+	    {
+	      struct ospf_nbr_nbma *nbr_nbma = getdata (nd);
+	      if (nbr_nbma->nbr == NULL
+		  || nbr_nbma->nbr->state == NSM_Down)
+		show_ip_ospf_nbr_nbma_detail_sub (vty, oi, nbr_nbma);
+	    }
+	}
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_ospf_neighbor_int_detail,
+       show_ip_ospf_neighbor_int_detail_cmd,
+       "show ip ospf neighbor A.B.C.D detail",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Neighbor list\n"
+       "Interface address\n"
+       "detail of all neighbors")
+{
+  struct ospf_interface *oi;
+  struct in_addr addr;
+  int ret;
+  
+  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;
+    }
+
+  if ((oi = ospf_if_is_configured (&addr)) == NULL)
+    vty_out (vty, "No such interface address%s", VTY_NEWLINE);
+  else
+    {
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	if ((nbr = rn->info))
+	  if (nbr != oi->nbr_self)
+	    if (nbr->state != NSM_Down)
+	      show_ip_ospf_neighbor_detail_sub (vty, oi, nbr);
+    }
+
+  return CMD_SUCCESS;
+}
+
+
+/* Show functions */
+int
+show_lsa_summary (struct ospf_lsa *lsa, void *v, int self)
+{
+  struct vty *vty = (struct vty *) v;
+  struct router_lsa *rl;
+  struct summary_lsa *sl;
+  struct as_external_lsa *asel;
+  struct prefix_ipv4 p;
+
+  if (lsa != NULL)
+    /* If self option is set, check LSA self flag. */
+    if (self == 0 || IS_LSA_SELF (lsa))
+      {
+	/* LSA common part show. */
+	vty_out (vty, "%-15s ", inet_ntoa (lsa->data->id));
+	vty_out (vty, "%-15s %4d 0x%08lx 0x%04x",
+		 inet_ntoa (lsa->data->adv_router), LS_AGE (lsa),
+		 (u_long)ntohl (lsa->data->ls_seqnum), ntohs (lsa->data->checksum));
+	/* LSA specific part show. */
+	switch (lsa->data->type)
+	  {
+	  case OSPF_ROUTER_LSA:
+	    rl = (struct router_lsa *) lsa->data;
+	    vty_out (vty, " %-d", ntohs (rl->links));
+	    break;
+	  case OSPF_SUMMARY_LSA:
+	    sl = (struct summary_lsa *) lsa->data;
+
+	    p.family = AF_INET;
+	    p.prefix = sl->header.id;
+	    p.prefixlen = ip_masklen (sl->mask);
+	    apply_mask_ipv4 (&p);
+
+	    vty_out (vty, " %s/%d", inet_ntoa (p.prefix), p.prefixlen);
+	    break;
+	  case OSPF_AS_EXTERNAL_LSA:
+	    asel = (struct as_external_lsa *) lsa->data;
+
+	    p.family = AF_INET;
+	    p.prefix = asel->header.id;
+	    p.prefixlen = ip_masklen (asel->mask);
+	    apply_mask_ipv4 (&p);
+
+	    vty_out (vty, " %s %s/%d [0x%lx]",
+		     IS_EXTERNAL_METRIC (asel->e[0].tos) ? "E2" : "E1",
+		     inet_ntoa (p.prefix), p.prefixlen,
+		     (u_long)ntohl (asel->e[0].route_tag));
+	    break;
+	  case OSPF_NETWORK_LSA:
+	  case OSPF_ASBR_SUMMARY_LSA:
+#ifdef HAVE_OPAQUE_LSA
+	  case OSPF_OPAQUE_LINK_LSA:
+	  case OSPF_OPAQUE_AREA_LSA:
+	  case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+	  default:
+	    break;
+	  }
+	vty_out (vty, VTY_NEWLINE);
+      }
+
+  return 0;
+}
+
+char *show_database_desc[] =
+{
+  "unknown",
+  "Router Link States",
+  "Net Link States",
+  "Summary Link States",
+  "ASBR-Summary Link States",
+  "AS External Link States",
+#if defined  (HAVE_NSSA) || defined (HAVE_OPAQUE_LSA)
+  "Group Membership LSA",
+  "NSSA-external Link States",
+#endif /* HAVE_NSSA */
+#ifdef HAVE_OPAQUE_LSA
+  "Type-8 LSA",
+  "Link-Local Opaque-LSA",
+  "Area-Local Opaque-LSA",
+  "AS-external Opaque-LSA",
+#endif /* HAVE_OPAQUE_LSA */
+};
+
+#define SHOW_OSPF_COMMON_HEADER \
+  "Link ID         ADV Router      Age  Seq#       CkSum"
+
+char *show_database_header[] =
+{
+  "",
+  "Link ID         ADV Router      Age  Seq#       CkSum  Link count",
+  "Link ID         ADV Router      Age  Seq#       CkSum",
+  "Link ID         ADV Router      Age  Seq#       CkSum  Route",
+  "Link ID         ADV Router      Age  Seq#       CkSum",
+  "Link ID         ADV Router      Age  Seq#       CkSum  Route",
+#ifdef HAVE_NSSA
+  " --- header for Group Member ----",
+  "Link ID         ADV Router      Age  Seq#       CkSum  Route",
+#endif /* HAVE_NSSA */
+#ifdef HAVE_OPAQUE_LSA
+#ifndef HAVE_NSSA
+  " --- type-6 ---",
+  " --- type-7 ---",
+#endif /* HAVE_NSSA */
+  " --- type-8 ---",
+  "Opaque-Type/Id  ADV Router      Age  Seq#       CkSum",
+  "Opaque-Type/Id  ADV Router      Age  Seq#       CkSum",
+  "Opaque-Type/Id  ADV Router      Age  Seq#       CkSum",
+#endif /* HAVE_OPAQUE_LSA */
+};
+
+void
+show_ip_ospf_database_header (struct vty *vty, struct ospf_lsa *lsa)
+{
+  struct router_lsa *rlsa = (struct router_lsa*) lsa->data;
+
+  vty_out (vty, "  LS age: %d%s", LS_AGE (lsa), VTY_NEWLINE);
+  vty_out (vty, "  Options: %d%s", lsa->data->options, VTY_NEWLINE);
+
+  if (lsa->data->type == OSPF_ROUTER_LSA)
+    {
+      vty_out (vty, "  Flags: 0x%x" , rlsa->flags);
+
+      if (rlsa->flags)
+	vty_out (vty, " :%s%s%s%s",
+		 IS_ROUTER_LSA_BORDER (rlsa) ? " ABR" : "",
+		 IS_ROUTER_LSA_EXTERNAL (rlsa) ? " ASBR" : "",
+		 IS_ROUTER_LSA_VIRTUAL (rlsa) ? " VL-endpoint" : "",
+		 IS_ROUTER_LSA_SHORTCUT (rlsa) ? " Shortcut" : "");
+
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+  vty_out (vty, "  LS Type: %s%s",
+           LOOKUP (ospf_lsa_type_msg, lsa->data->type), VTY_NEWLINE);
+  vty_out (vty, "  Link State ID: %s %s%s", inet_ntoa (lsa->data->id),
+           LOOKUP (ospf_link_state_id_type_msg, lsa->data->type), VTY_NEWLINE);
+  vty_out (vty, "  Advertising Router: %s%s",
+           inet_ntoa (lsa->data->adv_router), VTY_NEWLINE);
+  vty_out (vty, "  LS Seq Number: %08lx%s", (u_long)ntohl (lsa->data->ls_seqnum),
+           VTY_NEWLINE);
+  vty_out (vty, "  Checksum: 0x%04x%s", ntohs (lsa->data->checksum),
+           VTY_NEWLINE);
+  vty_out (vty, "  Length: %d%s", ntohs (lsa->data->length), VTY_NEWLINE);
+}
+
+char *link_type_desc[] =
+{
+  "(null)",
+  "another Router (point-to-point)",
+  "a Transit Network",
+  "Stub Network",
+  "a Virtual Link",
+};
+
+char *link_id_desc[] =
+{
+  "(null)",
+  "Neighboring Router ID",
+  "Designated Router address",
+  "Network/subnet number",
+  "Neighboring Router ID",
+};
+
+char *link_data_desc[] =
+{
+  "(null)",
+  "Router Interface address",
+  "Router Interface address",
+  "Network Mask",
+  "Router Interface address",
+};
+
+/* Show router-LSA each Link information. */
+void
+show_ip_ospf_database_router_links (struct vty *vty,
+                                    struct router_lsa *rl)
+{
+  int len, i, type;
+
+  len = ntohs (rl->header.length) - 4;
+  for (i = 0; i < ntohs (rl->links) && len > 0; len -= 12, i++)
+    {
+      type = rl->link[i].type;
+
+      vty_out (vty, "    Link connected to: %s%s",
+	       link_type_desc[type], VTY_NEWLINE);
+      vty_out (vty, "     (Link ID) %s: %s%s", link_id_desc[type],
+	       inet_ntoa (rl->link[i].link_id), VTY_NEWLINE);
+      vty_out (vty, "     (Link Data) %s: %s%s", link_data_desc[type],
+	       inet_ntoa (rl->link[i].link_data), VTY_NEWLINE);
+      vty_out (vty, "      Number of TOS metrics: 0%s", VTY_NEWLINE);
+      vty_out (vty, "       TOS 0 Metric: %d%s",
+	       ntohs (rl->link[i].metric), VTY_NEWLINE);
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+}
+
+/* Show router-LSA detail information. */
+int
+show_router_lsa_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  if (lsa != NULL)
+    {
+      struct router_lsa *rl = (struct router_lsa *) lsa->data;
+
+      show_ip_ospf_database_header (vty, lsa);
+          
+      vty_out (vty, "   Number of Links: %d%s%s", ntohs (rl->links),
+	       VTY_NEWLINE, VTY_NEWLINE);
+
+      show_ip_ospf_database_router_links (vty, rl);
+    }
+
+  return 0;
+}
+
+/* Show network-LSA detail information. */
+int
+show_network_lsa_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  int length, i;
+
+  if (lsa != NULL)
+    {
+      struct network_lsa *nl = (struct network_lsa *) lsa->data;
+
+      show_ip_ospf_database_header (vty, lsa);
+
+      vty_out (vty, "  Network Mask: /%d%s",
+	       ip_masklen (nl->mask), VTY_NEWLINE);
+
+      length = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4;
+
+      for (i = 0; length > 0; i++, length -= 4)
+	vty_out (vty, "        Attached Router: %s%s",
+		 inet_ntoa (nl->routers[i]), VTY_NEWLINE);
+
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+
+  return 0;
+}
+
+/* Show summary-LSA detail information. */
+int
+show_summary_lsa_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  if (lsa != NULL)
+    {
+      struct summary_lsa *sl = (struct summary_lsa *) lsa->data;
+
+      show_ip_ospf_database_header (vty, lsa);
+
+      vty_out (vty, "  Network Mask: /%d%s", ip_masklen (sl->mask),
+	       VTY_NEWLINE);
+      vty_out (vty, "        TOS: 0  Metric: %d%s", GET_METRIC (sl->metric),
+	       VTY_NEWLINE);
+    }
+
+  return 0;
+}
+
+/* Show summary-ASBR-LSA detail information. */
+int
+show_summary_asbr_lsa_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  if (lsa != NULL)
+    {
+      struct summary_lsa *sl = (struct summary_lsa *) lsa->data;
+
+      show_ip_ospf_database_header (vty, lsa);
+
+      vty_out (vty, "  Network Mask: /%d%s",
+	       ip_masklen (sl->mask), VTY_NEWLINE);
+      vty_out (vty, "        TOS: 0  Metric: %d%s", GET_METRIC (sl->metric),
+	       VTY_NEWLINE);
+    }
+
+  return 0;
+}
+
+/* Show AS-external-LSA detail information. */
+int
+show_as_external_lsa_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  if (lsa != NULL)
+    {
+      struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
+
+      show_ip_ospf_database_header (vty, lsa);
+
+      vty_out (vty, "  Network Mask: /%d%s",
+	       ip_masklen (al->mask), VTY_NEWLINE);
+      vty_out (vty, "        Metric Type: %s%s",
+	       IS_EXTERNAL_METRIC (al->e[0].tos) ?
+	       "2 (Larger than any link state path)" : "1", VTY_NEWLINE);
+      vty_out (vty, "        TOS: 0%s", VTY_NEWLINE);
+      vty_out (vty, "        Metric: %d%s",
+	       GET_METRIC (al->e[0].metric), VTY_NEWLINE);
+      vty_out (vty, "        Forward Address: %s%s",
+	       inet_ntoa (al->e[0].fwd_addr), VTY_NEWLINE);
+
+      vty_out (vty, "        External Route Tag: %lu%s%s",
+	       (u_long)ntohl (al->e[0].route_tag), VTY_NEWLINE, VTY_NEWLINE);
+    }
+
+  return 0;
+}
+
+#ifdef HAVE_NSSA
+int
+show_as_external_lsa_stdvty (struct ospf_lsa *lsa)
+{
+  struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
+
+  /* show_ip_ospf_database_header (vty, lsa); */
+
+  zlog_info( "  Network Mask: /%d%s",
+	     ip_masklen (al->mask), "\n");
+  zlog_info( "        Metric Type: %s%s",
+	     IS_EXTERNAL_METRIC (al->e[0].tos) ?
+	     "2 (Larger than any link state path)" : "1", "\n");
+  zlog_info( "        TOS: 0%s", "\n");
+  zlog_info( "        Metric: %d%s",
+	     GET_METRIC (al->e[0].metric), "\n");
+  zlog_info( "        Forward Address: %s%s",
+	     inet_ntoa (al->e[0].fwd_addr), "\n");
+
+  zlog_info( "        External Route Tag: %u%s%s",
+	     ntohl (al->e[0].route_tag), "\n", "\n");
+
+  return 0;
+}
+
+/* Show AS-NSSA-LSA detail information. */
+int
+show_as_nssa_lsa_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  if (lsa != NULL)
+    {
+      struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
+
+      show_ip_ospf_database_header (vty, lsa);
+
+      vty_out (vty, "  Network Mask: /%d%s",
+	       ip_masklen (al->mask), VTY_NEWLINE);
+      vty_out (vty, "        Metric Type: %s%s",
+	       IS_EXTERNAL_METRIC (al->e[0].tos) ?
+	       "2 (Larger than any link state path)" : "1", VTY_NEWLINE);
+      vty_out (vty, "        TOS: 0%s", VTY_NEWLINE);
+      vty_out (vty, "        Metric: %d%s",
+	       GET_METRIC (al->e[0].metric), VTY_NEWLINE);
+      vty_out (vty, "        NSSA: Forward Address: %s%s",
+	       inet_ntoa (al->e[0].fwd_addr), VTY_NEWLINE);
+
+      vty_out (vty, "        External Route Tag: %u%s%s",
+	       ntohl (al->e[0].route_tag), VTY_NEWLINE, VTY_NEWLINE);
+    }
+
+  return 0;
+}
+
+#endif /* HAVE_NSSA */
+
+int
+show_func_dummy (struct vty *vty, struct ospf_lsa *lsa)
+{
+  return 0;
+}
+
+#ifdef HAVE_OPAQUE_LSA
+int
+show_opaque_lsa_detail (struct vty *vty, struct ospf_lsa *lsa)
+{
+  if (lsa != NULL)
+    {
+      show_ip_ospf_database_header (vty, lsa);
+      show_opaque_info_detail (vty, lsa);
+
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+  return 0;
+}
+#endif /* HAVE_OPAQUE_LSA */
+
+int (*show_function[])(struct vty *, struct ospf_lsa *) =
+{
+  NULL,
+  show_router_lsa_detail,
+  show_network_lsa_detail,
+  show_summary_lsa_detail,
+  show_summary_asbr_lsa_detail,
+  show_as_external_lsa_detail,
+#ifdef HAVE_NSSA
+  show_func_dummy,
+  show_as_nssa_lsa_detail,  /* almost same as external */
+#endif /* HAVE_NSSA */
+#ifdef HAVE_OPAQUE_LSA
+#ifndef HAVE_NSSA
+  show_func_dummy,
+  show_func_dummy,
+#endif /* HAVE_NSSA */
+  NULL,				/* type-8 */
+  show_opaque_lsa_detail,
+  show_opaque_lsa_detail,
+  show_opaque_lsa_detail,
+#endif /* HAVE_OPAQUE_LSA */
+};
+
+void
+show_lsa_prefix_set (struct vty *vty, struct prefix_ls *lp, struct in_addr *id,
+		     struct in_addr *adv_router)
+{
+  memset (lp, 0, sizeof (struct prefix_ls));
+  lp->family = 0;
+  if (id == NULL)
+    lp->prefixlen = 0;
+  else if (adv_router == NULL)
+    {
+      lp->prefixlen = 32;
+      lp->id = *id;
+    }
+  else
+    {
+      lp->prefixlen = 64;
+      lp->id = *id;
+      lp->adv_router = *adv_router;
+    }
+}
+
+void
+show_lsa_detail_proc (struct vty *vty, struct route_table *rt,
+		      struct in_addr *id, struct in_addr *adv_router)
+{
+  struct prefix_ls lp;
+  struct route_node *rn, *start;
+  struct ospf_lsa *lsa;
+
+  show_lsa_prefix_set (vty, &lp, id, adv_router);
+  start = route_node_get (rt, (struct prefix *) &lp);
+  if (start)
+    {
+      route_lock_node (start);
+      for (rn = start; rn; rn = route_next_until (rn, start))
+	if ((lsa = rn->info))
+	  {
+#ifdef HAVE_NSSA
+	    /* Stay away from any Local Translated Type-7 LSAs */
+	    if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+	      continue;
+#endif /* HAVE_NSSA */
+
+	    if (show_function[lsa->data->type] != NULL)
+	      show_function[lsa->data->type] (vty, lsa);
+	  }
+      route_unlock_node (start);
+    }
+}
+
+/* Show detail LSA information
+   -- if id is NULL then show all LSAs. */
+void
+show_lsa_detail (struct vty *vty, int type,
+		 struct in_addr *id, struct in_addr *adv_router)
+{
+  listnode node;
+
+  switch (type)
+    {
+    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      vty_out (vty, "                %s %s%s",
+               show_database_desc[type],
+               VTY_NEWLINE, VTY_NEWLINE);
+      show_lsa_detail_proc (vty, AS_LSDB (ospf_top, type), id, adv_router);
+      break;
+    default:
+      for (node = listhead (ospf_top->areas); node; nextnode (node))
+        {
+          struct ospf_area *area = node->data;
+          vty_out (vty, "%s                %s (Area %s)%s%s",
+                   VTY_NEWLINE, show_database_desc[type],
+                   ospf_area_desc_string (area), VTY_NEWLINE, VTY_NEWLINE);
+          show_lsa_detail_proc (vty, AREA_LSDB (area, type), id, adv_router);
+        }
+      break;
+    }
+}
+
+void
+show_lsa_detail_adv_router_proc (struct vty *vty, struct route_table *rt,
+				 struct in_addr *adv_router)
+{
+  struct route_node *rn;
+  struct ospf_lsa *lsa;
+
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((lsa = rn->info))
+      if (IPV4_ADDR_SAME (adv_router, &lsa->data->adv_router))
+	{
+#ifdef HAVE_NSSA
+	  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+	    continue;
+#endif /* HAVE_NSSA */
+	  if (show_function[lsa->data->type] != NULL)
+	    show_function[lsa->data->type] (vty, lsa);
+	}
+}
+
+/* Show detail LSA information. */
+void
+show_lsa_detail_adv_router (struct vty *vty, int type,
+			    struct in_addr *adv_router)
+{
+  listnode node;
+
+  switch (type)
+    {
+    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      vty_out (vty, "                %s %s%s",
+               show_database_desc[type],
+               VTY_NEWLINE, VTY_NEWLINE);
+      show_lsa_detail_adv_router_proc (vty, AS_LSDB (ospf_top, type),
+                                       adv_router);
+      break;
+    default:
+      for (node = listhead (ospf_top->areas); node; nextnode (node))
+        {
+          struct ospf_area *area = node->data;
+          vty_out (vty, "%s                %s (Area %s)%s%s",
+                   VTY_NEWLINE, show_database_desc[type],
+                   ospf_area_desc_string (area), VTY_NEWLINE, VTY_NEWLINE);
+          show_lsa_detail_adv_router_proc (vty, AREA_LSDB (area, type),
+                                           adv_router);
+	}
+      break;
+    }
+}
+
+void
+show_ip_ospf_database_summary (struct vty *vty, int self)
+{
+  listnode node;
+  int type;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      struct ospf_area *area = node->data;
+      for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++)
+	{
+	  switch (type)
+	    {
+	    case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+            case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+	      continue;
+	    default:
+	      break;
+	    }
+          if (ospf_lsdb_count_self (area->lsdb, type) > 0 ||
+              (!self && ospf_lsdb_count (area->lsdb, type) > 0))
+            {
+              vty_out (vty, "                %s (Area %s)%s%s",
+                       show_database_desc[type],
+		       ospf_area_desc_string (area),
+                       VTY_NEWLINE, VTY_NEWLINE);
+              vty_out (vty, "%s%s", show_database_header[type], VTY_NEWLINE);
+
+              foreach_lsa (AREA_LSDB (area, type), vty, self, show_lsa_summary);
+
+              vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	}
+    }
+
+  for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++)
+    {
+      switch (type)
+        {
+          case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+          case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+            break;;
+          default:
+            continue;
+        }
+      if (ospf_lsdb_count_self (ospf_top->lsdb, type) ||
+         (!self && ospf_lsdb_count (ospf_top->lsdb, type)))
+        {
+          vty_out (vty, "                %s%s%s",
+	       show_database_desc[type],
+	       VTY_NEWLINE, VTY_NEWLINE);
+          vty_out (vty, "%s%s", show_database_header[type],
+	       VTY_NEWLINE);
+          foreach_lsa (AS_LSDB (ospf_top, type), vty, self, show_lsa_summary);
+          vty_out (vty, "%s", VTY_NEWLINE);
+        }
+    }
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+void
+show_ip_ospf_database_maxage (struct vty *vty)
+{
+  listnode node;
+  struct ospf_lsa *lsa;
+
+  vty_out (vty, "%s                MaxAge Link States:%s%s",
+           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+
+  for (node = listhead (ospf_top->maxage_lsa); node; nextnode (node))
+    if ((lsa = node->data) != NULL)
+      {
+	vty_out (vty, "Link type: %d%s", lsa->data->type, VTY_NEWLINE);
+	vty_out (vty, "Link State ID: %s%s",
+		 inet_ntoa (lsa->data->id), VTY_NEWLINE);
+	vty_out (vty, "Advertising Router: %s%s",
+		 inet_ntoa (lsa->data->adv_router), VTY_NEWLINE);
+	vty_out (vty, "LSA lock count: %d%s", lsa->lock, VTY_NEWLINE);
+	vty_out (vty, "%s", VTY_NEWLINE);
+      }
+}
+
+#ifdef HAVE_NSSA
+#define OSPF_LSA_TYPE_NSSA_DESC      "NSSA external link state\n"
+#define OSPF_LSA_TYPE_NSSA_CMD_STR   "|nssa-external"
+#else  /* HAVE_NSSA */
+#define OSPF_LSA_TYPE_NSSA_DESC      ""
+#define OSPF_LSA_TYPE_NSSA_CMD_STR   ""
+#endif /* HAVE_NSSA */
+
+#ifdef HAVE_OPAQUE_LSA
+#define OSPF_LSA_TYPE_OPAQUE_LINK_DESC "Link local Opaque-LSA\n"
+#define OSPF_LSA_TYPE_OPAQUE_AREA_DESC "Link area Opaque-LSA\n"
+#define OSPF_LSA_TYPE_OPAQUE_AS_DESC   "Link AS Opaque-LSA\n"
+#define OSPF_LSA_TYPE_OPAQUE_CMD_STR   "|opaque-link|opaque-area|opaque-as"
+#else /* HAVE_OPAQUE_LSA */
+#define OSPF_LSA_TYPE_OPAQUE_LINK_DESC ""
+#define OSPF_LSA_TYPE_OPAQUE_AREA_DESC ""
+#define OSPF_LSA_TYPE_OPAQUE_AS_DESC   ""
+#define OSPF_LSA_TYPE_OPAQUE_CMD_STR   ""
+#endif /* HAVE_OPAQUE_LSA */
+
+#define OSPF_LSA_TYPES_CMD_STR                                                \
+    "asbr-summary|external|network|router|summary"                            \
+    OSPF_LSA_TYPE_NSSA_CMD_STR                                                \
+    OSPF_LSA_TYPE_OPAQUE_CMD_STR
+
+#define OSPF_LSA_TYPES_DESC                                                   \
+   "ASBR summary link states\n"                                               \
+   "External link states\n"                                                   \
+   "Network link states\n"                                                    \
+   "Router link states\n"                                                     \
+   "Network summary link states\n"                                            \
+   OSPF_LSA_TYPE_NSSA_DESC                                                    \
+   OSPF_LSA_TYPE_OPAQUE_LINK_DESC                                             \
+   OSPF_LSA_TYPE_OPAQUE_AREA_DESC                                             \
+   OSPF_LSA_TYPE_OPAQUE_AS_DESC     
+
+DEFUN (show_ip_ospf_database,
+       show_ip_ospf_database_cmd,
+       "show ip ospf database",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Database summary\n")
+{
+  int type, ret;
+  struct in_addr id, adv_router;
+
+  if (ospf_top == NULL)
+    return CMD_SUCCESS;
+
+  vty_out (vty, "%s       OSPF Router with ID (%s)%s%s", VTY_NEWLINE,
+           inet_ntoa (ospf_top->router_id), VTY_NEWLINE, VTY_NEWLINE);
+
+  /* Show all LSA. */
+  if (argc == 0)
+    {
+      show_ip_ospf_database_summary (vty, 0);
+      return CMD_SUCCESS;
+    }
+
+  /* Set database type to show. */
+  if (strncmp (argv[0], "r", 1) == 0)
+    type = OSPF_ROUTER_LSA;
+  else if (strncmp (argv[0], "ne", 2) == 0)
+    type = OSPF_NETWORK_LSA;
+#ifdef HAVE_NSSA
+  else if (strncmp (argv[0], "ns", 2) == 0)
+    type = OSPF_AS_NSSA_LSA;
+#endif /* HAVE_NSSA */
+  else if (strncmp (argv[0], "su", 2) == 0)
+    type = OSPF_SUMMARY_LSA;
+  else if (strncmp (argv[0], "a", 1) == 0)
+    type = OSPF_ASBR_SUMMARY_LSA;
+  else if (strncmp (argv[0], "e", 1) == 0)
+    type = OSPF_AS_EXTERNAL_LSA;
+  else if (strncmp (argv[0], "se", 2) == 0)
+    {
+      show_ip_ospf_database_summary (vty, 1);
+      return CMD_SUCCESS;
+    }
+  else if (strncmp (argv[0], "m", 1) == 0)
+    {
+      show_ip_ospf_database_maxage (vty);
+      return CMD_SUCCESS;
+    }
+#ifdef HAVE_OPAQUE_LSA
+  else if (strncmp (argv[0], "opaque-l", 8) == 0)
+    type = OSPF_OPAQUE_LINK_LSA;
+  else if (strncmp (argv[0], "opaque-ar", 9) == 0)
+    type = OSPF_OPAQUE_AREA_LSA;
+  else if (strncmp (argv[0], "opaque-as", 9) == 0)
+    type = OSPF_OPAQUE_AS_LSA;
+#endif /* HAVE_OPAQUE_LSA */
+  else
+    return CMD_WARNING;
+
+  /* `show ip ospf database LSA'. */
+  if (argc == 1)
+    show_lsa_detail (vty, type, NULL, NULL);
+  else if (argc >= 2)
+    {
+      ret = inet_aton (argv[1], &id);
+      if (!ret)
+	return CMD_WARNING;
+      
+      /* `show ip ospf database LSA ID'. */
+      if (argc == 2)
+	show_lsa_detail (vty, type, &id, NULL);
+      /* `show ip ospf database LSA ID adv-router ADV_ROUTER'. */
+      else if (argc == 3)
+	{
+	  if (strncmp (argv[2], "s", 1) == 0)
+	    adv_router = ospf_top->router_id;
+	  else
+	    {
+	      ret = inet_aton (argv[2], &adv_router);
+	      if (!ret)
+		return CMD_WARNING;
+	    }
+	  show_lsa_detail (vty, type, &id, &adv_router);
+	}
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (show_ip_ospf_database,
+       show_ip_ospf_database_type_cmd,
+       "show ip ospf database (" OSPF_LSA_TYPES_CMD_STR "|max-age|self-originate)",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Database summary\n"
+       OSPF_LSA_TYPES_DESC
+       "LSAs in MaxAge list\n"
+       "Self-originated link states\n")
+
+ALIAS (show_ip_ospf_database,
+       show_ip_ospf_database_type_id_cmd,
+       "show ip ospf database (" OSPF_LSA_TYPES_CMD_STR ") A.B.C.D",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Database summary\n"
+       OSPF_LSA_TYPES_DESC
+       "Link State ID (as an IP address)\n")
+
+ALIAS (show_ip_ospf_database,
+       show_ip_ospf_database_type_id_adv_router_cmd,
+       "show ip ospf database (" OSPF_LSA_TYPES_CMD_STR ") A.B.C.D adv-router A.B.C.D",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Database summary\n"
+       OSPF_LSA_TYPES_DESC
+       "Link State ID (as an IP address)\n"
+       "Advertising Router link states\n"
+       "Advertising Router (as an IP address)\n")
+
+ALIAS (show_ip_ospf_database,
+       show_ip_ospf_database_type_id_self_cmd,
+       "show ip ospf database (" OSPF_LSA_TYPES_CMD_STR ") A.B.C.D (self-originate|)",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Database summary\n"
+       OSPF_LSA_TYPES_DESC
+       "Link State ID (as an IP address)\n"
+       "Self-originated link states\n"
+       "\n")
+
+DEFUN (show_ip_ospf_database_type_adv_router,
+       show_ip_ospf_database_type_adv_router_cmd,
+       "show ip ospf database (" OSPF_LSA_TYPES_CMD_STR ") adv-router A.B.C.D",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Database summary\n"
+       OSPF_LSA_TYPES_DESC
+       "Advertising Router link states\n"
+       "Advertising Router (as an IP address)\n")
+{
+  int type, ret;
+  struct in_addr adv_router;
+
+  if (ospf_top == NULL)
+    return CMD_SUCCESS;
+
+  vty_out (vty, "%s       OSPF Router with ID (%s)%s%s", VTY_NEWLINE,
+           inet_ntoa (ospf_top->router_id), VTY_NEWLINE, VTY_NEWLINE);
+
+  if (argc != 2)
+    return CMD_WARNING;
+
+  /* Set database type to show. */
+  if (strncmp (argv[0], "r", 1) == 0)
+    type = OSPF_ROUTER_LSA;
+  else if (strncmp (argv[0], "ne", 2) == 0)
+    type = OSPF_NETWORK_LSA;
+#ifdef HAVE_NSSA
+  else if (strncmp (argv[0], "ns", 2) == 0)
+    type = OSPF_AS_NSSA_LSA;
+#endif /* HAVE_NSSA */
+  else if (strncmp (argv[0], "s", 1) == 0)
+    type = OSPF_SUMMARY_LSA;
+  else if (strncmp (argv[0], "a", 1) == 0)
+    type = OSPF_ASBR_SUMMARY_LSA;
+  else if (strncmp (argv[0], "e", 1) == 0)
+    type = OSPF_AS_EXTERNAL_LSA;
+#ifdef HAVE_OPAQUE_LSA
+  else if (strncmp (argv[0], "opaque-l", 8) == 0)
+    type = OSPF_OPAQUE_LINK_LSA;
+  else if (strncmp (argv[0], "opaque-ar", 9) == 0)
+    type = OSPF_OPAQUE_AREA_LSA;
+  else if (strncmp (argv[0], "opaque-as", 9) == 0)
+    type = OSPF_OPAQUE_AS_LSA;
+#endif /* HAVE_OPAQUE_LSA */
+  else
+    return CMD_WARNING;
+
+  /* `show ip ospf database LSA adv-router ADV_ROUTER'. */
+  if (strncmp (argv[1], "s", 1) == 0)
+    adv_router = ospf_top->router_id;
+  else
+    {
+      ret = inet_aton (argv[1], &adv_router);
+      if (!ret)
+	return CMD_WARNING;
+    }
+
+  show_lsa_detail_adv_router (vty, type, &adv_router);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (show_ip_ospf_database_type_adv_router,
+       show_ip_ospf_database_type_self_cmd,
+       "show ip ospf database (" OSPF_LSA_TYPES_CMD_STR ") (self-originate|)",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "Database summary\n"
+       OSPF_LSA_TYPES_DESC
+       "Self-originated link states\n")
+
+
+DEFUN (ip_ospf_authentication_args,
+       ip_ospf_authentication_args_addr_cmd,
+       "ip ospf authentication (null|message-digest) A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable authentication on this interface\n"
+       "Use null authentication\n"
+       "Use message-digest authentication\n"
+       "Address of interface")
+{
+  struct interface *ifp;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+  /* Handle null authentication */
+  if ( argv[0][0] == 'n' )
+    {
+      SET_IF_PARAM (params, auth_type);
+      params->auth_type = OSPF_AUTH_NULL;
+      return CMD_SUCCESS;
+    }
+
+  /* Handle message-digest authentication */
+  if ( argv[0][0] == 'm' )
+    {
+      SET_IF_PARAM (params, auth_type);
+      params->auth_type = OSPF_AUTH_CRYPTOGRAPHIC;
+      return CMD_SUCCESS;
+    }
+
+  vty_out (vty, "You shouldn't get here!%s", VTY_NEWLINE);
+  return CMD_WARNING;
+}
+
+ALIAS (ip_ospf_authentication_args,
+       ip_ospf_authentication_args_cmd,
+       "ip ospf authentication (null|message-digest)",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable authentication on this interface\n"
+       "Use null authentication\n"
+       "Use message-digest authentication\n")
+
+DEFUN (ip_ospf_authentication,
+       ip_ospf_authentication_addr_cmd,
+       "ip ospf authentication A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable authentication on this interface\n"
+       "Address of interface")
+{
+  struct interface *ifp;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 1)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+  
+  SET_IF_PARAM (params, auth_type);
+  params->auth_type = OSPF_AUTH_SIMPLE;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_authentication,
+       ip_ospf_authentication_cmd,
+       "ip ospf authentication",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable authentication on this interface\n")
+
+DEFUN (no_ip_ospf_authentication,
+       no_ip_ospf_authentication_addr_cmd,
+       "no ip ospf authentication A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable authentication on this interface\n"
+       "Address of interface")
+{
+  struct interface *ifp;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 1)
+    {
+      ret = inet_aton(argv[1], &addr);
+      if (!ret)
+	{
+	  vty_out (vty, "Please specify interface address by A.B.C.D%s",
+		   VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+
+      params = ospf_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  params->auth_type = OSPF_AUTH_NOTSET;
+  UNSET_IF_PARAM (params, auth_type);
+  
+  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_authentication,
+       no_ip_ospf_authentication_cmd,
+       "no ip ospf authentication",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable authentication on this interface\n")
+
+DEFUN (ip_ospf_authentication_key,
+       ip_ospf_authentication_key_addr_cmd,
+       "ip ospf authentication-key AUTH_KEY A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Authentication password (key)\n"
+       "The OSPF password (key)\n"
+       "Address of interface")
+{
+  struct interface *ifp;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+
+  memset (params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE + 1);
+  strncpy (params->auth_simple, argv[0], OSPF_AUTH_SIMPLE_SIZE);
+  SET_IF_PARAM (params, auth_simple);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_authentication_key,
+       ip_ospf_authentication_key_cmd,
+       "ip ospf authentication-key AUTH_KEY",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Authentication password (key)\n"
+       "The OSPF password (key)")
+
+ALIAS (ip_ospf_authentication_key,
+       ospf_authentication_key_cmd,
+       "ospf authentication-key AUTH_KEY",
+       "OSPF interface commands\n"
+       "Authentication password (key)\n"
+       "The OSPF password (key)")
+
+DEFUN (no_ip_ospf_authentication_key,
+       no_ip_ospf_authentication_key_addr_cmd,
+       "no ip ospf authentication-key A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Authentication password (key)\n"
+       "Address of interface")
+{
+  struct interface *ifp;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &addr);
+      if (!ret)
+	{
+	  vty_out (vty, "Please specify interface address by A.B.C.D%s",
+		   VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+
+      params = ospf_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  memset (params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE);
+  UNSET_IF_PARAM (params, auth_simple);
+  
+  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_authentication_key,
+       no_ip_ospf_authentication_key_cmd,
+       "no ip ospf authentication-key",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Authentication password (key)\n")
+
+ALIAS (no_ip_ospf_authentication_key,
+       no_ospf_authentication_key_cmd,
+       "no ospf authentication-key",
+       NO_STR
+       "OSPF interface commands\n"
+       "Authentication password (key)\n")
+
+DEFUN (ip_ospf_message_digest_key,
+       ip_ospf_message_digest_key_addr_cmd,
+       "ip ospf message-digest-key <1-255> md5 KEY A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Message digest authentication password (key)\n"
+       "Key ID\n"
+       "Use MD5 algorithm\n"
+       "The OSPF password (key)"
+       "Address of interface")
+{
+  struct interface *ifp;
+  struct crypt_key *ck;
+  u_char key_id;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 3)
+    {
+      ret = inet_aton(argv[2], &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);
+    }
+
+  key_id = strtol (argv[0], NULL, 10);
+  if (ospf_crypt_key_lookup (params->auth_crypt, key_id) != NULL)
+    {
+      vty_out (vty, "OSPF: Key %d already exists%s", key_id, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ck = ospf_crypt_key_new ();
+  ck->key_id = (u_char) key_id;
+  memset (ck->auth_key, 0, OSPF_AUTH_MD5_SIZE+1);
+  strncpy (ck->auth_key, argv[1], OSPF_AUTH_MD5_SIZE);
+
+  ospf_crypt_key_add (params->auth_crypt, ck);
+  SET_IF_PARAM (params, auth_crypt);
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_message_digest_key,
+       ip_ospf_message_digest_key_cmd,
+       "ip ospf message-digest-key <1-255> md5 KEY",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Message digest authentication password (key)\n"
+       "Key ID\n"
+       "Use MD5 algorithm\n"
+       "The OSPF password (key)")
+
+ALIAS (ip_ospf_message_digest_key,
+       ospf_message_digest_key_cmd,
+       "ospf message-digest-key <1-255> md5 KEY",
+       "OSPF interface commands\n"
+       "Message digest authentication password (key)\n"
+       "Key ID\n"
+       "Use MD5 algorithm\n"
+       "The OSPF password (key)")
+
+DEFUN (no_ip_ospf_message_digest_key,
+       no_ip_ospf_message_digest_key_addr_cmd,
+       "no ip ospf message-digest-key <1-255> A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Message digest authentication password (key)\n"
+       "Key ID\n"
+       "Address of interface")
+{
+  struct interface *ifp;
+  struct crypt_key *ck;
+  int key_id;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  params = IF_DEF_PARAMS (ifp);
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &addr);
+      if (!ret)
+	{
+	  vty_out (vty, "Please specify interface address by A.B.C.D%s",
+		   VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+
+      params = ospf_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  key_id = strtol (argv[0], NULL, 10);
+  ck = ospf_crypt_key_lookup (params->auth_crypt, key_id);
+  if (ck == NULL)
+    {
+      vty_out (vty, "OSPF: Key %d does not exist%s", key_id, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ospf_crypt_key_delete (params->auth_crypt, key_id);
+
+  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_message_digest_key,
+       no_ip_ospf_message_digest_key_cmd,
+       "no ip ospf message-digest-key <1-255>",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Message digest authentication password (key)\n"
+       "Key ID\n")
+     
+ALIAS (no_ip_ospf_message_digest_key,
+       no_ospf_message_digest_key_cmd,
+       "no ospf message-digest-key <1-255>",
+       NO_STR
+       "OSPF interface commands\n"
+       "Message digest authentication password (key)\n"
+       "Key ID\n")
+
+DEFUN (ip_ospf_cost,
+       ip_ospf_cost_addr_cmd,
+       "ip ospf cost <1-65535> A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interface cost\n"
+       "Cost\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  u_int32_t cost;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+      
+  params = IF_DEF_PARAMS (ifp);
+
+  cost = strtol (argv[0], NULL, 10);
+
+  /* cost range is <1-65535>. */
+  if (cost < 1 || cost > 65535)
+    {
+      vty_out (vty, "Interface output cost is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+  SET_IF_PARAM (params, output_cost_cmd);
+  params->output_cost_cmd = cost;
+
+  ospf_if_recalculate_output_cost (ifp);
+    
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_cost,
+       ip_ospf_cost_cmd,
+       "ip ospf cost <1-65535>",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interface cost\n"
+       "Cost")
+
+ALIAS (ip_ospf_cost,
+       ospf_cost_cmd,
+       "ospf cost <1-65535>",
+       "OSPF interface commands\n"
+       "Interface cost\n"
+       "Cost")
+
+DEFUN (no_ip_ospf_cost,
+       no_ip_ospf_cost_addr_cmd,
+       "no ip ospf cost A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interface cost\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  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_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  UNSET_IF_PARAM (params, output_cost_cmd);
+
+  if (params != IF_DEF_PARAMS (ifp))
+    {
+      ospf_free_if_params (ifp, addr);
+      ospf_if_update_params (ifp, addr);
+    }
+
+  ospf_if_recalculate_output_cost (ifp);
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_ip_ospf_cost,
+       no_ip_ospf_cost_cmd,
+       "no ip ospf cost",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interface cost\n")
+
+ALIAS (no_ip_ospf_cost,
+       no_ospf_cost_cmd,
+       "no ospf cost",
+       NO_STR
+       "OSPF interface commands\n"
+       "Interface cost\n")
+
+void
+ospf_nbr_timer_update (struct ospf_interface *oi)
+{
+  struct route_node *rn;
+  struct ospf_neighbor *nbr;
+
+  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+    if ((nbr = rn->info))
+      {
+	nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait);
+	nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval);
+	nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval);
+	nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval);
+      }
+}
+
+DEFUN (ip_ospf_dead_interval,
+       ip_ospf_dead_interval_addr_cmd,
+       "ip ospf dead-interval <1-65535> A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interval after which a neighbor is declared dead\n"
+       "Seconds\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  u_int32_t seconds;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  struct ospf_interface *oi;
+  struct route_node *rn;
+      
+  params = IF_DEF_PARAMS (ifp);
+
+  seconds = strtol (argv[0], NULL, 10);
+
+  /* dead_interval range is <1-65535>. */
+  if (seconds < 1 || seconds > 65535)
+    {
+      vty_out (vty, "Router Dead Interval is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+  SET_IF_PARAM (params, v_wait);
+  params->v_wait = seconds;
+  
+  /* Update timer values in neighbor structure. */
+  if (argc == 2)
+    {
+      oi = ospf_if_lookup_by_local_addr (ifp, addr);
+      if (oi)
+	ospf_nbr_timer_update (oi);
+    }
+  else
+    {
+      for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+	if ((oi = rn->info))
+	  ospf_nbr_timer_update (oi);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_dead_interval,
+       ip_ospf_dead_interval_cmd,
+       "ip ospf dead-interval <1-65535>",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interval after which a neighbor is declared dead\n"
+       "Seconds\n")
+
+ALIAS (ip_ospf_dead_interval,
+       ospf_dead_interval_cmd,
+       "ospf dead-interval <1-65535>",
+       "OSPF interface commands\n"
+       "Interval after which a neighbor is declared dead\n"
+       "Seconds\n")
+
+DEFUN (no_ip_ospf_dead_interval,
+       no_ip_ospf_dead_interval_addr_cmd,
+       "no ip ospf dead-interval A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interval after which a neighbor is declared dead\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  struct ospf_interface *oi;
+  struct route_node *rn;
+  
+  ifp = vty->index;
+  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_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  UNSET_IF_PARAM (params, v_wait);
+  params->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
+
+  if (params != IF_DEF_PARAMS (ifp))
+    {
+      ospf_free_if_params (ifp, addr);
+      ospf_if_update_params (ifp, addr);
+    }
+
+  /* Update timer values in neighbor structure. */
+  if (argc == 1)
+    {
+      oi = ospf_if_lookup_by_local_addr (ifp, addr);
+      if (oi)
+	ospf_nbr_timer_update (oi);
+    }
+  else
+    {
+      for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+	if ((oi = rn->info))
+	  ospf_nbr_timer_update (oi);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_ip_ospf_dead_interval,
+       no_ip_ospf_dead_interval_cmd,
+       "no ip ospf dead-interval",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Interval after which a neighbor is declared dead\n")
+
+ALIAS (no_ip_ospf_dead_interval,
+       no_ospf_dead_interval_cmd,
+       "no ospf dead-interval",
+       NO_STR
+       "OSPF interface commands\n"
+       "Interval after which a neighbor is declared dead\n")
+
+DEFUN (ip_ospf_hello_interval,
+       ip_ospf_hello_interval_addr_cmd,
+       "ip ospf hello-interval <1-65535> A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between HELLO packets\n"
+       "Seconds\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  u_int32_t seconds;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+      
+  params = IF_DEF_PARAMS (ifp);
+
+  seconds = strtol (argv[0], NULL, 10);
+  
+  /* HelloInterval range is <1-65535>. */
+  if (seconds < 1 || seconds > 65535)
+    {
+      vty_out (vty, "Hello Interval is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+  SET_IF_PARAM (params, v_hello); 
+  params->v_hello = seconds;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_hello_interval,
+       ip_ospf_hello_interval_cmd,
+       "ip ospf hello-interval <1-65535>",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between HELLO packets\n"
+       "Seconds\n")
+
+ALIAS (ip_ospf_hello_interval,
+       ospf_hello_interval_cmd,
+       "ospf hello-interval <1-65535>",
+       "OSPF interface commands\n"
+       "Time between HELLO packets\n"
+       "Seconds\n")
+
+DEFUN (no_ip_ospf_hello_interval,
+       no_ip_ospf_hello_interval_addr_cmd,
+       "no ip ospf hello-interval A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between HELLO packets\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  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_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  UNSET_IF_PARAM (params, v_hello);
+  params->v_hello = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
+
+  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_hello_interval,
+       no_ip_ospf_hello_interval_cmd,
+       "no ip ospf hello-interval",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between HELLO packets\n")
+
+ALIAS (no_ip_ospf_hello_interval,
+       no_ospf_hello_interval_cmd,
+       "no ospf hello-interval",
+       NO_STR
+       "OSPF interface commands\n"
+       "Time between HELLO packets\n")
+
+DEFUN (ip_ospf_network,
+       ip_ospf_network_cmd,
+       "ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Network type\n"
+       "Specify OSPF broadcast multi-access network\n"
+       "Specify OSPF NBMA network\n"
+       "Specify OSPF point-to-multipoint network\n"
+       "Specify OSPF point-to-point network\n")
+{
+  struct interface *ifp = vty->index;
+  int old_type = IF_DEF_PARAMS (ifp)->type;
+  struct route_node *rn;
+  
+  if (strncmp (argv[0], "b", 1) == 0)
+    IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
+  else if (strncmp (argv[0], "n", 1) == 0)
+    IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_NBMA;
+  else if (strncmp (argv[0], "point-to-m", 10) == 0)
+    IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
+  else if (strncmp (argv[0], "point-to-p", 10) == 0)
+    IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOPOINT;
+
+  if (IF_DEF_PARAMS (ifp)->type == old_type)
+    return CMD_SUCCESS;
+
+  SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
+
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi = rn->info;
+
+      if (!oi)
+	continue;
+      
+      oi->type = IF_DEF_PARAMS (ifp)->type;
+      
+      if (oi->state > ISM_Down)
+	{
+	  OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
+	  OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceUp);
+	}
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_network,
+       ospf_network_cmd,
+       "ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)",
+       "OSPF interface commands\n"
+       "Network type\n"
+       "Specify OSPF broadcast multi-access network\n"
+       "Specify OSPF NBMA network\n"
+       "Specify OSPF point-to-multipoint network\n"
+       "Specify OSPF point-to-point network\n")
+
+DEFUN (no_ip_ospf_network,
+       no_ip_ospf_network_cmd,
+       "no ip ospf network",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Network type\n")
+{
+  struct interface *ifp = vty->index;
+  int old_type = IF_DEF_PARAMS (ifp)->type;
+  struct route_node *rn;
+
+  IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
+
+  if (IF_DEF_PARAMS (ifp)->type == old_type)
+    return CMD_SUCCESS;
+
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi = rn->info;
+
+      if (!oi)
+	continue;
+      
+      oi->type = IF_DEF_PARAMS (ifp)->type;
+      
+      if (oi->state > ISM_Down)
+	{
+	  OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
+	  OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceUp);
+	}
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_ip_ospf_network,
+       no_ospf_network_cmd,
+       "no ospf network",
+       NO_STR
+       "OSPF interface commands\n"
+       "Network type\n")
+
+DEFUN (ip_ospf_priority,
+       ip_ospf_priority_addr_cmd,
+       "ip ospf priority <0-255> A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Router priority\n"
+       "Priority\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  u_int32_t priority;
+  struct route_node *rn;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+      
+  params = IF_DEF_PARAMS (ifp);
+
+  priority = strtol (argv[0], NULL, 10);
+  
+  /* Router Priority range is <0-255>. */
+  if (priority < 0 || priority > 255)
+    {
+      vty_out (vty, "Router Priority is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+  
+  SET_IF_PARAM (params, priority);
+  params->priority = priority;
+
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi = rn->info;
+      
+      if (!oi)
+	continue;
+      
+
+      if (PRIORITY (oi) != OSPF_IF_PARAM (oi, priority))
+	{
+	  PRIORITY (oi) = OSPF_IF_PARAM (oi, priority);
+	  OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+	}
+    }
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_priority,
+       ip_ospf_priority_cmd,
+       "ip ospf priority <0-255>",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Router priority\n"
+       "Priority\n")
+
+ALIAS (ip_ospf_priority,
+       ospf_priority_cmd,
+       "ospf priority <0-255>",
+       "OSPF interface commands\n"
+       "Router priority\n"
+       "Priority\n")
+
+DEFUN (no_ip_ospf_priority,
+       no_ip_ospf_priority_addr_cmd,
+       "no ip ospf priority A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Router priority\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct route_node *rn;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  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_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  UNSET_IF_PARAM (params, priority);
+  params->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
+
+  if (params != IF_DEF_PARAMS (ifp))
+    {
+      ospf_free_if_params (ifp, addr);
+      ospf_if_update_params (ifp, addr);
+    }
+  
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi = rn->info;
+      
+      if (!oi)
+	continue;
+      
+      
+      if (PRIORITY (oi) != OSPF_IF_PARAM (oi, priority))
+	{
+	  PRIORITY (oi) = OSPF_IF_PARAM (oi, priority);
+	  OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+	}
+    }
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_ip_ospf_priority,
+       no_ip_ospf_priority_cmd,
+       "no ip ospf priority",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Router priority\n")
+
+ALIAS (no_ip_ospf_priority,
+       no_ospf_priority_cmd,
+       "no ospf priority",
+       NO_STR
+       "OSPF interface commands\n"
+       "Router priority\n")
+
+DEFUN (ip_ospf_retransmit_interval,
+       ip_ospf_retransmit_interval_addr_cmd,
+       "ip ospf retransmit-interval <3-65535> A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between retransmitting lost link state advertisements\n"
+       "Seconds\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  u_int32_t seconds;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+      
+  params = IF_DEF_PARAMS (ifp);
+  seconds = strtol (argv[0], NULL, 10);
+
+  /* Retransmit Interval range is <3-65535>. */
+  if (seconds < 3 || seconds > 65535)
+    {
+      vty_out (vty, "Retransmit Interval is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+  SET_IF_PARAM (params, retransmit_interval);
+  params->retransmit_interval = seconds;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_retransmit_interval,
+       ip_ospf_retransmit_interval_cmd,
+       "ip ospf retransmit-interval <3-65535>",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between retransmitting lost link state advertisements\n"
+       "Seconds\n")
+
+ALIAS (ip_ospf_retransmit_interval,
+       ospf_retransmit_interval_cmd,
+       "ospf retransmit-interval <3-65535>",
+       "OSPF interface commands\n"
+       "Time between retransmitting lost link state advertisements\n"
+       "Seconds\n")
+
+DEFUN (no_ip_ospf_retransmit_interval,
+       no_ip_ospf_retransmit_interval_addr_cmd,
+       "no ip ospf retransmit-interval A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between retransmitting lost link state advertisements\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  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_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  UNSET_IF_PARAM (params, retransmit_interval);
+  params->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
+
+  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_retransmit_interval,
+       no_ip_ospf_retransmit_interval_cmd,
+       "no ip ospf retransmit-interval",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Time between retransmitting lost link state advertisements\n")
+
+ALIAS (no_ip_ospf_retransmit_interval,
+       no_ospf_retransmit_interval_cmd,
+       "no ospf retransmit-interval",
+       NO_STR
+       "OSPF interface commands\n"
+       "Time between retransmitting lost link state advertisements\n")
+
+DEFUN (ip_ospf_transmit_delay,
+       ip_ospf_transmit_delay_addr_cmd,
+       "ip ospf transmit-delay <1-65535> A.B.C.D",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Link state transmit delay\n"
+       "Seconds\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  u_int32_t seconds;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+      
+  params = IF_DEF_PARAMS (ifp);
+  seconds = strtol (argv[0], NULL, 10);
+
+  /* Transmit Delay range is <1-65535>. */
+  if (seconds < 1 || seconds > 65535)
+    {
+      vty_out (vty, "Transmit Delay is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc == 2)
+    {
+      ret = inet_aton(argv[1], &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);
+    }
+
+  SET_IF_PARAM (params, transmit_delay); 
+  params->transmit_delay = seconds;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (ip_ospf_transmit_delay,
+       ip_ospf_transmit_delay_cmd,
+       "ip ospf transmit-delay <1-65535>",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Link state transmit delay\n"
+       "Seconds\n")
+
+ALIAS (ip_ospf_transmit_delay,
+       ospf_transmit_delay_cmd,
+       "ospf transmit-delay <1-65535>",
+       "OSPF interface commands\n"
+       "Link state transmit delay\n"
+       "Seconds\n")
+
+DEFUN (no_ip_ospf_transmit_delay,
+       no_ip_ospf_transmit_delay_addr_cmd,
+       "no ip ospf transmit-delay A.B.C.D",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Link state transmit delay\n"
+       "Address of interface")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr addr;
+  int ret;
+  struct ospf_if_params *params;
+  
+  ifp = vty->index;
+  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_lookup_if_params (ifp, addr);
+      if (params == NULL)
+	return CMD_SUCCESS;
+    }
+
+  UNSET_IF_PARAM (params, transmit_delay);
+  params->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
+
+  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_transmit_delay,
+       no_ip_ospf_transmit_delay_cmd,
+       "no ip ospf transmit-delay",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Link state transmit delay\n")
+
+ALIAS (no_ip_ospf_transmit_delay,
+       no_ospf_transmit_delay_cmd,
+       "no ospf transmit-delay",
+       NO_STR
+       "OSPF interface commands\n"
+       "Link state transmit delay\n")
+
+
+DEFUN (ospf_redistribute_source_metric_type,
+       ospf_redistribute_source_metric_type_routemap_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric <0-16777214> metric-type (1|2) route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int source;
+  int type = -1;
+  int metric = -1;
+
+  /* Get distribute source. */
+  if (!str2distribute_source (argv[0], &source))
+    return CMD_WARNING;
+
+  /* Get metric value. */
+  if (argc >= 2)
+    if (!str2metric (argv[1], &metric))
+      return CMD_WARNING;
+
+  /* Get metric type. */
+  if (argc >= 3)
+    if (!str2metric_type (argv[2], &type))
+      return CMD_WARNING;
+
+  if (argc == 4)
+    ospf_routemap_set (source, argv[3]);
+  else
+    ospf_routemap_unset (source);
+  
+  return ospf_redistribute_set (source, type, metric);
+}
+
+ALIAS (ospf_redistribute_source_metric_type,
+       ospf_redistribute_source_metric_type_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric <0-16777214> metric-type (1|2)",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n")
+
+ALIAS (ospf_redistribute_source_metric_type,
+       ospf_redistribute_source_metric_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric <0-16777214>",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n")
+
+DEFUN (ospf_redistribute_source_type_metric,
+       ospf_redistribute_source_type_metric_routemap_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric <0-16777214> route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int source;
+  int type = -1;
+  int metric = -1;
+
+  /* Get distribute source. */
+  if (!str2distribute_source (argv[0], &source))
+    return CMD_WARNING;
+
+  /* Get metric value. */
+  if (argc >= 2)
+    if (!str2metric_type (argv[1], &type))
+      return CMD_WARNING;
+
+  /* Get metric type. */
+  if (argc >= 3)
+    if (!str2metric (argv[2], &metric))
+      return CMD_WARNING;
+
+  if (argc == 4)
+    ospf_routemap_set (source, argv[3]);
+  else
+    ospf_routemap_unset (source);
+
+  return ospf_redistribute_set (source, type, metric);
+}
+
+ALIAS (ospf_redistribute_source_type_metric,
+       ospf_redistribute_source_type_metric_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric <0-16777214>",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n")
+
+ALIAS (ospf_redistribute_source_type_metric,
+       ospf_redistribute_source_type_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2)",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n")
+
+ALIAS (ospf_redistribute_source_type_metric,
+       ospf_redistribute_source_cmd,
+       "redistribute (kernel|connected|static|rip|bgp)",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n")
+
+DEFUN (ospf_redistribute_source_metric_routemap,
+       ospf_redistribute_source_metric_routemap_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric <0-16777214> route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "Metric for redistributed routes\n"
+       "OSPF default metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int source;
+  int metric = -1;
+
+  /* Get distribute source. */
+  if (!str2distribute_source (argv[0], &source))
+    return CMD_WARNING;
+
+  /* Get metric value. */
+  if (argc >= 2)
+    if (!str2metric (argv[1], &metric))
+      return CMD_WARNING;
+
+  if (argc == 3)
+    ospf_routemap_set (source, argv[2]);
+  else
+    ospf_routemap_unset (source);
+  
+  return ospf_redistribute_set (source, -1, metric);
+}
+
+DEFUN (ospf_redistribute_source_type_routemap,
+       ospf_redistribute_source_type_routemap_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "OSPF exterior metric type for redistributed routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int source;
+  int type = -1;
+
+  /* Get distribute source. */
+  if (!str2distribute_source (argv[0], &source))
+    return CMD_WARNING;
+
+  /* Get metric value. */
+  if (argc >= 2)
+    if (!str2metric_type (argv[1], &type))
+      return CMD_WARNING;
+
+  if (argc == 3)
+    ospf_routemap_set (source, argv[2]);
+  else
+    ospf_routemap_unset (source);
+
+  return ospf_redistribute_set (source, type, -1);
+}
+
+DEFUN (ospf_redistribute_source_routemap,
+       ospf_redistribute_source_routemap_cmd,
+       "redistribute (kernel|connected|static|rip|bgp) route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int source;
+
+  /* Get distribute source. */
+  if (!str2distribute_source (argv[0], &source))
+    return CMD_WARNING;
+
+  if (argc == 2)
+    ospf_routemap_set (source, argv[1]);
+  else
+    ospf_routemap_unset (source);
+
+  return ospf_redistribute_set (source, -1, -1);
+}
+
+DEFUN (no_ospf_redistribute_source,
+       no_ospf_redistribute_source_cmd,
+       "no redistribute (kernel|connected|static|rip|bgp)",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n")
+{
+  int source;
+
+  if (!str2distribute_source (argv[0], &source))
+    return CMD_WARNING;
+
+  ospf_routemap_unset (source);
+  return ospf_redistribute_unset (source);
+}
+
+DEFUN (ospf_distribute_list_out,
+       ospf_distribute_list_out_cmd,
+       "distribute-list WORD out (kernel|connected|static|rip|bgp)",
+       "Filter networks in routing updates\n"
+       "Access-list name\n"
+       OUT_STR
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n")
+{
+  int source;
+
+  /* Get distribute source. */
+  if (!str2distribute_source (argv[1], &source))
+    return CMD_WARNING;
+
+  return ospf_distribute_list_out_set (source, argv[0]);
+}
+
+DEFUN (no_ospf_distribute_list_out,
+       no_ospf_distribute_list_out_cmd,
+       "no distribute-list WORD out (kernel|connected|static|rip|bgp)",
+       NO_STR
+       "Filter networks in routing updates\n"
+       "Access-list name\n"
+       OUT_STR
+       "Kernel routes\n"
+       "Connected\n"
+       "Static routes\n"
+       "Routing Information Protocol (RIP)\n"
+       "Border Gateway Protocol (BGP)\n")
+{
+  int source;
+
+  if (!str2distribute_source (argv[1], &source))
+    return CMD_WARNING;
+
+  return ospf_distribute_list_out_unset (source, argv[0]);
+}
+
+/* Default information originate. */
+DEFUN (ospf_default_information_originate_metric_type_routemap,
+       ospf_default_information_originate_metric_type_routemap_cmd,
+       "default-information originate metric <0-16777214> metric-type (1|2) route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type = -1;
+  int metric = -1;
+
+  /* Get metric value. */
+  if (argc >= 1)
+    if (!str2metric (argv[0], &metric))
+      return CMD_WARNING;
+
+  /* Get metric type. */
+  if (argc >= 2)
+    if (!str2metric_type (argv[1], &type))
+      return CMD_WARNING;
+
+  if (argc == 3)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[2]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ZEBRA, type, metric);
+}
+
+ALIAS (ospf_default_information_originate_metric_type_routemap,
+       ospf_default_information_originate_metric_type_cmd,
+       "default-information originate metric <0-16777214> metric-type (1|2)",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n")
+
+ALIAS (ospf_default_information_originate_metric_type_routemap,
+       ospf_default_information_originate_metric_cmd,
+       "default-information originate metric <0-16777214>",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n")
+
+ALIAS (ospf_default_information_originate_metric_type_routemap,
+       ospf_default_information_originate_cmd,
+       "default-information originate",
+       "Control distribution of default information\n"
+       "Distribute a default route\n")
+
+/* Default information originate. */
+DEFUN (ospf_default_information_originate_metric_routemap,
+       ospf_default_information_originate_metric_routemap_cmd,
+       "default-information originate metric <0-16777214> route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int metric = -1;
+
+  /* Get metric value. */
+  if (argc >= 1)
+    if (!str2metric (argv[0], &metric))
+      return CMD_WARNING;
+
+  if (argc == 2)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[1]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ZEBRA, -1, metric);
+}
+
+/* Default information originate. */
+DEFUN (ospf_default_information_originate_routemap,
+       ospf_default_information_originate_routemap_cmd,
+       "default-information originate route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  if (argc == 1)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[0]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ZEBRA, -1, -1);
+}
+
+DEFUN (ospf_default_information_originate_type_metric_routemap,
+       ospf_default_information_originate_type_metric_routemap_cmd,
+       "default-information originate metric-type (1|2) metric <0-16777214> route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type = -1;
+  int metric = -1;
+
+  /* Get metric type. */
+  if (argc >= 1)
+    if (!str2metric_type (argv[0], &type))
+      return CMD_WARNING;
+
+  /* Get metric value. */
+  if (argc >= 2)
+    if (!str2metric (argv[1], &metric))
+      return CMD_WARNING;
+
+  if (argc == 3)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[2]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ZEBRA, type, metric);
+}
+
+ALIAS (ospf_default_information_originate_type_metric_routemap,
+       ospf_default_information_originate_type_metric_cmd,
+       "default-information originate metric-type (1|2) metric <0-16777214>",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "OSPF default metric\n"
+       "OSPF metric\n")
+
+ALIAS (ospf_default_information_originate_type_metric_routemap,
+       ospf_default_information_originate_type_cmd,
+       "default-information originate metric-type (1|2)",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n")
+
+DEFUN (ospf_default_information_originate_type_routemap,
+       ospf_default_information_originate_type_routemap_cmd,
+       "default-information originate metric-type (1|2) route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type = -1;
+
+  /* Get metric type. */
+  if (argc >= 1)
+    if (!str2metric_type (argv[0], &type))
+      return CMD_WARNING;
+
+  if (argc == 2)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[1]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ZEBRA, type, -1);
+}
+
+DEFUN (ospf_default_information_originate_always_metric_type_routemap,
+       ospf_default_information_originate_always_metric_type_routemap_cmd,
+       "default-information originate always metric <0-16777214> metric-type (1|2) route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type = -1;
+  int metric = -1;
+
+  /* Get metric value. */
+  if (argc >= 1)
+    if (!str2metric (argv[0], &metric))
+      return CMD_WARNING;
+
+  /* Get metric type. */
+  if (argc >= 2)
+    if (!str2metric_type (argv[1], &type))
+      return CMD_WARNING;
+
+  if (argc == 3)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[2]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ALWAYS,
+					type, metric);
+}
+
+ALIAS (ospf_default_information_originate_always_metric_type_routemap,
+       ospf_default_information_originate_always_metric_type_cmd,
+       "default-information originate always metric <0-16777214> metric-type (1|2)",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n")
+
+ALIAS (ospf_default_information_originate_always_metric_type_routemap,
+       ospf_default_information_originate_always_metric_cmd,
+       "default-information originate always metric <0-16777214>",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "OSPF metric type for default routes\n")
+
+ALIAS (ospf_default_information_originate_always_metric_type_routemap,
+       ospf_default_information_originate_always_cmd,
+       "default-information originate always",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n")
+
+DEFUN (ospf_default_information_originate_always_metric_routemap,
+       ospf_default_information_originate_always_metric_routemap_cmd,
+       "default-information originate always metric <0-16777214> route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int metric = -1;
+
+  /* Get metric value. */
+  if (argc >= 1)
+    if (!str2metric (argv[0], &metric))
+      return CMD_WARNING;
+
+  if (argc == 2)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[1]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ALWAYS, -1, metric);
+}
+
+DEFUN (ospf_default_information_originate_always_routemap,
+       ospf_default_information_originate_always_routemap_cmd,
+       "default-information originate always route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  if (argc == 1)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[0]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ALWAYS, -1, -1);
+}
+
+DEFUN (ospf_default_information_originate_always_type_metric_routemap,
+       ospf_default_information_originate_always_type_metric_routemap_cmd,
+       "default-information originate always metric-type (1|2) metric <0-16777214> route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "OSPF default metric\n"
+       "OSPF metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type = -1;
+  int metric = -1;
+
+  /* Get metric type. */
+  if (argc >= 1)
+    if (!str2metric_type (argv[0], &type))
+      return CMD_WARNING;
+
+  /* Get metric value. */
+  if (argc >= 2)
+    if (!str2metric (argv[1], &metric))
+      return CMD_WARNING;
+
+  if (argc == 3)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[2]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ALWAYS,
+					type, metric);
+}
+
+ALIAS (ospf_default_information_originate_always_type_metric_routemap,
+       ospf_default_information_originate_always_type_metric_cmd,
+       "default-information originate always metric-type (1|2) metric <0-16777214>",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "OSPF default metric\n"
+       "OSPF metric\n")
+
+ALIAS (ospf_default_information_originate_always_type_metric_routemap,
+       ospf_default_information_originate_always_type_cmd,
+       "default-information originate always metric-type (1|2)",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n")
+
+DEFUN (ospf_default_information_originate_always_type_routemap,
+       ospf_default_information_originate_always_type_routemap_cmd,
+       "default-information originate always metric-type (1|2) route-map WORD",
+       "Control distribution of default information\n"
+       "Distribute a default route\n"
+       "Always advertise default route\n"
+       "OSPF metric type for default routes\n"
+       "Set OSPF External Type 1 metrics\n"
+       "Set OSPF External Type 2 metrics\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type = -1;
+
+  /* Get metric type. */
+  if (argc >= 1)
+    if (!str2metric_type (argv[0], &type))
+      return CMD_WARNING;
+
+  if (argc == 2)
+    ospf_routemap_set (DEFAULT_ROUTE, argv[1]);
+  else
+    ospf_routemap_unset (DEFAULT_ROUTE);
+
+  return ospf_redistribute_default_set (DEFAULT_ORIGINATE_ALWAYS,
+					type, -1);
+}
+
+DEFUN (no_ospf_default_information_originate,
+       no_ospf_default_information_originate_cmd,
+       "no default-information originate",
+       NO_STR
+       "Control distribution of default information\n"
+       "Distribute a default route\n")
+{
+  struct prefix_ipv4 p;
+  struct in_addr nexthop;
+    
+  p.family = AF_INET;
+  p.prefix.s_addr = 0;
+  p.prefixlen = 0;
+
+  ospf_external_lsa_flush (DEFAULT_ROUTE, &p, 0, nexthop);
+
+  if (EXTERNAL_INFO (DEFAULT_ROUTE)) {
+    ospf_external_info_delete (DEFAULT_ROUTE, p);
+    route_table_finish (EXTERNAL_INFO (DEFAULT_ROUTE));
+    EXTERNAL_INFO (DEFAULT_ROUTE) = NULL;
+  }
+
+  ospf_routemap_unset (DEFAULT_ROUTE);
+  return ospf_redistribute_default_unset ();
+}
+
+DEFUN (ospf_default_metric,
+       ospf_default_metric_cmd,
+       "default-metric <0-16777214>",
+       "Set metric of redistributed routes\n"
+       "Default metric\n")
+{
+  int metric = -1;
+
+  if (!str2metric (argv[0], &metric))
+    return CMD_WARNING;
+
+  ospf_top->default_metric = metric;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_default_metric,
+       no_ospf_default_metric_cmd,
+       "no default-metric",
+       NO_STR
+       "Set metric of redistributed routes\n")
+{
+  ospf_top->default_metric = -1;
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_ospf_default_metric,
+       no_ospf_default_metric_val_cmd,
+       "no default-metric <0-16777214>",
+       NO_STR
+       "Set metric of redistributed routes\n"
+       "Default metric\n")
+
+DEFUN (ospf_distance,
+       ospf_distance_cmd,
+       "distance <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n")
+{
+  ospf_top->distance_all = atoi (argv[0]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_distance,
+       no_ospf_distance_cmd,
+       "no distance <1-255>",
+       NO_STR
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n")
+{
+  ospf_top->distance_all = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_distance_ospf,
+       no_ospf_distance_ospf_cmd,
+       "no distance ospf",
+       NO_STR
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "OSPF Distance\n")
+{
+  ospf_top->distance_intra = 0;
+  ospf_top->distance_inter = 0;
+  ospf_top->distance_external = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_intra,
+       ospf_distance_ospf_intra_cmd,
+       "distance ospf intra-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n")
+{
+  ospf_top->distance_intra = atoi (argv[0]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_intra_inter,
+       ospf_distance_ospf_intra_inter_cmd,
+       "distance ospf intra-area <1-255> inter-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n")
+{
+  ospf_top->distance_intra = atoi (argv[0]);
+  ospf_top->distance_inter = atoi (argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_intra_external,
+       ospf_distance_ospf_intra_external_cmd,
+       "distance ospf intra-area <1-255> external <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n"
+       "External routes\n"
+       "Distance for external routes\n")
+{
+  ospf_top->distance_intra = atoi (argv[0]);
+  ospf_top->distance_external = atoi (argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_intra_inter_external,
+       ospf_distance_ospf_intra_inter_external_cmd,
+       "distance ospf intra-area <1-255> inter-area <1-255> external <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n"
+       "External routes\n"
+       "Distance for external routes\n")
+{
+  ospf_top->distance_intra = atoi (argv[0]);
+  ospf_top->distance_inter = atoi (argv[1]);
+  ospf_top->distance_external = atoi (argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_intra_external_inter,
+       ospf_distance_ospf_intra_external_inter_cmd,
+       "distance ospf intra-area <1-255> external <1-255> inter-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n"
+       "External routes\n"
+       "Distance for external routes\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n")
+{
+  ospf_top->distance_intra = atoi (argv[0]);
+  ospf_top->distance_external = atoi (argv[1]);
+  ospf_top->distance_inter = atoi (argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_inter,
+       ospf_distance_ospf_inter_cmd,
+       "distance ospf inter-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n")
+{
+  ospf_top->distance_inter = atoi (argv[0]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_inter_intra,
+       ospf_distance_ospf_inter_intra_cmd,
+       "distance ospf inter-area <1-255> intra-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n")
+{
+  ospf_top->distance_inter = atoi (argv[0]);
+  ospf_top->distance_intra = atoi (argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_inter_external,
+       ospf_distance_ospf_inter_external_cmd,
+       "distance ospf inter-area <1-255> external <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n"
+       "External routes\n"
+       "Distance for external routes\n")
+{
+  ospf_top->distance_inter = atoi (argv[0]);
+  ospf_top->distance_external = atoi (argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_inter_intra_external,
+       ospf_distance_ospf_inter_intra_external_cmd,
+       "distance ospf inter-area <1-255> intra-area <1-255> external <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n"
+       "External routes\n"
+       "Distance for external routes\n")
+{
+  ospf_top->distance_inter = atoi (argv[0]);
+  ospf_top->distance_intra = atoi (argv[1]);
+  ospf_top->distance_external = atoi (argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_inter_external_intra,
+       ospf_distance_ospf_inter_external_intra_cmd,
+       "distance ospf inter-area <1-255> external <1-255> intra-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n"
+       "External routes\n"
+       "Distance for external routes\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n")
+{
+  ospf_top->distance_inter = atoi (argv[0]);
+  ospf_top->distance_external = atoi (argv[1]);
+  ospf_top->distance_intra = atoi (argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_external,
+       ospf_distance_ospf_external_cmd,
+       "distance ospf external <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "External routes\n"
+       "Distance for external routes\n")
+{
+  ospf_top->distance_external = atoi (argv[0]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_external_intra,
+       ospf_distance_ospf_external_intra_cmd,
+       "distance ospf external <1-255> intra-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "External routes\n"
+       "Distance for external routes\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n")
+{
+  ospf_top->distance_external = atoi (argv[0]);
+  ospf_top->distance_intra = atoi (argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_external_inter,
+       ospf_distance_ospf_external_inter_cmd,
+       "distance ospf external <1-255> inter-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "External routes\n"
+       "Distance for external routes\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n")
+{
+  ospf_top->distance_external = atoi (argv[0]);
+  ospf_top->distance_inter = atoi (argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_external_intra_inter,
+       ospf_distance_ospf_external_intra_inter_cmd,
+       "distance ospf external <1-255> intra-area <1-255> inter-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "External routes\n"
+       "Distance for external routes\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n")
+{
+  ospf_top->distance_external = atoi (argv[0]);
+  ospf_top->distance_intra = atoi (argv[1]);
+  ospf_top->distance_inter = atoi (argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_ospf_external_inter_intra,
+       ospf_distance_ospf_external_inter_intra_cmd,
+       "distance ospf external <1-255> inter-area <1-255> intra-area <1-255>",
+       "Define an administrative distance\n"
+       "OSPF Administrative distance\n"
+       "External routes\n"
+       "Distance for external routes\n"
+       "Inter-area routes\n"
+       "Distance for inter-area routes\n"
+       "Intra-area routes\n"
+       "Distance for intra-area routes\n")
+{
+  ospf_top->distance_external = atoi (argv[0]);
+  ospf_top->distance_inter = atoi (argv[1]);
+  ospf_top->distance_intra = atoi (argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_source,
+       ospf_distance_source_cmd,
+       "distance <1-255> A.B.C.D/M",
+       "Administrative distance\n"
+       "Distance value\n"
+       "IP source prefix\n")
+{
+  ospf_distance_set (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_distance_source,
+       no_ospf_distance_source_cmd,
+       "no distance <1-255> A.B.C.D/M",
+       NO_STR
+       "Administrative distance\n"
+       "Distance value\n"
+       "IP source prefix\n")
+{
+  ospf_distance_unset (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf_distance_source_access_list,
+       ospf_distance_source_access_list_cmd,
+       "distance <1-255> A.B.C.D/M WORD",
+       "Administrative distance\n"
+       "Distance value\n"
+       "IP source prefix\n"
+       "Access list name\n")
+{
+  ospf_distance_set (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_distance_source_access_list,
+       no_ospf_distance_source_access_list_cmd,
+       "no distance <1-255> A.B.C.D/M WORD",
+       NO_STR
+       "Administrative distance\n"
+       "Distance value\n"
+       "IP source prefix\n"
+       "Access list name\n")
+{
+  ospf_distance_unset (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
+void
+show_ip_ospf_route_network (struct vty *vty, struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  listnode pnode;
+  struct ospf_path *path;
+
+  vty_out (vty, "============ OSPF network routing table ============%s",
+	   VTY_NEWLINE);
+
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((or = rn->info) != NULL)
+      {
+	char buf1[19];
+	snprintf (buf1, 19, "%s/%d",
+		  inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
+
+	switch (or->path_type)
+	  {
+	  case OSPF_PATH_INTER_AREA:
+	    if (or->type == OSPF_DESTINATION_NETWORK)
+	      vty_out (vty, "N IA %-18s    [%d] area: %s%s", buf1, or->cost,
+		       inet_ntoa (or->u.std.area_id), VTY_NEWLINE);
+	    else if (or->type == OSPF_DESTINATION_DISCARD)
+	      vty_out (vty, "D IA %-18s    Discard entry%s", buf1, VTY_NEWLINE);
+	    break;
+	  case OSPF_PATH_INTRA_AREA:
+	    vty_out (vty, "N    %-18s    [%d] area: %s%s", buf1, or->cost,
+		     inet_ntoa (or->u.std.area_id), VTY_NEWLINE);
+	    break;
+	  default:
+	    break;
+	  }
+
+        if (or->type == OSPF_DESTINATION_NETWORK)
+ 	  for (pnode = listhead (or->path); pnode; nextnode (pnode))
+	    {
+	      path = getdata (pnode);
+	      if (path->oi != NULL)
+		{
+		  if (path->nexthop.s_addr == 0)
+		    vty_out (vty, "%24s   directly attached to %s%s",
+			     "", path->oi->ifp->name, VTY_NEWLINE);
+		  else 
+		    vty_out (vty, "%24s   via %s, %s%s", "",
+			     inet_ntoa (path->nexthop), path->oi->ifp->name,
+			     VTY_NEWLINE);
+		}
+	    }
+      }
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+void
+show_ip_ospf_route_router (struct vty *vty, struct route_table *rtrs)
+{
+  struct route_node *rn;
+  struct ospf_route *or;
+  listnode pn, nn;
+  struct ospf_path *path;
+
+  vty_out (vty, "============ OSPF router routing table =============%s",
+	   VTY_NEWLINE);
+  for (rn = route_top (rtrs); rn; rn = route_next (rn))
+    if (rn->info)
+      {
+	int flag = 0;
+
+	vty_out (vty, "R    %-15s    ", inet_ntoa (rn->p.u.prefix4));
+
+	for (nn = listhead ((list) rn->info); nn; nextnode (nn))
+	  if ((or = getdata (nn)) != NULL)
+	    {
+	      if (flag++)
+		vty_out(vty,"                              " );
+
+	      /* Show path. */
+	      vty_out (vty, "%s [%d] area: %s",
+		       (or->path_type == OSPF_PATH_INTER_AREA ? "IA" : "  "),
+		       or->cost, inet_ntoa (or->u.std.area_id));
+	      /* Show flags. */
+	      vty_out (vty, "%s%s%s",
+		       (or->u.std.flags & ROUTER_LSA_BORDER ? ", ABR" : ""),
+		       (or->u.std.flags & ROUTER_LSA_EXTERNAL ? ", ASBR" : ""),
+		       VTY_NEWLINE);
+
+	      for (pn = listhead (or->path); pn; nextnode (pn))
+		{
+		  path = getdata (pn);
+		  if (path->nexthop.s_addr == 0)
+		    vty_out (vty, "%24s   directly attached to %s%s",
+			     "", path->oi->ifp->name, VTY_NEWLINE);
+		  else 
+		    vty_out (vty, "%24s   via %s, %s%s", "",
+			     inet_ntoa (path->nexthop), path->oi->ifp->name,
+			     VTY_NEWLINE);
+		}
+	    }
+      }
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+void
+show_ip_ospf_route_external (struct vty *vty, struct route_table *rt)
+{
+  struct route_node *rn;
+  struct ospf_route *er;
+  listnode pnode;
+  struct ospf_path *path;
+
+  vty_out (vty, "============ OSPF external routing table ===========%s",
+	   VTY_NEWLINE);
+  for (rn = route_top (rt); rn; rn = route_next (rn))
+    if ((er = rn->info) != NULL)
+      {
+	char buf1[19];
+	snprintf (buf1, 19, "%s/%d",
+		  inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
+
+	switch (er->path_type)
+	  {
+	  case OSPF_PATH_TYPE1_EXTERNAL:
+	    vty_out (vty, "N E1 %-18s    [%d] tag: %u%s", buf1,
+		     er->cost, er->u.ext.tag, VTY_NEWLINE);
+	    break;
+	  case OSPF_PATH_TYPE2_EXTERNAL:
+	    vty_out (vty, "N E2 %-18s    [%d/%d] tag: %u%s", buf1, er->cost,
+		     er->u.ext.type2_cost, er->u.ext.tag, VTY_NEWLINE);
+	    break;
+	  }
+
+        for (pnode = listhead (er->path); pnode; nextnode (pnode))
+          {
+            path = getdata (pnode);
+            if (path->oi != NULL)
+              {
+                if (path->nexthop.s_addr == 0)
+	          vty_out (vty, "%24s   directly attached to %s%s",
+		           "", path->oi->ifp->name, VTY_NEWLINE);
+                else 
+	          vty_out (vty, "%24s   via %s, %s%s", "",
+			   inet_ntoa (path->nexthop), path->oi->ifp->name,
+     		           VTY_NEWLINE);
+              }
+           }
+        }
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+#ifdef HAVE_NSSA
+DEFUN (show_ip_ospf_border_routers,
+       show_ip_ospf_border_routers_cmd,
+       "show ip ospf border-routers",
+       SHOW_STR
+       IP_STR
+       "show all the ABR's and ASBR's\n"
+       "for this area\n")
+{
+  if (ospf_top == NULL)
+    {
+      vty_out (vty, "OSPF is not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  if (ospf_top->new_table == NULL)
+    {
+      vty_out (vty, "No OSPF routing information exist%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* Show Network routes.
+  show_ip_ospf_route_network (vty, ospf_top->new_table);   */
+
+  /* Show Router routes. */
+  show_ip_ospf_route_router (vty, ospf_top->new_rtrs);
+
+  return CMD_SUCCESS;
+}
+#endif /* HAVE_NSSA */
+
+DEFUN (show_ip_ospf_route,
+       show_ip_ospf_route_cmd,
+       "show ip ospf route",
+       SHOW_STR
+       IP_STR
+       "OSPF information\n"
+       "OSPF routing table\n")
+{
+  if (ospf_top == NULL)
+    {
+      vty_out (vty, "OSPF is not enabled%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  if (ospf_top->new_table == NULL)
+    {
+      vty_out (vty, "No OSPF routing information exist%s", VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* Show Network routes. */
+  show_ip_ospf_route_network (vty, ospf_top->new_table);
+
+  /* Show Router routes. */
+  show_ip_ospf_route_router (vty, ospf_top->new_rtrs);
+
+  /* Show AS External routes. */
+  show_ip_ospf_route_external (vty, ospf_top->old_external_route);
+
+  return CMD_SUCCESS;
+}
+
+
+char *ospf_abr_type_str[] = 
+{
+  "unknown",
+  "standard",
+  "ibm",
+  "cisco",
+  "shortcut"
+};
+
+char *ospf_shortcut_mode_str[] = 
+{
+  "default",
+  "enable",
+  "disable"
+};
+
+
+void
+area_id2str (char *buf, int length, struct ospf_area *area)
+{
+  memset (buf, 0, length);
+
+  if (area->format == OSPF_AREA_ID_FORMAT_ADDRESS)
+    strncpy (buf, inet_ntoa (area->area_id), length);
+  else
+    sprintf (buf, "%lu", (unsigned long) ntohl (area->area_id.s_addr));
+}
+
+
+char *ospf_int_type_str[] = 
+{
+  "unknown",		/* should never be used. */
+  "point-to-point",
+  "broadcast",
+  "non-broadcast",
+  "point-to-multipoint",
+  "virtual-link",	/* should never be used. */
+  "loopback"
+};
+
+/* Configuration write function for ospfd. */
+int
+config_write_interface (struct vty *vty)
+{
+  listnode n1, n2;
+  struct interface *ifp;
+  struct crypt_key *ck;
+  int write = 0;
+  struct route_node *rn = NULL;
+  struct ospf_if_params *params;
+
+  for (n1 = listhead (iflist); n1; nextnode (n1))
+    {
+      ifp = getdata (n1);
+
+      if (memcmp (ifp->name, "VLINK", 5) == 0)
+	continue;
+
+      vty_out (vty, "!%s", VTY_NEWLINE);
+      vty_out (vty, "interface %s%s", ifp->name,
+               VTY_NEWLINE);
+      if (ifp->desc)
+        vty_out (vty, " description %s%s", ifp->desc,
+               VTY_NEWLINE);
+
+      write++;
+
+      params = IF_DEF_PARAMS (ifp);
+      
+      do {
+	/* Interface Network print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, type) &&
+	    params->type != OSPF_IFTYPE_BROADCAST &&
+	    params->type != OSPF_IFTYPE_LOOPBACK)
+	  {
+	    vty_out (vty, " ip ospf network %s",
+		     ospf_int_type_str[params->type]);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+	/* OSPF interface authentication print */
+	if (OSPF_IF_PARAM_CONFIGURED (params, auth_type) &&
+	    params->auth_type != OSPF_AUTH_NOTSET)
+	  {
+	    char *auth_str;
+	    
+	    /* Translation tables are not that much help here due to syntax
+	       of the simple option */
+	    switch (params->auth_type)
+	      {
+		
+	      case OSPF_AUTH_NULL:
+		auth_str = " null";
+		break;
+		
+	      case OSPF_AUTH_SIMPLE:
+		auth_str = "";
+		break;
+		
+	      case OSPF_AUTH_CRYPTOGRAPHIC:
+		auth_str = " message-digest";
+		break;
+		
+	      default:
+		auth_str = "";
+		break;
+	      }
+	    
+	    vty_out (vty, " ip ospf authentication%s", auth_str);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+
+	/* Simple Authentication Password print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, auth_simple) &&
+	    params->auth_simple[0] != '\0')
+	  {
+	    vty_out (vty, " ip ospf authentication-key %s",
+		     params->auth_simple);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+	/* Cryptographic Authentication Key print. */
+	for (n2 = listhead (params->auth_crypt); n2; nextnode (n2))
+	  {
+	    ck = getdata (n2);
+	    vty_out (vty, " ip ospf message-digest-key %d md5 %s",
+		     ck->key_id, ck->auth_key);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+	/* Interface Output Cost print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, output_cost_cmd))
+	  {
+	    vty_out (vty, " ip ospf cost %u", params->output_cost_cmd);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+	/* Hello Interval print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, v_hello) &&
+	    params->v_hello != OSPF_HELLO_INTERVAL_DEFAULT)
+	  {
+	    vty_out (vty, " ip ospf hello-interval %u", params->v_hello);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+	
+	/* Router Dead Interval print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, v_wait) &&
+	    params->v_wait != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT)
+	  {
+	    vty_out (vty, " ip ospf dead-interval %u", params->v_wait);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+      /* Router Priority print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, priority) &&
+	    params->priority != OSPF_ROUTER_PRIORITY_DEFAULT)
+	  {
+	    vty_out (vty, " ip ospf priority %u", params->priority);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+	/* Retransmit Interval print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, retransmit_interval) &&
+	    params->retransmit_interval != OSPF_RETRANSMIT_INTERVAL_DEFAULT)
+	  {
+	    vty_out (vty, " ip ospf retransmit-interval %u",
+		     params->retransmit_interval);
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+	
+	/* Transmit Delay print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, transmit_delay) &&
+	    params->transmit_delay != OSPF_TRANSMIT_DELAY_DEFAULT)
+	  {
+	    vty_out (vty, " ip ospf transmit-delay %u", params->transmit_delay);
+	    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)
+	      rn = route_top (IF_OIFS_PARAMS (ifp));
+	    else
+	      rn = route_next (rn);
+
+	    if (rn == NULL)
+	      break;
+	    params = rn->info;
+	    if (params != NULL)
+	      break;
+	  }
+      } while (rn);
+      
+#ifdef HAVE_OPAQUE_LSA
+      ospf_opaque_config_write_if (vty, ifp);
+#endif /* HAVE_OPAQUE_LSA */
+    }
+
+  return write;
+}
+
+int
+config_write_network_area (struct vty *vty)
+{
+  struct route_node *rn;
+  u_char buf[INET_ADDRSTRLEN];
+
+  /* `network area' print. */
+  for (rn = route_top (ospf_top->networks); rn; rn = route_next (rn))
+    if (rn->info)
+      {
+	struct ospf_network *n = rn->info;
+
+	memset (buf, 0, INET_ADDRSTRLEN);
+
+	/* Create Area ID string by specified Area ID format. */
+	if (n->format == OSPF_AREA_ID_FORMAT_ADDRESS)
+	  strncpy (buf, inet_ntoa (n->area_id), INET_ADDRSTRLEN);
+	else
+	  sprintf (buf, "%lu", 
+		   (unsigned long int) ntohl (n->area_id.s_addr));
+
+	/* Network print. */
+	vty_out (vty, " network %s/%d area %s%s",
+		 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
+		 buf, VTY_NEWLINE);
+      }
+
+  return 0;
+}
+
+int
+config_write_ospf_area (struct vty *vty)
+{
+  listnode node;
+  u_char buf[INET_ADDRSTRLEN];
+
+  /* Area configuration print. */
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      struct ospf_area *area = getdata (node);
+      struct route_node *rn1;
+
+      area_id2str (buf, INET_ADDRSTRLEN, area);
+
+      if (area->auth_type != OSPF_AUTH_NULL)
+	{
+	  if (area->auth_type == OSPF_AUTH_SIMPLE)
+	    vty_out (vty, " area %s authentication%s", buf, VTY_NEWLINE);
+	  else
+	    vty_out (vty, " area %s authentication message-digest%s",
+		     buf, VTY_NEWLINE);
+	}
+
+      if (area->shortcut_configured != OSPF_SHORTCUT_DEFAULT)
+	vty_out (vty, " area %s shortcut %s%s", buf,
+		 ospf_shortcut_mode_str[area->shortcut_configured],
+		 VTY_NEWLINE);
+
+      if ((area->external_routing == OSPF_AREA_STUB)
+#ifdef HAVE_NSSA
+	  || (area->external_routing == OSPF_AREA_NSSA)
+#endif /* HAVE_NSSA */
+	  )
+	{
+#ifdef HAVE_NSSA
+	  if (area->external_routing == OSPF_AREA_NSSA)
+	    vty_out (vty, " area %s nssa", buf);
+	  else
+#endif /* HAVE_NSSA */
+	    vty_out (vty, " area %s stub", buf);
+
+	  if (area->no_summary)
+	    vty_out (vty, " no-summary");
+
+	  vty_out (vty, "%s", VTY_NEWLINE);
+
+	  if (area->default_cost != 1)
+	    vty_out (vty, " area %s default-cost %d%s", buf, 
+		     area->default_cost, VTY_NEWLINE);
+	}
+
+      for (rn1 = route_top (area->ranges); rn1; rn1 = route_next (rn1))
+	if (rn1->info)
+	  {
+	    struct ospf_area_range *range = rn1->info;
+
+	    vty_out (vty, " area %s range %s/%d", buf,
+		     inet_ntoa (rn1->p.u.prefix4), rn1->p.prefixlen);
+
+	    if (range->cost_config != -1)
+	      vty_out (vty, " cost %d", range->cost_config);
+
+	    if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE))
+	      vty_out (vty, " not-advertise");
+
+	    if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))
+	      vty_out (vty, " substitute %s/%d",
+		       inet_ntoa (range->subst_addr), range->subst_masklen);
+
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+
+      if (EXPORT_NAME (area))
+	vty_out (vty, " area %s export-list %s%s", buf,
+		 EXPORT_NAME (area), VTY_NEWLINE);
+
+      if (IMPORT_NAME (area))
+	vty_out (vty, " area %s import-list %s%s", buf,
+		 IMPORT_NAME (area), VTY_NEWLINE);
+
+      if (PREFIX_NAME_IN (area))
+	vty_out (vty, " area %s filter-list prefix %s in%s", buf,
+		 PREFIX_NAME_IN (area), VTY_NEWLINE);
+
+      if (PREFIX_NAME_OUT (area))
+	vty_out (vty, " area %s filter-list prefix %s out%s", buf,
+		 PREFIX_NAME_OUT (area), VTY_NEWLINE);
+    }
+
+  return 0;
+}
+
+int
+config_write_ospf_nbr_nbma (struct vty *vty)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+  struct route_node *rn;
+
+  /* Static Neighbor configuration print. */
+  for (rn = route_top (ospf_top->nbr_nbma); rn; rn = route_next (rn))
+    if ((nbr_nbma = rn->info))
+      {
+	vty_out (vty, " neighbor %s", inet_ntoa (nbr_nbma->addr));
+
+	if (nbr_nbma->priority != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
+	  vty_out (vty, " priority %d", nbr_nbma->priority);
+
+	if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
+	  vty_out (vty, " poll-interval %d", nbr_nbma->v_poll);
+
+	vty_out (vty, "%s", VTY_NEWLINE);
+      }
+
+  return 0;
+}
+
+int
+config_write_virtual_link (struct vty *vty)
+{
+  listnode node;
+  u_char buf[INET_ADDRSTRLEN];
+
+  /* Virtual-Link print */
+  for (node = listhead (ospf_top->vlinks); node; nextnode (node))
+    {
+      listnode n2;
+      struct crypt_key *ck;
+      struct ospf_vl_data *vl_data = getdata (node);
+      struct ospf_interface *oi;
+
+      if (vl_data != NULL)
+	{
+	  memset (buf, 0, INET_ADDRSTRLEN);
+	  
+	  if (vl_data->format == OSPF_AREA_ID_FORMAT_ADDRESS)
+	    strncpy (buf, inet_ntoa (vl_data->vl_area_id), INET_ADDRSTRLEN);
+	  else
+	    sprintf (buf, "%lu", 
+		     (unsigned long int) ntohl (vl_data->vl_area_id.s_addr));
+	  oi = vl_data->vl_oi;
+
+	  /* timers */
+	  if (OSPF_IF_PARAM (oi, v_hello) != OSPF_HELLO_INTERVAL_DEFAULT ||
+	      OSPF_IF_PARAM (oi, v_wait) != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT ||
+	      OSPF_IF_PARAM (oi, retransmit_interval) != OSPF_RETRANSMIT_INTERVAL_DEFAULT ||
+	      OSPF_IF_PARAM (oi, transmit_delay) != OSPF_TRANSMIT_DELAY_DEFAULT)
+	    vty_out (vty, " area %s virtual-link %s hello-interval %d retransmit-interval %d transmit-delay %d dead-interval %d%s",
+		     buf,
+		     inet_ntoa (vl_data->vl_peer), 
+		     OSPF_IF_PARAM (oi, v_hello),
+		     OSPF_IF_PARAM (oi, retransmit_interval),
+		     OSPF_IF_PARAM (oi, transmit_delay),
+		     OSPF_IF_PARAM (oi, v_wait),
+		     VTY_NEWLINE);
+	  else
+	    vty_out (vty, " area %s virtual-link %s%s", buf,
+		     inet_ntoa (vl_data->vl_peer), VTY_NEWLINE);
+	  /* Auth key */
+	  if (IF_DEF_PARAMS (vl_data->vl_oi->ifp)->auth_simple[0] != '\0')
+	    vty_out (vty, " area %s virtual-link %s authentication-key %s%s",
+		     buf,
+		     inet_ntoa (vl_data->vl_peer),
+		     IF_DEF_PARAMS (vl_data->vl_oi->ifp)->auth_simple,
+		     VTY_NEWLINE);
+	  /* md5 keys */
+	  for (n2 = listhead (IF_DEF_PARAMS (vl_data->vl_oi->ifp)->auth_crypt); n2; nextnode (n2))
+	    {
+	      ck = getdata (n2);
+	      vty_out (vty, " area %s virtual-link %s message-digest-key %d md5 %s%s",
+		       buf,
+		       inet_ntoa (vl_data->vl_peer),
+		       ck->key_id, ck->auth_key, VTY_NEWLINE);
+	    }
+	 
+	}
+    }
+
+  return 0;
+}
+
+
+char *distribute_str[] = { "system", "kernel", "connected", "static", "rip",
+			   "ripng", "ospf", "ospf6", "bgp"};
+int
+config_write_ospf_redistribute (struct vty *vty)
+{
+  int type;
+
+  /* redistribute print. */
+  for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+    if (type != zclient->redist_default && zclient->redist[type])
+      {
+        vty_out (vty, " redistribute %s", distribute_str[type]);
+	if (ospf_top->dmetric[type].value >= 0)
+	  vty_out (vty, " metric %d", ospf_top->dmetric[type].value);
+	
+        if (ospf_top->dmetric[type].type == EXTERNAL_METRIC_TYPE_1)
+	  vty_out (vty, " metric-type 1");
+
+	if (ROUTEMAP_NAME (type))
+	  vty_out (vty, " route-map %s", ROUTEMAP_NAME (type));
+	
+        vty_out (vty, "%s", VTY_NEWLINE);
+      }
+
+  return 0;
+}
+
+int
+config_write_ospf_default_metric (struct vty *vty)
+{
+  if (ospf_top->default_metric != -1)
+    vty_out (vty, " default-metric %d%s", ospf_top->default_metric,
+	     VTY_NEWLINE);
+  return 0;
+}
+
+int
+config_write_ospf_distribute (struct vty *vty)
+{
+  int type;
+
+  if (ospf_top)
+    {
+      /* distribute-list print. */
+      for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+	if (ospf_top->dlist[type].name)
+	  vty_out (vty, " distribute-list %s out %s%s", 
+		   ospf_top->dlist[type].name,
+		   distribute_str[type], VTY_NEWLINE);
+
+      /* default-information print. */
+      if (ospf_top->default_originate != DEFAULT_ORIGINATE_NONE)
+	{
+	  if (ospf_top->default_originate == DEFAULT_ORIGINATE_ZEBRA)
+	    vty_out (vty, " default-information originate");
+	  else
+	    vty_out (vty, " default-information originate always");
+
+	  if (ospf_top->dmetric[DEFAULT_ROUTE].value >= 0)
+	    vty_out (vty, " metric %d",
+		     ospf_top->dmetric[DEFAULT_ROUTE].value);
+	  if (ospf_top->dmetric[DEFAULT_ROUTE].type == EXTERNAL_METRIC_TYPE_1)
+	    vty_out (vty, " metric-type 1");
+
+	  if (ROUTEMAP_NAME (DEFAULT_ROUTE))
+	    vty_out (vty, " route-map %s", ROUTEMAP_NAME (DEFAULT_ROUTE));
+	  
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+
+    }
+
+  return 0;
+}
+
+int
+config_write_ospf_distance (struct vty *vty)
+{
+  struct route_node *rn;
+  struct ospf_distance *odistance;
+
+  if (ospf_top->distance_all)
+    vty_out (vty, " distance %d%s", ospf_top->distance_all, VTY_NEWLINE);
+
+  if (ospf_top->distance_intra 
+      || ospf_top->distance_inter 
+      || ospf_top->distance_external)
+    {
+      vty_out (vty, " distance ospf");
+
+      if (ospf_top->distance_intra)
+	vty_out (vty, " intra-area %d", ospf_top->distance_intra);
+      if (ospf_top->distance_inter)
+	vty_out (vty, " inter-area %d", ospf_top->distance_inter);
+      if (ospf_top->distance_external)
+	vty_out (vty, " external %d", ospf_top->distance_external);
+
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+  
+  for (rn = route_top (ospf_top->distance_table); rn; rn = route_next (rn))
+    if ((odistance = rn->info) != NULL)
+      {
+	vty_out (vty, " distance %d %s/%d %s%s", odistance->distance,
+		 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
+		 odistance->access_list ? odistance->access_list : "",
+		 VTY_NEWLINE);
+      }
+  return 0;
+}
+
+/* OSPF configuration write function. */
+int
+ospf_config_write (struct vty *vty)
+{
+  listnode node;
+  int write = 0;
+
+  if (ospf_top != NULL)
+    {
+      /* `router ospf' print. */
+      vty_out (vty, "router ospf%s", VTY_NEWLINE);
+
+      write++;
+
+      if (!ospf_top->networks)
+        return write;
+
+      /* Router ID print. */
+      if (ospf_top->router_id_static.s_addr != 0)
+        vty_out (vty, " ospf router-id %s%s",
+                 inet_ntoa (ospf_top->router_id_static), VTY_NEWLINE);
+
+      /* ABR type print. */
+      if (ospf_top->abr_type != OSPF_ABR_STAND)
+        vty_out (vty, " ospf abr-type %s%s", 
+                 ospf_abr_type_str[ospf_top->abr_type], VTY_NEWLINE);
+
+      /* RFC1583 compatibility flag print -- Compatible with CISCO 12.1. */
+      if (CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+	vty_out (vty, " compatible rfc1583%s", VTY_NEWLINE);
+
+      /* auto-cost reference-bandwidth configuration.  */
+      if (ospf_top->ref_bandwidth != OSPF_DEFAULT_REF_BANDWIDTH)
+	vty_out (vty, " auto-cost reference-bandwidth %d%s",
+		 ospf_top->ref_bandwidth / 1000, VTY_NEWLINE);
+
+      /* SPF timers print. */
+      if (ospf_top->spf_delay != OSPF_SPF_DELAY_DEFAULT ||
+	  ospf_top->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT)
+	vty_out (vty, " timers spf %d %d%s",
+		 ospf_top->spf_delay, ospf_top->spf_holdtime, VTY_NEWLINE);
+
+      /* SPF refresh parameters print. */
+      if (ospf_top->lsa_refresh_interval != OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
+	vty_out (vty, " refresh timer %d%s",
+		 ospf_top->lsa_refresh_interval, VTY_NEWLINE);
+
+      /* Redistribute information print. */
+      config_write_ospf_redistribute (vty);
+
+      /* passive-interface print. */
+      for (node = listhead (ospf_top->iflist); node; nextnode (node))
+        {
+          struct interface *ifp = getdata (node);
+
+	  if (!ifp)
+	    continue;
+	  if (IF_DEF_PARAMS (ifp)->passive_interface == OSPF_IF_PASSIVE)
+	    vty_out (vty, " passive-interface %s%s",
+		     ifp->name, VTY_NEWLINE);
+        }
+
+      for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+        {
+          struct ospf_interface *oi = getdata (node);
+
+	  if (OSPF_IF_PARAM_CONFIGURED (oi->params, passive_interface) &&
+	      oi->params->passive_interface == OSPF_IF_PASSIVE)
+	    vty_out (vty, " passive-interface %s%s",
+		     inet_ntoa (oi->address->u.prefix4), VTY_NEWLINE);
+        }
+
+      
+      /* Network area print. */
+      config_write_network_area (vty);
+
+      /* Area config print. */
+      config_write_ospf_area (vty);
+
+      /* static neighbor print. */
+      config_write_ospf_nbr_nbma (vty);
+
+      /* Virtual-Link print. */
+      config_write_virtual_link (vty);
+
+      /* Default metric configuration.  */
+      config_write_ospf_default_metric (vty);
+
+      /* Distribute-list and default-information print. */
+      config_write_ospf_distribute (vty);
+
+      /* Distance configuration. */
+      config_write_ospf_distance (vty);
+
+#ifdef HAVE_OPAQUE_LSA
+      ospf_opaque_config_write_router (vty, ospf_top);
+#endif /* HAVE_OPAQUE_LSA */
+    }
+
+  return write;
+}
+
+void
+ospf_vty_show_init ()
+{
+  /* "show ip ospf" commands. */
+  install_element (VIEW_NODE, &show_ip_ospf_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_cmd);
+
+  /* "show ip ospf database" commands. */
+  install_element (VIEW_NODE, &show_ip_ospf_database_type_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_database_type_id_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_database_type_id_adv_router_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_database_type_adv_router_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_database_type_id_self_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_database_type_self_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_database_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_database_type_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_database_type_id_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_database_type_id_adv_router_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_database_type_adv_router_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_database_type_id_self_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_database_type_self_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_database_cmd);
+
+  /* "show ip ospf interface" commands. */
+  install_element (VIEW_NODE, &show_ip_ospf_interface_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_interface_cmd);
+
+  /* "show ip ospf neighbor" commands. */
+  install_element (VIEW_NODE, &show_ip_ospf_neighbor_int_detail_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_neighbor_int_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_neighbor_id_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_neighbor_detail_all_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_neighbor_detail_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_neighbor_cmd);
+  install_element (VIEW_NODE, &show_ip_ospf_neighbor_all_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_neighbor_int_detail_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_neighbor_int_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_neighbor_id_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_neighbor_detail_all_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_neighbor_detail_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_neighbor_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_neighbor_all_cmd);
+
+  /* "show ip ospf route" commands. */
+  install_element (VIEW_NODE, &show_ip_ospf_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_route_cmd);
+#ifdef HAVE_NSSA
+  install_element (VIEW_NODE, &show_ip_ospf_border_routers_cmd);
+  install_element (ENABLE_NODE, &show_ip_ospf_border_routers_cmd);
+#endif /* HAVE_NSSA */
+}
+
+
+/* ospfd's interface node. */
+struct cmd_node interface_node =
+{
+  INTERFACE_NODE,
+  "%s(config-if)# ",
+  1
+};
+
+/* Initialization of OSPF interface. */
+void
+ospf_vty_if_init ()
+{
+  /* Install interface node. */
+  install_node (&interface_node, config_write_interface);
+
+  install_element (CONFIG_NODE, &interface_cmd);
+  install_default (INTERFACE_NODE);
+
+  /* "description" commands. */
+  install_element (INTERFACE_NODE, &interface_desc_cmd);
+  install_element (INTERFACE_NODE, &no_interface_desc_cmd);
+
+  /* "ip ospf authentication" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_authentication_args_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_authentication_args_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_authentication_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_authentication_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_authentication_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_authentication_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_authentication_key_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_authentication_key_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_authentication_key_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_authentication_key_cmd);
+
+  /* "ip ospf message-digest-key" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_message_digest_key_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_message_digest_key_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_message_digest_key_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_message_digest_key_cmd);
+
+  /* "ip ospf cost" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_cost_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_cost_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_cost_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_cost_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);
+  install_element (INTERFACE_NODE, &no_ip_ospf_dead_interval_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_dead_interval_cmd);
+
+  /* "ip ospf hello-interval" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_hello_interval_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_hello_interval_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_hello_interval_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_hello_interval_cmd);
+
+  /* "ip ospf network" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_network_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_network_cmd);
+
+  /* "ip ospf priority" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_priority_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_priority_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_priority_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_priority_cmd);
+
+  /* "ip ospf retransmit-interval" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_retransmit_interval_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_retransmit_interval_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_retransmit_interval_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_retransmit_interval_cmd);
+
+  /* "ip ospf transmit-delay" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_transmit_delay_addr_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_transmit_delay_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_cmd);
+
+  /* These commands are compatibitliy for previous version. */
+  install_element (INTERFACE_NODE, &ospf_authentication_key_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd);
+  install_element (INTERFACE_NODE, &ospf_message_digest_key_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_message_digest_key_cmd);
+  install_element (INTERFACE_NODE, &ospf_cost_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_cost_cmd);
+  install_element (INTERFACE_NODE, &ospf_dead_interval_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_dead_interval_cmd);
+  install_element (INTERFACE_NODE, &ospf_hello_interval_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_hello_interval_cmd);
+  install_element (INTERFACE_NODE, &ospf_network_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_network_cmd);
+  install_element (INTERFACE_NODE, &ospf_priority_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_priority_cmd);
+  install_element (INTERFACE_NODE, &ospf_retransmit_interval_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_retransmit_interval_cmd);
+  install_element (INTERFACE_NODE, &ospf_transmit_delay_cmd);
+  install_element (INTERFACE_NODE, &no_ospf_transmit_delay_cmd);
+}
+
+/* Zebra node structure. */
+struct cmd_node zebra_node =
+{
+  ZEBRA_NODE,
+  "%s(config-router)#",
+};
+
+void
+ospf_vty_zebra_init ()
+{
+  install_element (OSPF_NODE, &ospf_redistribute_source_type_metric_cmd);
+  install_element (OSPF_NODE, &ospf_redistribute_source_metric_type_cmd);
+  install_element (OSPF_NODE, &ospf_redistribute_source_type_cmd);
+  install_element (OSPF_NODE, &ospf_redistribute_source_metric_cmd);
+  install_element (OSPF_NODE, &ospf_redistribute_source_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_redistribute_source_metric_type_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_redistribute_source_type_metric_routemap_cmd);
+  install_element (OSPF_NODE, &ospf_redistribute_source_metric_routemap_cmd);
+  install_element (OSPF_NODE, &ospf_redistribute_source_type_routemap_cmd);
+  install_element (OSPF_NODE, &ospf_redistribute_source_routemap_cmd);
+  
+  install_element (OSPF_NODE, &no_ospf_redistribute_source_cmd);
+
+  install_element (OSPF_NODE, &ospf_distribute_list_out_cmd);
+  install_element (OSPF_NODE, &no_ospf_distribute_list_out_cmd);
+
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_metric_type_cmd);
+  install_element (OSPF_NODE, &ospf_default_information_originate_metric_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_type_metric_cmd);
+  install_element (OSPF_NODE, &ospf_default_information_originate_type_cmd);
+  install_element (OSPF_NODE, &ospf_default_information_originate_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_metric_type_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_metric_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_type_metric_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_type_cmd);
+
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_metric_type_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_metric_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_type_metric_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_type_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_metric_type_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_metric_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_type_metric_routemap_cmd);
+  install_element (OSPF_NODE,
+		   &ospf_default_information_originate_always_type_routemap_cmd);
+
+  install_element (OSPF_NODE, &no_ospf_default_information_originate_cmd);
+
+  install_element (OSPF_NODE, &ospf_default_metric_cmd);
+  install_element (OSPF_NODE, &no_ospf_default_metric_cmd);
+  install_element (OSPF_NODE, &no_ospf_default_metric_val_cmd);
+
+  install_element (OSPF_NODE, &ospf_distance_cmd);
+  install_element (OSPF_NODE, &no_ospf_distance_cmd);
+  install_element (OSPF_NODE, &no_ospf_distance_ospf_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_intra_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_intra_inter_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_intra_external_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_intra_inter_external_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_intra_external_inter_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_inter_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_inter_intra_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_inter_external_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_inter_intra_external_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_inter_external_intra_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_external_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_external_intra_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_external_inter_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_external_intra_inter_cmd);
+  install_element (OSPF_NODE, &ospf_distance_ospf_external_inter_intra_cmd);
+#if 0
+  install_element (OSPF_NODE, &ospf_distance_source_cmd);
+  install_element (OSPF_NODE, &no_ospf_distance_source_cmd);
+  install_element (OSPF_NODE, &ospf_distance_source_access_list_cmd);
+  install_element (OSPF_NODE, &no_ospf_distance_source_access_list_cmd);
+#endif /* 0 */
+}
+
+struct cmd_node ospf_node =
+{
+  OSPF_NODE,
+  "%s(config-router)# ",
+  1
+};
+
+
+/* Install OSPF related vty commands. */
+void
+ospf_vty_init ()
+{
+  /* Install ospf top node. */
+  install_node (&ospf_node, ospf_config_write);
+
+  /* "router ospf" commands. */
+  install_element (CONFIG_NODE, &router_ospf_cmd);
+  install_element (CONFIG_NODE, &no_router_ospf_cmd);
+
+  install_default (OSPF_NODE);
+
+  /* "ospf router-id" commands. */
+  install_element (OSPF_NODE, &ospf_router_id_cmd);
+  install_element (OSPF_NODE, &no_ospf_router_id_cmd);
+  install_element (OSPF_NODE, &router_id_cmd);
+  install_element (OSPF_NODE, &no_router_id_cmd);
+
+  /* "passive-interface" commands. */
+  install_element (OSPF_NODE, &passive_interface_addr_cmd);
+  install_element (OSPF_NODE, &passive_interface_cmd);
+  install_element (OSPF_NODE, &no_passive_interface_addr_cmd);
+  install_element (OSPF_NODE, &no_passive_interface_cmd);
+
+  /* "ospf abr-type" commands. */
+  install_element (OSPF_NODE, &ospf_abr_type_cmd);
+  install_element (OSPF_NODE, &no_ospf_abr_type_cmd);
+
+  /* "ospf rfc1583-compatible" commands. */
+  install_element (OSPF_NODE, &ospf_rfc1583_flag_cmd);
+  install_element (OSPF_NODE, &no_ospf_rfc1583_flag_cmd);
+  install_element (OSPF_NODE, &ospf_compatible_rfc1583_cmd);
+  install_element (OSPF_NODE, &no_ospf_compatible_rfc1583_cmd);
+
+  /* "network area" commands. */
+  install_element (OSPF_NODE, &network_area_cmd);
+  install_element (OSPF_NODE, &no_network_area_cmd);
+
+  /* "area authentication" commands. */
+  install_element (OSPF_NODE, &area_authentication_message_digest_cmd);
+  install_element (OSPF_NODE, &area_authentication_cmd);
+  install_element (OSPF_NODE, &no_area_authentication_cmd);
+
+  /* "area range" commands.  */
+  install_element (OSPF_NODE, &area_range_cmd);
+  install_element (OSPF_NODE, &area_range_advertise_cmd);
+  install_element (OSPF_NODE, &area_range_cost_cmd);
+  install_element (OSPF_NODE, &area_range_advertise_cost_cmd);
+  install_element (OSPF_NODE, &area_range_not_advertise_cmd);
+  install_element (OSPF_NODE, &no_area_range_cmd);
+  install_element (OSPF_NODE, &no_area_range_advertise_cmd);
+  install_element (OSPF_NODE, &no_area_range_cost_cmd);
+  install_element (OSPF_NODE, &no_area_range_advertise_cost_cmd);
+  install_element (OSPF_NODE, &area_range_substitute_cmd);
+  install_element (OSPF_NODE, &no_area_range_substitute_cmd);
+
+  /* "area virtual-link" commands. */
+  install_element (OSPF_NODE, &area_vlink_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_param1_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_param1_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_param2_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_param2_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_param3_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_param3_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_param4_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_param4_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_authtype_args_cmd);
+  install_element (OSPF_NODE, &area_vlink_authtype_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_authtype_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_md5_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_md5_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_authkey_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_authkey_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_authtype_args_authkey_cmd);
+  install_element (OSPF_NODE, &area_vlink_authtype_authkey_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_authtype_authkey_cmd);
+
+  install_element (OSPF_NODE, &area_vlink_authtype_args_md5_cmd);
+  install_element (OSPF_NODE, &area_vlink_authtype_md5_cmd);
+  install_element (OSPF_NODE, &no_area_vlink_authtype_md5_cmd);
+
+  /* "area stub" commands. */
+  install_element (OSPF_NODE, &area_stub_no_summary_cmd);
+  install_element (OSPF_NODE, &area_stub_cmd);
+  install_element (OSPF_NODE, &no_area_stub_no_summary_cmd);
+  install_element (OSPF_NODE, &no_area_stub_cmd);
+
+#ifdef HAVE_NSSA
+  /* "area nssa" commands. */
+  install_element (OSPF_NODE, &area_nssa_cmd);
+  install_element (OSPF_NODE, &area_nssa_translate_no_summary_cmd);
+  install_element (OSPF_NODE, &area_nssa_translate_cmd);
+  install_element (OSPF_NODE, &area_nssa_no_summary_cmd);
+  install_element (OSPF_NODE, &no_area_nssa_cmd);
+  install_element (OSPF_NODE, &no_area_nssa_no_summary_cmd);
+#endif /* HAVE_NSSA */
+
+  install_element (OSPF_NODE, &area_default_cost_cmd);
+  install_element (OSPF_NODE, &no_area_default_cost_cmd);
+
+  install_element (OSPF_NODE, &area_shortcut_cmd);
+  install_element (OSPF_NODE, &no_area_shortcut_cmd);
+
+  install_element (OSPF_NODE, &area_export_list_cmd);
+  install_element (OSPF_NODE, &no_area_export_list_cmd);
+
+  install_element (OSPF_NODE, &area_filter_list_cmd);
+  install_element (OSPF_NODE, &no_area_filter_list_cmd);
+
+  install_element (OSPF_NODE, &area_import_list_cmd);
+  install_element (OSPF_NODE, &no_area_import_list_cmd);
+
+  install_element (OSPF_NODE, &timers_spf_cmd);
+  install_element (OSPF_NODE, &no_timers_spf_cmd);
+
+  install_element (OSPF_NODE, &refresh_timer_cmd);
+  install_element (OSPF_NODE, &no_refresh_timer_val_cmd);
+  install_element (OSPF_NODE, &no_refresh_timer_cmd);
+  
+  install_element (OSPF_NODE, &auto_cost_reference_bandwidth_cmd);
+  install_element (OSPF_NODE, &no_auto_cost_reference_bandwidth_cmd);
+
+  /* "neighbor" commands. */
+  install_element (OSPF_NODE, &neighbor_cmd);
+  install_element (OSPF_NODE, &neighbor_priority_poll_interval_cmd);
+  install_element (OSPF_NODE, &neighbor_priority_cmd);
+  install_element (OSPF_NODE, &neighbor_poll_interval_cmd);
+  install_element (OSPF_NODE, &neighbor_poll_interval_priority_cmd);
+  install_element (OSPF_NODE, &no_neighbor_cmd);
+  install_element (OSPF_NODE, &no_neighbor_priority_cmd);
+  install_element (OSPF_NODE, &no_neighbor_poll_interval_cmd);
+
+  /* Init interface related vty commands. */
+  ospf_vty_if_init ();
+
+  /* Init zebra related vty commands. */
+  ospf_vty_zebra_init ();
+}
+
diff --git a/ospfd/ospf_vty.h b/ospfd/ospf_vty.h
new file mode 100644
index 0000000..9f30e20
--- /dev/null
+++ b/ospfd/ospf_vty.h
@@ -0,0 +1,85 @@
+/* OSPF VTY interface.
+ * Copyright (C) 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+/* Macros. */
+#define VTY_GET_UINT32(NAME,V,STR)                                            \
+{                                                                             \
+  char *endptr = NULL;                                                        \
+  (V) = strtoul ((STR), &endptr, 10);                                         \
+  if (*endptr != '\0' || ((V) == ULONG_MAX && errno == ERANGE))               \
+    {                                                                         \
+      vty_out (vty, "%% Invalid %s value%s", NAME, VTY_NEWLINE);              \
+      return CMD_WARNING;                                                     \
+    }                                                                         \
+}
+
+#define VTY_GET_IPV4_ADDRESS(NAME,V,STR)                                      \
+{                                                                             \
+  int retv;                                                                   \
+  retv = inet_aton ((STR), &(V));                                             \
+  if (!retv)                                                                  \
+    {                                                                         \
+      vty_out (vty, "%% Invalid %s value%s", NAME, VTY_NEWLINE);              \
+      return CMD_WARNING;                                                     \
+    }                                                                         \
+}
+
+#define VTY_GET_IPV4_PREFIX(NAME,V,STR)                                       \
+{                                                                             \
+  int retv;                                                                   \
+  retv = str2prefix_ipv4 ((STR), &(V));                                       \
+  if (retv <= 0)                                                              \
+    {                                                                         \
+      vty_out (vty, "%% Invalid %s value%s", NAME, VTY_NEWLINE);              \
+      return CMD_WARNING;                                                     \
+    }                                                                         \
+}
+
+#define VTY_GET_OSPF_AREA_ID(V,F,STR)                                         \
+{                                                                             \
+  int retv;                                                                   \
+  retv = ospf_str2area_id ((STR), &(V), &(F));                                \
+  if (retv < 0)                                                               \
+    {                                                                         \
+      vty_out (vty, "%% Invalid OSPF area ID%s", VTY_NEWLINE);                \
+      return CMD_WARNING;                                                     \
+    }                                                                         \
+}
+
+#define VTY_GET_OSPF_AREA_ID_NO_BB(NAME,V,F,STR)                              \
+{                                                                             \
+  int retv;                                                                   \
+  retv = ospf_str2area_id ((STR), &(V), &(F));                                \
+  if (retv < 0)                                                               \
+    {                                                                         \
+      vty_out (vty, "%% Invalid OSPF area ID%s", VTY_NEWLINE);                \
+      return CMD_WARNING;                                                     \
+    }                                                                         \
+  if (OSPF_IS_AREA_ID_BACKBONE ((V)))                                         \
+    {                                                                         \
+      vty_out (vty, "%% You can't configure %s to backbone%s",                \
+               NAME, VTY_NEWLINE);                                            \
+    }                                                                         \
+}
+
+/* Prototypes. */
+void ospf_vty_init ();
+void ospf_vty_show_init ();
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
new file mode 100644
index 0000000..1ad31f2
--- /dev/null
+++ b/ospfd/ospf_zebra.c
@@ -0,0 +1,1180 @@
+/*
+ * Zebra connect library for OSPFd
+ * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA. 
+ */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "command.h"
+#include "network.h"
+#include "prefix.h"
+#include "routemap.h"
+#include "table.h"
+#include "stream.h"
+#include "memory.h"
+#include "zclient.h"
+#include "filter.h"
+#include "log.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_zebra.h"
+#ifdef HAVE_SNMP
+#include "ospfd/ospf_snmp.h"
+#endif /* HAVE_SNMP */
+
+/* Zebra structure to hold current status. */
+struct zclient *zclient = NULL;
+
+/* For registering threads. */
+extern struct thread_master *master;
+
+/* Inteface addition message from zebra. */
+int
+ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct interface *ifp;
+
+  ifp = zebra_interface_add_read (zclient->ibuf);
+
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+    zlog_info ("Zebra: interface add %s index %d flags %ld metric %d mtu %d",
+	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+
+  if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
+    {
+      SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
+      IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
+      
+      if (if_is_broadcast (ifp))
+	IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
+      else if (if_is_pointopoint (ifp))
+	IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOPOINT;
+      else if (if_is_loopback (ifp))
+	IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_LOOPBACK;
+    }
+
+  ospf_if_update ();
+
+#ifdef HAVE_SNMP
+  ospf_snmp_if_update (ifp);
+#endif /* HAVE_SNMP */
+
+  return 0;
+}
+
+int
+ospf_interface_delete (int command, struct zclient *zclient,
+		       zebra_size_t length)
+{
+  struct interface *ifp;
+  struct stream *s;
+  struct route_node *rn;
+
+  s = zclient->ibuf;  
+  /* zebra_interface_state_read() updates interface structure in iflist */
+  ifp = zebra_interface_state_read (s);
+
+  if (ifp == NULL)
+    return 0;
+
+  if (if_is_up (ifp))
+    zlog_warn ("Zebra: got delete of %s, but interface is still up",
+	       ifp->name);
+  
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+    zlog_info ("Zebra: interface delete %s index %d flags %ld metric %d mtu %d",
+	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);  
+
+#ifdef HAVE_SNMP
+  ospf_snmp_if_delete (ifp);
+#endif /* HAVE_SNMP */
+
+  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
+    if (rn->info)
+      ospf_if_free ((struct ospf_interface *) rn->info);
+
+  for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
+    if (rn->info)
+      ospf_del_if_params (rn->info);
+  
+  if_delete (ifp);
+
+  return 0;
+}
+
+struct interface *
+zebra_interface_if_lookup (struct stream *s)
+{
+  struct interface *ifp;
+  u_char ifname_tmp[INTERFACE_NAMSIZ];
+
+  /* Read interface name. */
+  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
+
+  /* Lookup this by interface index. */
+  ifp = if_lookup_by_name (ifname_tmp);
+
+  /* If such interface does not exist, indicate an error */
+  if (!ifp)
+    return NULL;
+
+  return ifp;
+}
+
+void
+zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
+{
+  /* Read interface's index. */
+  ifp->ifindex = stream_getl (s);
+
+  /* Read interface's value. */
+  ifp->flags = stream_getl (s);
+  ifp->metric = stream_getl (s);
+  ifp->mtu = stream_getl (s);
+  ifp->bandwidth = stream_getl (s);
+}
+
+int
+ospf_interface_state_up (int command, struct zclient *zclient,
+			 zebra_size_t length)
+{
+  struct interface *ifp;
+  struct interface if_tmp;
+  struct ospf_interface *oi;
+  struct route_node *rn;
+  
+  ifp = zebra_interface_if_lookup (zclient->ibuf);
+
+  if (ifp == NULL)
+    return 0;
+
+  /* Interface is already up. */
+  if (if_is_up (ifp))
+    {
+      /* Temporarily keep ifp values. */
+      memcpy (&if_tmp, ifp, sizeof (struct interface));
+
+      zebra_interface_if_set_value (zclient->ibuf, ifp);
+
+      if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+	zlog_info ("Zebra: Interface[%s] state update.", ifp->name);
+
+      if (if_tmp.bandwidth != ifp->bandwidth)
+	{
+	  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+	    zlog_info ("Zebra: Interface[%s] bandwidth change %d -> %d.",
+		       ifp->name, if_tmp.bandwidth, ifp->bandwidth);
+
+	  ospf_if_recalculate_output_cost (ifp);
+	}
+      return 0;
+    }
+  
+  zebra_interface_if_set_value (zclient->ibuf, ifp);
+  
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+    zlog_info ("Zebra: Interface[%s] state change to up.", ifp->name);
+  
+  for (rn = route_top (IF_OIFS (ifp));rn; rn = route_next (rn))
+    {
+      if ( (oi = rn->info) == NULL)
+	continue;
+      
+      ospf_if_up (oi);
+    }
+  
+  return 0;
+}
+
+int
+ospf_interface_state_down (int command, struct zclient *zclient,
+			   zebra_size_t length)
+{
+  struct interface *ifp;
+  struct ospf_interface *oi;
+  struct route_node *node;
+
+  ifp = zebra_interface_state_read (zclient->ibuf);
+
+  if (ifp == NULL)
+    return 0;
+
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+    zlog_info ("Zebra: Interface[%s] state change to down.", ifp->name);
+
+  for (node = route_top (IF_OIFS (ifp));node; node = route_next (node))
+    {
+      if ( (oi = node->info) == NULL)
+	continue;
+      ospf_if_down (oi);
+    }
+
+  return 0;
+}
+
+int
+ospf_interface_address_add (int command, struct zclient *zclient,
+			    zebra_size_t length)
+{
+  struct connected *c;
+
+  c = zebra_interface_address_add_read (zclient->ibuf);
+
+  if (c == NULL)
+    return 0;
+
+#if 0
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+    {
+      struct prefix *p;
+
+      p = c->address;
+      if (p->family == AF_INET)
+	zlog_info (" connected address %s/%d", 
+		   inet_atop (p->u.prefix4), p->prefixlen);
+    }
+#endif
+
+  ospf_if_update ();
+
+#ifdef HAVE_SNMP
+  ospf_snmp_if_update (c->ifp);
+#endif /* HAVE_SNMP */
+
+  return 0;
+}
+
+int
+ospf_interface_address_delete (int command, struct zclient *zclient,
+			       zebra_size_t length)
+{
+  struct connected *c;
+  struct interface *ifp;
+  struct ospf_interface *oi;
+  struct route_node *rn;
+  struct prefix p;
+
+  c = zebra_interface_address_delete_read (zclient->ibuf);
+
+  if (c == NULL)
+    return 0;
+
+  ifp = c->ifp;
+  p = *c->address;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+
+  rn = route_node_lookup (IF_OIFS (ifp), &p);
+  if (! rn)
+    return 0;
+
+  assert (rn->info);
+  oi = rn->info;
+  
+  /* Call interface hook functions to clean up */
+  ospf_if_free (oi);
+  
+#ifdef HAVE_SNMP
+  ospf_snmp_if_update (c->ifp);
+#endif /* HAVE_SNMP */
+
+  connected_free (c);
+
+  ospf_if_update();
+
+  return 0;
+}
+
+void
+ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
+{
+  u_char message;
+  u_char distance;
+  u_char flags;
+  int psize;
+  struct stream *s;
+  struct ospf_path *path;
+  listnode node;
+
+  if (zclient->redist[ZEBRA_ROUTE_OSPF])
+    {
+      message = 0;
+      flags = 0;
+
+      /* OSPF pass nexthop and metric */
+      SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
+      SET_FLAG (message, ZAPI_MESSAGE_METRIC);
+
+      /* Distance value. */
+      distance = ospf_distance_apply (p, or);
+      if (distance)
+	SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
+
+      /* Make packet. */
+      s = zclient->obuf;
+      stream_reset (s);
+
+      /* Length place holder. */
+      stream_putw (s, 0);
+
+      /* Put command, type, flags, message. */
+      stream_putc (s, ZEBRA_IPV4_ROUTE_ADD);
+      stream_putc (s, ZEBRA_ROUTE_OSPF);
+      stream_putc (s, flags);
+      stream_putc (s, message);
+  
+      /* Put prefix information. */
+      psize = PSIZE (p->prefixlen);
+      stream_putc (s, p->prefixlen);
+      stream_write (s, (u_char *)&p->prefix, psize);
+
+      /* Nexthop count. */
+      stream_putc (s, or->path->count);
+
+      /* Nexthop, ifindex, distance and metric information. */
+      for (node = listhead (or->path); node; nextnode (node))
+	{
+	  path = getdata (node);
+
+	  if (path->nexthop.s_addr != INADDR_ANY)
+	    {
+	      stream_putc (s, ZEBRA_NEXTHOP_IPV4);
+	      stream_put_in_addr (s, &path->nexthop);
+	    }
+	  else
+	    {
+	      stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
+	      if (path->oi)
+		stream_putl (s, path->oi->ifp->ifindex);
+	      else
+		stream_putl (s, 0);
+	    }
+	}
+
+      if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
+	stream_putc (s, distance);
+      if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
+	{
+	  if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
+	    stream_putl (s, or->cost + or->u.ext.type2_cost);
+	  else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
+	    stream_putl (s, or->u.ext.type2_cost);
+	  else
+	    stream_putl (s, or->cost);
+	}
+
+      stream_putw_at (s, 0, stream_get_endp (s));
+
+      writen (zclient->sock, s->data, stream_get_endp (s));
+
+#if 0
+      if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	{
+	  char *nexthop_str;
+
+	  nexthop_str = strdup (inet_ntoa (*nexthop));
+	  zlog_info ("Zebra: Route add %s/%d nexthop %s metric %d",
+		     inet_ntoa (p->prefix), p->prefixlen, nexthop_str,
+		     metric);
+	  free (nexthop_str);
+	}
+#endif /* 0 */
+    }
+}
+
+void
+ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
+{
+  struct zapi_ipv4 api;
+
+  if (zclient->redist[ZEBRA_ROUTE_OSPF])
+    {
+      api.type = ZEBRA_ROUTE_OSPF;
+      api.flags = 0;
+      api.message = 0;
+      zapi_ipv4_delete (zclient, p, &api);
+
+#if 0
+      if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	{
+	  char *nexthop_str;
+
+	  nexthop_str = strdup (inet_ntoa (*nexthop));
+	  zlog_info ("Zebra: Route delete %s/%d nexthop %s",
+		     inet_ntoa (p->prefix), p->prefixlen, nexthop_str);
+	  free (nexthop_str);
+	}
+#endif /* 0 */
+    }
+}
+
+void
+ospf_zebra_add_discard (struct prefix_ipv4 *p)
+{
+  struct zapi_ipv4 api;
+
+  if (zclient->redist[ZEBRA_ROUTE_OSPF])
+    {
+      api.type = ZEBRA_ROUTE_OSPF;
+      api.flags = ZEBRA_FLAG_BLACKHOLE;
+      api.message = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+      api.nexthop_num = 0;
+      api.ifindex_num = 0;
+
+      zapi_ipv4_add (zclient, p, &api);
+    }
+}
+
+void
+ospf_zebra_delete_discard (struct prefix_ipv4 *p)
+{
+  struct zapi_ipv4 api;
+
+  if (zclient->redist[ZEBRA_ROUTE_OSPF])
+    {
+      api.type = ZEBRA_ROUTE_OSPF;
+      api.flags = ZEBRA_FLAG_BLACKHOLE;
+      api.message = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+      api.nexthop_num = 0;
+      api.ifindex_num = 0;
+
+      zapi_ipv4_delete (zclient, p, &api);
+    }
+}
+
+int
+ospf_is_type_redistributed (int type)
+{
+  return (DEFAULT_ROUTE_TYPE (type)) ?
+    zclient->default_information : zclient->redist[type];
+}
+
+int
+ospf_redistribute_set (int type, int mtype, int mvalue)
+{
+  int force = 0;
+  
+  if (ospf_is_type_redistributed (type))
+    {
+      if (mtype != ospf_top->dmetric[type].type)
+	{
+	  ospf_top->dmetric[type].type = mtype;
+	  force = LSA_REFRESH_FORCE;
+	}
+      if (mvalue != ospf_top->dmetric[type].value)
+	{
+	  ospf_top->dmetric[type].value = mvalue;
+	  force = LSA_REFRESH_FORCE;
+	}
+	  
+      ospf_external_lsa_refresh_type (type, force);
+      
+      if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	zlog_info ("Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
+		   LOOKUP (ospf_redistributed_proto, type),
+		   metric_type (type), metric_value (type));
+      
+      return CMD_SUCCESS;
+    }
+
+  ospf_top->dmetric[type].type = mtype;
+  ospf_top->dmetric[type].value = mvalue;
+
+  zclient_redistribute_set (zclient, type);
+
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+    zlog_info ("Redistribute[%s]: Start  Type[%d], Metric[%d]",
+	       LOOKUP (ospf_redistributed_proto, type),
+	       metric_type (type), metric_value (type));
+  
+  ospf_asbr_status_update (++ospf_top->redistribute);
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_redistribute_unset (int type)
+{
+  if (type == zclient->redist_default)
+    return CMD_SUCCESS;
+
+  if (! ospf_is_type_redistributed (type))
+    return CMD_SUCCESS;
+
+  zclient_redistribute_unset (zclient, type);
+  
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+    zlog_info ("Redistribute[%s]: Stop",
+	       LOOKUP (ospf_redistributed_proto, type));
+
+  ospf_top->dmetric[type].type = -1;
+  ospf_top->dmetric[type].value = -1;
+
+  /* Remove the routes from OSPF table. */
+  ospf_redistribute_withdraw (type);
+
+  ospf_asbr_status_update (--ospf_top->redistribute);
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_redistribute_default_set (int originate, int mtype, int mvalue)
+{
+  int force = 0;
+  if (ospf_is_type_redistributed (DEFAULT_ROUTE))
+    {
+      if (mtype != ospf_top->dmetric[DEFAULT_ROUTE].type)
+	{
+	  ospf_top->dmetric[DEFAULT_ROUTE].type = mtype;
+	  force = 1;
+	}
+      if (mvalue != ospf_top->dmetric[DEFAULT_ROUTE].value)
+	{
+	  force = 1;
+	  ospf_top->dmetric[DEFAULT_ROUTE].value = mvalue;
+	}
+      
+      ospf_external_lsa_refresh_default ();
+      
+      if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	zlog_info ("Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
+		   LOOKUP (ospf_redistributed_proto, DEFAULT_ROUTE),
+		   metric_type (DEFAULT_ROUTE),
+		   metric_value (DEFAULT_ROUTE));
+      return CMD_SUCCESS;
+    }
+
+  ospf_top->default_originate = originate;
+  ospf_top->dmetric[DEFAULT_ROUTE].type = mtype;
+  ospf_top->dmetric[DEFAULT_ROUTE].value = mvalue;
+
+  zclient_redistribute_default_set (zclient);
+  
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+    zlog_info ("Redistribute[DEFAULT]: Start  Type[%d], Metric[%d]",
+	       metric_type (DEFAULT_ROUTE), metric_value (DEFAULT_ROUTE));
+
+
+  if (ospf_top->router_id.s_addr == 0)
+    ospf_top->external_origin |= (1 << DEFAULT_ROUTE);
+  else
+    thread_add_timer (master, ospf_default_originate_timer,
+		      &ospf_top->default_originate, 1);
+
+  ospf_asbr_status_update (++ospf_top->redistribute);
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_redistribute_default_unset ()
+{
+  if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
+    return CMD_SUCCESS;
+
+  ospf_top->default_originate = DEFAULT_ORIGINATE_NONE;
+  ospf_top->dmetric[DEFAULT_ROUTE].type = -1;
+  ospf_top->dmetric[DEFAULT_ROUTE].value = -1;
+
+  zclient_redistribute_default_unset (zclient);
+
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+    zlog_info ("Redistribute[DEFAULT]: Stop");
+  
+  ospf_asbr_status_update (--ospf_top->redistribute);
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_external_lsa_originate_check (struct external_info *ei)
+{
+  /* If prefix is multicast, then do not originate LSA. */
+  if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
+    {
+      zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
+		 "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
+      return 0;
+    }
+
+  /* Take care of default-originate. */
+  if (is_prefix_default (&ei->p))
+    if (ospf_top->default_originate == DEFAULT_ORIGINATE_NONE)
+      {
+	zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA "
+		   "for default");
+	return 0;
+      }
+
+  return 1;
+}
+
+/* If connected prefix is OSPF enable interface, then do not announce. */
+int
+ospf_distribute_check_connected (struct external_info *ei)
+{
+  struct route_node *rn;
+
+  for (rn = route_top (ospf_top->networks); rn; rn = route_next (rn))
+    if (rn->info != NULL)
+      if (prefix_match (&rn->p, (struct prefix *)&ei->p))
+	return 0;
+
+  return 1;
+}
+
+/* return 1 if external LSA must be originated, 0 otherwise */
+int
+ospf_redistribute_check (struct external_info *ei, int *changed)
+{
+  struct route_map_set_values save_values;
+  struct prefix_ipv4 *p = &ei->p;
+  u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
+  
+  if (changed)
+    *changed = 0;
+
+  if (!ospf_external_lsa_originate_check (ei))
+    return 0;
+
+  /* Take care connected route. */
+  if (type == ZEBRA_ROUTE_CONNECT && !ospf_distribute_check_connected (ei))
+    return 0;
+
+  if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (type))
+    /* distirbute-list exists, but access-list may not? */
+    if (DISTRIBUTE_LIST (type))
+      if (access_list_apply (DISTRIBUTE_LIST (type), p) == FILTER_DENY)
+	{
+	  if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	    zlog_info ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
+		       LOOKUP (ospf_redistributed_proto, type),
+		       inet_ntoa (p->prefix), p->prefixlen);
+	  return 0;
+	}
+
+  save_values = ei->route_map_set;
+  ospf_reset_route_map_set_values (&ei->route_map_set);
+  
+  /* apply route-map if needed */
+  if (ROUTEMAP_NAME (type))
+    {
+      int ret;
+
+      ret = route_map_apply (ROUTEMAP (type), (struct prefix *)p,
+			     RMAP_OSPF, ei);
+
+      if (ret == RMAP_DENYMATCH)
+	{
+	  ei->route_map_set = save_values;
+	  if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+	    zlog_info ("Redistribute[%s]: %s/%d filtered by route-map.",
+		       LOOKUP (ospf_redistributed_proto, type),
+		       inet_ntoa (p->prefix), p->prefixlen);
+	  return 0;
+	}
+      
+      /* check if 'route-map set' changed something */
+      if (changed)
+	*changed = !ospf_route_map_set_compare (&ei->route_map_set,
+						&save_values);
+    }
+
+  return 1;
+}
+
+/* OSPF route-map set for redistribution */
+void
+ospf_routemap_set (int type, char *name)
+{
+  if (ROUTEMAP_NAME (type))
+    free (ROUTEMAP_NAME (type));
+
+  ROUTEMAP_NAME (type) = strdup (name);
+  ROUTEMAP (type) = route_map_lookup_by_name (name);
+}
+
+void
+ospf_routemap_unset (int type)
+{
+  if (ROUTEMAP_NAME (type))
+    free (ROUTEMAP_NAME (type));
+
+  ROUTEMAP_NAME (type) = NULL;
+  ROUTEMAP (type) = NULL;
+}
+
+/* Zebra route add and delete treatment. */
+int
+ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
+		      zebra_size_t length)
+{
+  struct stream *s;
+  struct zapi_ipv4 api;
+  unsigned long ifindex;
+  struct in_addr nexthop;
+  struct prefix_ipv4 p;
+  struct external_info *ei;
+
+  s = zclient->ibuf;
+  ifindex = 0;
+  nexthop.s_addr = 0;
+
+  /* Type, flags, message. */
+  api.type = stream_getc (s);
+  api.flags = stream_getc (s);
+  api.message = stream_getc (s);
+
+  /* IPv4 prefix. */
+  memset (&p, 0, sizeof (struct prefix_ipv4));
+  p.family = AF_INET;
+  p.prefixlen = stream_getc (s);
+  stream_get (&p.prefix, s, PSIZE (p.prefixlen));
+
+  /* Nexthop, ifindex, distance, metric. */
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
+    {
+      api.nexthop_num = stream_getc (s);
+      nexthop.s_addr = stream_get_ipv4 (s);
+    }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
+    {
+      api.ifindex_num = stream_getc (s);
+      ifindex = stream_getl (s);
+    }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+    api.distance = stream_getc (s);
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+    api.metric = stream_getl (s);
+
+  if (command == ZEBRA_IPV4_ROUTE_ADD)
+    {
+      ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
+
+      if (ospf_top->router_id.s_addr == 0)
+	/* Set flags to generate AS-external-LSA originate event
+	   for each redistributed protocols later. */
+	ospf_top->external_origin |= (1 << api.type);
+      else
+	{
+	  if (ei)
+	    {
+	      if (is_prefix_default (&p))
+		ospf_external_lsa_refresh_default ();
+	      else
+		{
+		  struct ospf_lsa *current;
+
+		  current = ospf_external_info_find_lsa (&ei->p);
+		  if (!current)
+		    ospf_external_lsa_originate (ei);
+		  else if (IS_LSA_MAXAGE (current))
+		    ospf_external_lsa_refresh (current, ei, LSA_REFRESH_FORCE);
+		  else
+		    zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
+			       inet_ntoa (p.prefix));
+		}
+	    }
+	}
+    }
+  else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
+    {
+      ospf_external_info_delete (api.type, p);
+      if ( !is_prefix_default (&p))
+	ospf_external_lsa_flush (api.type, &p, ifindex, nexthop);
+      else
+	ospf_external_lsa_refresh_default ();
+    }
+
+  return 0;
+}
+
+
+int
+ospf_distribute_list_out_set (int type, char *name)
+{
+  /* Lookup access-list for distribute-list. */
+  DISTRIBUTE_LIST (type) = access_list_lookup (AFI_IP, name);
+
+  /* Clear previous distribute-name. */
+  if (DISTRIBUTE_NAME (type))
+    free (DISTRIBUTE_NAME (type));
+
+  /* Set distribute-name. */
+  DISTRIBUTE_NAME (type) = strdup (name);
+
+  /* If access-list have been set, schedule update timer. */
+  if (DISTRIBUTE_LIST (type))
+    ospf_distribute_list_update (type);
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_distribute_list_out_unset (int type, char *name)
+{
+  /* Schedule update timer. */
+  if (DISTRIBUTE_LIST (type))
+    ospf_distribute_list_update (type);
+
+  /* Unset distribute-list. */
+  DISTRIBUTE_LIST (type) = NULL;
+
+  /* Clear distribute-name. */
+  if (DISTRIBUTE_NAME (type))
+    free (DISTRIBUTE_NAME (type));
+  
+  DISTRIBUTE_NAME (type) = NULL;
+
+  return CMD_SUCCESS;
+}
+
+/* distribute-list update timer. */
+int
+ospf_distribute_list_update_timer (struct thread *thread)
+{
+  struct route_node *rn;
+  struct external_info *ei;
+  struct route_table *rt;
+  struct ospf_lsa *lsa;
+  u_char type;
+
+  type = (int) THREAD_ARG (thread);
+  rt = EXTERNAL_INFO (type);
+
+  ospf_top->t_distribute_update = NULL;
+
+  zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
+
+  /* foreach all external info. */
+  if (rt)
+    for (rn = route_top (rt); rn; rn = route_next (rn))
+      if ((ei = rn->info) != NULL)
+	{
+	  if (is_prefix_default (&ei->p))
+	    ospf_external_lsa_refresh_default ();
+	  else if ((lsa = ospf_external_info_find_lsa (&ei->p)))
+	    ospf_external_lsa_refresh (lsa, ei, LSA_REFRESH_IF_CHANGED);
+	  else
+	    ospf_external_lsa_originate (ei);
+	}
+  return 0;
+}
+
+#define OSPF_DISTRIBUTE_UPDATE_DELAY 5
+
+/* Update distribute-list and set timer to apply access-list. */
+void
+ospf_distribute_list_update (int type)
+{
+  struct route_table *rt;
+  
+  zlog_info ("ospf_distribute_list_update(): start");
+
+  /* External info does not exist. */
+  if (!(rt = EXTERNAL_INFO (type)))
+    return;
+
+  /* If exists previously invoked thread, then cancel it. */
+  if (ospf_top->t_distribute_update)
+    OSPF_TIMER_OFF (ospf_top->t_distribute_update);
+
+  /* Set timer. */
+  ospf_top->t_distribute_update =
+    thread_add_timer (master, ospf_distribute_list_update_timer,
+		      (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
+
+  zlog_info ("ospf_distribute_list_update(): stop");
+}
+
+/* If access-list is updated, apply some check. */
+void
+ospf_filter_update (struct access_list *access)
+{
+  int type;
+  int abr_inv = 0;
+  struct ospf_area *area;
+  listnode node;
+
+  /* If OSPF instatnce does not exist, return right now. */
+  if (!ospf_top)
+    return;
+
+
+  /* Update distribute-list, and apply filter. */
+  for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+    {
+      if (ROUTEMAP (type) != NULL)
+	{
+	  /* if route-map is not NULL it may be using this access list */
+	  ospf_distribute_list_update (type);
+	  continue;
+	}
+      
+
+      if (DISTRIBUTE_NAME (type))
+	{
+	  /* Keep old access-list for distribute-list. */
+	  struct access_list *old = DISTRIBUTE_LIST (type);
+	  
+	  /* Update access-list for distribute-list. */
+	  DISTRIBUTE_LIST (type) =
+	    access_list_lookup (AFI_IP, DISTRIBUTE_NAME (type));
+	  
+	  /* No update for this distribute type. */
+	  if (old == NULL && DISTRIBUTE_LIST (type) == NULL)
+	    continue;
+	  
+	  /* Schedule distribute-list update timer. */
+	  if (DISTRIBUTE_LIST (type) == NULL ||
+	      strcmp (DISTRIBUTE_NAME (type), access->name) == 0)
+	    ospf_distribute_list_update (type);
+	}
+    }
+
+  /* Update Area access-list. */
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    if ((area = getdata (node)) != NULL)
+      {
+	if (EXPORT_NAME (area))
+	  {
+	    EXPORT_LIST (area) = NULL;
+	    abr_inv++;
+	  }
+
+	if (IMPORT_NAME (area))
+	  {
+	    IMPORT_LIST (area) = NULL;
+	    abr_inv++;
+	  }
+      }
+
+  /* Schedule ABR tasks -- this will be changed -- takada. */
+  if (OSPF_IS_ABR && abr_inv)
+    ospf_schedule_abr_task ();
+}
+
+
+struct ospf_distance *
+ospf_distance_new ()
+{
+  struct ospf_distance *new;
+  new = XMALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
+  memset (new, 0, sizeof (struct ospf_distance));
+  return new;
+}
+
+void
+ospf_distance_free (struct ospf_distance *odistance)
+{
+  XFREE (MTYPE_OSPF_DISTANCE, odistance);
+}
+
+int
+ospf_distance_set (struct vty *vty, char *distance_str, char *ip_str,
+		   char *access_list_str)
+{
+  int ret;
+  struct prefix_ipv4 p;
+  u_char distance;
+  struct route_node *rn;
+  struct ospf_distance *odistance;
+
+  ret = str2prefix_ipv4 (ip_str, &p);
+  if (ret == 0)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  distance = atoi (distance_str);
+
+  /* Get OSPF distance node. */
+  rn = route_node_get (ospf_top->distance_table, (struct prefix *) &p);
+  if (rn->info)
+    {
+      odistance = rn->info;
+      route_unlock_node (rn);
+    }
+  else
+    {
+      odistance = ospf_distance_new ();
+      rn->info = odistance;
+    }
+
+  /* Set distance value. */
+  odistance->distance = distance;
+
+  /* Reset access-list configuration. */
+  if (odistance->access_list)
+    {
+      free (odistance->access_list);
+      odistance->access_list = NULL;
+    }
+  if (access_list_str)
+    odistance->access_list = strdup (access_list_str);
+
+  return CMD_SUCCESS;
+}
+
+int
+ospf_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
+		     char *access_list_str)
+{
+  int ret;
+  struct prefix_ipv4 p;
+  u_char distance;
+  struct route_node *rn;
+  struct ospf_distance *odistance;
+
+  ret = str2prefix_ipv4 (ip_str, &p);
+  if (ret == 0)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  distance = atoi (distance_str);
+
+  rn = route_node_lookup (ospf_top->distance_table, (struct prefix *)&p);
+  if (! rn)
+    {
+      vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  odistance = rn->info;
+
+  if (odistance->access_list)
+    free (odistance->access_list);
+  ospf_distance_free (odistance);
+
+  rn->info = NULL;
+  route_unlock_node (rn);
+  route_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+void
+ospf_distance_reset ()
+{
+  struct route_node *rn;
+  struct ospf_distance *odistance;
+
+  for (rn = route_top (ospf_top->distance_table); rn; rn = route_next (rn))
+    if ((odistance = rn->info) != NULL)
+      {
+	if (odistance->access_list)
+	  free (odistance->access_list);
+	ospf_distance_free (odistance);
+	rn->info = NULL;
+	route_unlock_node (rn);
+      }
+}
+
+u_char
+ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
+{
+#if 0
+  struct route_node *rn;
+  struct ospf_distance *odistance;
+  struct access_list *alist;
+  struct prefix_ipv4 q;
+
+  memset (&q, 0, sizeof (struct prefix_ipv4));
+  q.family = AF_INET;
+  /* q.prefix =  */
+  q.prefixlen = IPV4_MAX_BITLEN;
+#endif /* 0 */
+
+  if (! ospf_top)
+    return 0;
+
+#if 0
+  rn = route_node_match (ospf_top->distance_table, (struct prefix *) &q);
+  if (rn)
+    {
+      odistance = rn->info;
+      route_unlock_node (rn);
+
+      if (odistance->access_list)
+	{
+	  alist = access_list_lookup (AFI_IP, odistance->access_list);
+	  if (alist == NULL)
+	    return 0;
+	  if (access_list_apply (alist, (struct prefix *) p) == FILTER_DENY)
+	    return 0;
+
+	  return odistance->distance;
+	}
+      else
+	return odistance->distance;
+    }
+#endif /* 0 */
+
+  if (ospf_top->distance_intra)
+    if (or->path_type == OSPF_PATH_INTRA_AREA)
+      return ospf_top->distance_intra;
+
+  if (ospf_top->distance_inter)
+    if (or->path_type == OSPF_PATH_INTER_AREA)
+      return ospf_top->distance_inter;
+
+  if (ospf_top->distance_external)
+    if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
+	|| or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
+      return ospf_top->distance_external;
+  
+  if (ospf_top->distance_all)
+    return ospf_top->distance_all;
+
+  return 0;
+}
+
+void
+ospf_zebra_init ()
+{
+  /* Allocate zebra structure. */
+  zclient = zclient_new ();
+  zclient_init (zclient, ZEBRA_ROUTE_OSPF);
+  zclient->interface_add = ospf_interface_add;
+  zclient->interface_delete = ospf_interface_delete;
+  zclient->interface_up = ospf_interface_state_up;
+  zclient->interface_down = ospf_interface_state_down;
+  zclient->interface_address_add = ospf_interface_address_add;
+  zclient->interface_address_delete = ospf_interface_address_delete;
+  zclient->ipv4_route_add = ospf_zebra_read_ipv4;
+  zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
+
+  access_list_add_hook (ospf_filter_update);
+  access_list_delete_hook (ospf_filter_update);
+}
diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h
new file mode 100644
index 0000000..5dbf573
--- /dev/null
+++ b/ospfd/ospf_zebra.h
@@ -0,0 +1,78 @@
+/*
+ * Zebra connect library for OSPFd
+ * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA. 
+ */
+
+#ifndef _ZEBRA_OSPF_ZEBRA_H
+#define _ZEBRA_OSPF_ZEBRA_H
+
+#define EXTERNAL_METRIC_TYPE_1      0
+#define EXTERNAL_METRIC_TYPE_2      1
+
+#define DEFAULT_ROUTE		    ZEBRA_ROUTE_MAX
+#define DEFAULT_ROUTE_TYPE(T) ((T) == DEFAULT_ROUTE)
+
+/* OSPF distance. */
+struct ospf_distance
+{
+  /* Distance value for the IP source prefix. */
+  u_char distance;
+
+  /* Name of the access-list to be matched. */
+  char *access_list;
+};
+
+/* Prototypes */
+void ospf_zclient_start ();
+
+void ospf_zebra_add (struct prefix_ipv4 *, struct ospf_route *);
+void ospf_zebra_delete (struct prefix_ipv4 *, struct ospf_route *);
+
+void ospf_zebra_add_discard (struct prefix_ipv4 *);
+void ospf_zebra_delete_discard (struct prefix_ipv4 *);
+
+int ospf_default_originate_timer (struct thread *);
+
+int ospf_redistribute_check (struct external_info *, int *);
+int ospf_distribute_check_connected (struct external_info *);
+void ospf_distribute_list_update (int);
+
+int ospf_is_type_redistributed (int);
+int ospf_redistribute_unset (int);
+
+void ospf_distance_reset ();
+u_char ospf_distance_apply (struct prefix_ipv4 *, struct ospf_route *);
+
+struct vty;
+
+int ospf_redistribute_set (int, int, int);
+int ospf_redistribute_unset (int);
+int ospf_redistribute_default_set (int, int, int);
+int ospf_redistribute_default_unset ();
+int ospf_distribute_list_out_set (int, char *);
+int ospf_distribute_list_out_unset (int, char *);
+void ospf_routemap_set (int, char *);
+void ospf_routemap_unset (int);
+int ospf_distance_set (struct vty *, char *, char *, char *);
+int ospf_distance_unset (struct vty *, char *, char *, char *);
+void ospf_zebra_init ();
+
+#endif /* _ZEBRA_OSPF_ZEBRA_H */
+
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
new file mode 100644
index 0000000..e7de8ea
--- /dev/null
+++ b/ospfd/ospfd.c
@@ -0,0 +1,1603 @@
+/* OSPF version 2 daemon program.
+   Copyright (C) 1999, 2000 Toshiaki Takada
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "vty.h"
+#include "command.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "table.h"
+#include "if.h"
+#include "memory.h"
+#include "stream.h"
+#include "log.h"
+#include "sockunion.h"          /* for inet_aton () */
+#include "zclient.h"
+#include "plist.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_network.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_ase.h"
+
+/* OSPF instance top. */
+struct ospf *ospf_top;
+
+extern struct zclient *zclient;
+
+
+void ospf_remove_vls_through_area (struct ospf_area *);
+void ospf_network_free (struct ospf_network *);
+void ospf_area_free (struct ospf_area *);
+void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
+
+/* Get Router ID from ospf interface list. */
+struct in_addr
+ospf_router_id_get (list if_list)
+{
+  listnode node;
+  struct in_addr router_id;
+
+  memset (&router_id, 0, sizeof (struct in_addr));
+
+  for (node = listhead (if_list); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+
+      if (!if_is_up (oi->ifp) ||
+	  OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+	continue;
+      
+      /* Ignore virtual link interface. */
+      if (oi->type != OSPF_IFTYPE_VIRTUALLINK &&
+	  oi->type != OSPF_IFTYPE_LOOPBACK) 
+	if (IPV4_ADDR_CMP (&router_id, &oi->address->u.prefix4) < 0)
+	  router_id = oi->address->u.prefix4;
+    }
+
+  return router_id;
+}
+
+#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
+
+void
+ospf_router_id_update ()
+{
+  listnode node;
+  struct in_addr router_id, router_id_old;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Router-ID[OLD:%s]: Update",inet_ntoa (ospf_top->router_id));
+
+  router_id_old = ospf_top->router_id;
+
+  if (ospf_top->router_id_static.s_addr != 0)
+    router_id = ospf_top->router_id_static;
+  else
+    router_id = ospf_router_id_get (ospf_top->oiflist);
+
+  ospf_top->router_id = router_id;
+  
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf_top->router_id));
+
+  if (!IPV4_ADDR_SAME (&router_id_old, &router_id))
+    {
+      for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+        {
+	  struct ospf_interface *oi = getdata (node);
+
+          /* Update self-neighbor's router_id. */
+          oi->nbr_self->router_id = router_id;
+        }
+
+      /* If AS-external-LSA is queued, then flush those LSAs. */
+      if (router_id_old.s_addr == 0 && ospf_top->external_origin)
+	{
+	  int type;
+	  /* Originate each redistributed external route. */
+	  for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+	    if (ospf_top->external_origin & (1 << type))
+	      thread_add_event (master, ospf_external_lsa_originate_timer,
+				NULL, type);
+	  /* Originate Deafult. */
+	  if (ospf_top->external_origin & (1 << ZEBRA_ROUTE_MAX))
+	    thread_add_event (master, ospf_default_originate_timer,
+			      &ospf_top->default_originate, 0);
+
+	  ospf_top->external_origin = 0;
+	}
+
+      OSPF_TIMER_ON (ospf_top->t_router_lsa_update,
+		     ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
+    }
+}
+
+int
+ospf_router_id_update_timer (struct thread *thread)
+{
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Router-ID: Update timer fired!");
+
+  ospf_top->t_router_id_update = NULL;
+  ospf_router_id_update ();
+
+  return 0;
+}
+
+/* For OSPF area sort by area id. */
+int
+ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2)
+{
+  if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr))
+    return 1;
+  if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr))
+    return -1;
+  return 0;
+}
+
+/* Allocate new ospf structure. */
+struct ospf *
+ospf_new ()
+{
+  int i;
+
+  struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf));
+
+  new->router_id.s_addr = htonl (0);
+  new->router_id_static.s_addr = htonl (0);
+
+  new->abr_type = OSPF_ABR_STAND;
+  new->iflist = iflist;
+  new->oiflist = list_new ();
+  new->vlinks = list_new ();
+  new->areas = list_new ();
+  new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp;
+  new->networks = route_table_init ();
+  new->nbr_nbma = route_table_init ();
+
+  new->lsdb = ospf_lsdb_new ();
+
+  new->default_originate = DEFAULT_ORIGINATE_NONE;
+
+  new->new_external_route = route_table_init ();
+  new->old_external_route = route_table_init ();
+  new->external_lsas = route_table_init ();
+
+  /* Distribute parameter init. */
+  for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
+    {
+      new->dmetric[i].type = -1;
+      new->dmetric[i].value = -1;
+    }
+  new->default_metric = -1;
+  new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH;
+
+  /* SPF timer value init. */
+  new->spf_delay = OSPF_SPF_DELAY_DEFAULT;
+  new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
+
+  /* MaxAge init. */
+  new->maxage_lsa = list_new ();
+  new->t_maxage_walker =
+    thread_add_timer (master, ospf_lsa_maxage_walker,
+                      NULL, OSPF_LSA_MAXAGE_CHECK_INTERVAL);
+
+  /* Distance table init. */
+  new->distance_table = route_table_init ();
+
+  new->lsa_refresh_queue.index = 0;
+  new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
+  new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
+					   new, new->lsa_refresh_interval);
+  new->lsa_refresher_started = time (NULL);
+
+  new->fd = ospf_sock_init ();
+  if (new->fd >= 0)
+    new->t_read = thread_add_read (master, ospf_read, new, new->fd);
+  new->oi_write_q = list_new ();
+  
+  return new;
+}
+
+struct ospf *
+ospf_get ()
+{
+  if (ospf_top != NULL)
+    return ospf_top;
+
+  ospf_top = ospf_new ();
+
+  if (ospf_top->router_id_static.s_addr == 0)
+    ospf_router_id_update ();
+
+#ifdef HAVE_OPAQUE_LSA
+  ospf_opaque_type11_lsa_init (ospf_top);
+#endif /* HAVE_OPAQUE_LSA */
+
+  return ospf_top;
+}
+
+void
+ospf_finish (struct ospf *ospf)
+{
+  struct route_node *rn;
+  struct ospf_nbr_nbma *nbr_nbma;
+  listnode node;
+  int i;
+
+#ifdef HAVE_OPAQUE_LSA
+  ospf_opaque_type11_lsa_term (ospf);
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* Unredister redistribution */
+  for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+    ospf_redistribute_unset (i);
+
+  for (node = listhead (ospf->areas); node;)
+    {
+      struct ospf_area *area = getdata (node);
+      nextnode (node);
+      
+      ospf_remove_vls_through_area (area);
+    }
+  
+  for (node = listhead (ospf->vlinks); node; )
+    {
+      struct ospf_vl_data *vl_data = node->data;
+      nextnode (node);
+      
+      ospf_vl_delete (vl_data);
+    }
+  
+  list_delete (ospf->vlinks);
+
+  /* Reset interface. */
+  for (node = listhead (ospf->oiflist); node;)
+    {
+      struct ospf_interface *oi = getdata (node);
+      nextnode (node);
+      
+      if (oi)
+	ospf_if_free (oi);
+    }
+
+  /* Clear static neighbors */
+  for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn))
+    if ((nbr_nbma = rn->info))
+      {
+	OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
+
+	if (nbr_nbma->nbr)
+	  {
+	    nbr_nbma->nbr->nbr_nbma = NULL;
+	    nbr_nbma->nbr = NULL;
+	  }
+
+	if (nbr_nbma->oi)
+	  {
+	    listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
+	    nbr_nbma->oi = NULL;
+	  }
+
+	XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
+      }
+
+  route_table_finish (ospf->nbr_nbma);
+
+  /* Clear networks and Areas. */
+  for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
+    {
+      struct ospf_network *network;
+
+      if ((network = rn->info) != NULL)
+	{
+	  ospf_network_free (network);
+	  rn->info = NULL;
+	  route_unlock_node (rn);
+	}
+    }
+
+  for (node = listhead (ospf->areas); node;)
+    {
+      struct ospf_area *area = getdata (node);
+      nextnode (node);
+      
+      listnode_delete (ospf->areas, area);
+      ospf_area_free (area);
+    }
+
+  /* Cancel all timers. */
+  OSPF_TIMER_OFF (ospf->t_external_lsa);
+  OSPF_TIMER_OFF (ospf->t_router_id_update);
+  OSPF_TIMER_OFF (ospf->t_router_lsa_update);
+  OSPF_TIMER_OFF (ospf->t_spf_calc);
+  OSPF_TIMER_OFF (ospf->t_ase_calc);
+  OSPF_TIMER_OFF (ospf->t_maxage);
+  OSPF_TIMER_OFF (ospf->t_maxage_walker);
+  OSPF_TIMER_OFF (ospf->t_abr_task);
+  OSPF_TIMER_OFF (ospf->t_distribute_update);
+  OSPF_TIMER_OFF (ospf->t_lsa_refresher);
+  OSPF_TIMER_OFF (ospf->t_read);
+  OSPF_TIMER_OFF (ospf->t_write);
+
+  close (ospf->fd);
+   
+#ifdef HAVE_OPAQUE_LSA
+  foreach_lsa (OPAQUE_AS_LSDB (ospf), ospf_top->lsdb, 0,
+	       ospf_lsa_discard_callback);
+#endif /* HAVE_OPAQUE_LSA */
+  foreach_lsa (EXTERNAL_LSDB (ospf), ospf->lsdb, 0,
+	       ospf_lsa_discard_callback);
+  ospf_lsdb_delete_all (ospf->lsdb);
+  ospf_lsdb_free (ospf->lsdb);
+
+  for (node = listhead (ospf->maxage_lsa); node; nextnode (node))
+    ospf_lsa_unlock (getdata (node));
+
+  list_delete (ospf->maxage_lsa);
+
+  if (ospf->old_table)
+    ospf_route_table_free (ospf->old_table);
+  if (ospf->new_table)
+    {
+      ospf_route_delete (ospf->new_table);
+      ospf_route_table_free (ospf->new_table);
+    }
+  if (ospf->old_rtrs)
+    ospf_rtrs_free (ospf->old_rtrs);
+  if (ospf->new_rtrs)
+    ospf_rtrs_free (ospf->new_rtrs);
+  if (ospf->new_external_route)
+    {
+      ospf_route_delete (ospf->new_external_route);
+      ospf_route_table_free (ospf->new_external_route);
+    }
+  if (ospf->old_external_route)
+    {
+      ospf_route_delete (ospf->old_external_route);
+      ospf_route_table_free (ospf->old_external_route);
+    }
+  if (ospf->external_lsas)
+    {
+      ospf_ase_external_lsas_finish (ospf->external_lsas);
+    }
+
+  list_delete (ospf->areas);
+  
+  for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++)
+    if (EXTERNAL_INFO (i) != NULL)
+      for (rn = route_top (EXTERNAL_INFO (i)); rn; rn = route_next (rn))
+	{
+	  if (rn->info == NULL)
+	    continue;
+	  
+	  XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info);
+	  rn->info = NULL;
+	  route_unlock_node (rn);
+	}
+
+  ospf_distance_reset ();
+  route_table_finish (ospf->distance_table);
+
+  XFREE (MTYPE_OSPF_TOP, ospf);
+
+  ospf_top = NULL;
+}
+
+
+/* allocate new OSPF Area object */
+struct ospf_area *
+ospf_area_new (struct in_addr area_id)
+{
+  struct ospf_area *new;
+
+  /* Allocate new config_network. */
+  new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area));
+
+  new->top = ospf_top;
+
+  new->area_id = area_id;
+
+  new->external_routing = OSPF_AREA_DEFAULT;
+  new->default_cost = 1;
+  new->auth_type = OSPF_AUTH_NULL;
+
+  /* New LSDB init. */
+  new->lsdb = ospf_lsdb_new ();
+
+  /* Self-originated LSAs initialize. */
+  new->router_lsa_self = NULL;
+
+#ifdef HAVE_OPAQUE_LSA
+  ospf_opaque_type10_lsa_init (new);
+#endif /* HAVE_OPAQUE_LSA */
+
+  new->oiflist = list_new ();
+  new->ranges = route_table_init ();
+
+  if (area_id.s_addr == OSPF_AREA_BACKBONE)
+    ospf_top->backbone = new;
+
+  return new;
+}
+
+void
+ospf_area_free (struct ospf_area *area)
+{
+  /* Free LSDBs. */
+  foreach_lsa (ROUTER_LSDB (area), area->lsdb, 0, ospf_lsa_discard_callback);
+  foreach_lsa (NETWORK_LSDB (area), area->lsdb, 0, ospf_lsa_discard_callback);
+  foreach_lsa (SUMMARY_LSDB (area), area->lsdb, 0, ospf_lsa_discard_callback);
+  foreach_lsa (ASBR_SUMMARY_LSDB (area), area->lsdb, 0,
+	       ospf_lsa_discard_callback);
+
+#ifdef HAVE_NSSA
+  foreach_lsa (NSSA_LSDB (area), area->lsdb, 0, ospf_lsa_discard_callback);
+#endif /* HAVE_NSSA */
+#ifdef HAVE_OPAQUE_LSA
+  foreach_lsa (OPAQUE_AREA_LSDB (area), area->lsdb, 0,
+               ospf_lsa_discard_callback);
+  foreach_lsa (OPAQUE_LINK_LSDB (area), area->lsdb, 0,
+               ospf_lsa_discard_callback);
+#endif /* HAVE_OPAQUE_LSA */
+
+  ospf_lsdb_delete_all (area->lsdb);
+  ospf_lsdb_free (area->lsdb);
+
+#ifdef HAVE_OPAQUE_LSA
+  ospf_opaque_type10_lsa_term (area);
+#endif /* HAVE_OPAQUE_LSA */
+  ospf_lsa_unlock (area->router_lsa_self);
+  
+  route_table_finish (area->ranges);
+  list_delete (area->oiflist);
+
+  if (EXPORT_NAME (area))
+    free (EXPORT_NAME (area));
+
+  if (IMPORT_NAME (area))
+    free (IMPORT_NAME (area));
+
+  /* Cancel timer. */
+  OSPF_TIMER_OFF (area->t_router_lsa_self);
+
+  if (OSPF_IS_AREA_BACKBONE (area))
+    ospf_top->backbone = NULL;
+
+  XFREE (MTYPE_OSPF_AREA, area);
+}
+
+void
+ospf_area_check_free (struct in_addr area_id)
+{
+  struct ospf_area *area;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area &&
+      listcount (area->oiflist) == 0 &&
+      area->ranges->top == NULL &&
+      area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
+      area->external_routing == OSPF_AREA_DEFAULT &&
+      area->no_summary == 0 &&
+      area->default_cost == 1 &&
+      EXPORT_NAME (area) == NULL &&
+      IMPORT_NAME (area) == NULL &&
+      area->auth_type == OSPF_AUTH_NULL)
+    {
+      listnode_delete (ospf_top->areas, area);
+      ospf_area_free (area);
+    }
+}
+
+struct ospf_area *
+ospf_area_get (struct in_addr area_id, int format)
+{
+  struct ospf_area *area;
+  
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (!area)
+    {
+      area = ospf_area_new (area_id);
+      area->format = format;
+      listnode_add_sort (ospf_top->areas, area);
+      ospf_check_abr_status ();  
+    }
+
+  return area;
+}
+
+struct ospf_area *
+ospf_area_lookup_by_area_id (struct in_addr area_id)
+{
+  struct ospf_area *area;
+  listnode node;
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      if (IPV4_ADDR_SAME (&area->area_id, &area_id))
+        return area;
+    }
+
+  return NULL;
+}
+
+void
+ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi)
+{
+  listnode_add (area->oiflist, oi);
+}
+
+void
+ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi)
+{
+  listnode_delete (area->oiflist, oi);
+}
+
+
+/* Config network statement related functions. */
+struct ospf_network *
+ospf_network_new (struct in_addr area_id, int format)
+{
+  struct ospf_network *new;
+  new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network));
+
+  new->area_id = area_id;
+  new->format = format;
+  
+  return new;
+}
+
+void
+ospf_network_free (struct ospf_network *network)
+{
+  ospf_area_check_free (network->area_id);
+  ospf_schedule_abr_task ();
+  XFREE (MTYPE_OSPF_NETWORK, network);
+}
+
+int
+ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
+		  struct in_addr area_id)
+{
+  struct ospf_network *network;
+  struct ospf_area *area;
+  struct route_node *rn;
+  struct external_info *ei;
+  int ret = OSPF_AREA_ID_FORMAT_DECIMAL;
+
+  rn = route_node_get (ospf->networks, (struct prefix *)p);
+  if (rn->info)
+    {
+      /* There is already same network statement. */
+      route_unlock_node (rn);
+      return 0;
+    }
+
+  rn->info = network = ospf_network_new (area_id, ret);
+  area = ospf_area_get (area_id, ret);
+
+  /* Run network config now. */
+  ospf_network_run (ospf, (struct prefix *)p, area);
+
+  /* Update connected redistribute. */
+  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
+    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
+      for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
+	   rn; rn = route_next (rn))
+	if ((ei = rn->info) != NULL)
+	  if (ospf_external_info_find_lsa (&ei->p))
+	    if (!ospf_distribute_check_connected (ei))
+	      ospf_external_lsa_flush (ei->type, &ei->p,
+				       ei->ifindex, ei->nexthop);
+
+  ospf_area_check_free (area_id);
+
+  return 1;
+}
+
+int
+ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
+		    struct in_addr area_id)
+{
+  struct route_node *rn;
+  struct ospf_network *network;
+  struct external_info *ei;
+
+  rn = route_node_lookup (ospf->networks, (struct prefix *)p);
+  if (rn == NULL)
+    return 0;
+
+  network = rn->info;
+  if (!IPV4_ADDR_SAME (&area_id, &network->area_id))
+    return 0;
+
+  ospf_network_free (rn->info);
+  rn->info = NULL;
+  route_unlock_node (rn);
+
+  ospf_if_update ();
+  
+  /* Update connected redistribute. */
+  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
+    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
+      for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
+	   rn; rn = route_next (rn))
+	if ((ei = rn->info) != NULL)
+	  if (!ospf_external_info_find_lsa (&ei->p))
+	    if (ospf_distribute_check_connected (ei))
+	      ospf_external_lsa_originate (ei);
+
+  return 1;
+}
+
+
+void
+ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
+{
+  struct interface *ifp;
+  listnode node;
+
+  /* Schedule Router ID Update. */
+  if (ospf->router_id_static.s_addr == 0)
+    if (ospf->t_router_id_update == NULL)
+      {
+	ospf->t_router_id_update = 
+	  thread_add_timer (master, ospf_router_id_update_timer, ospf,
+			    OSPF_ROUTER_ID_UPDATE_DELAY);
+      }
+
+  /* Get target interface. */
+  for (node = listhead (ospf->iflist); node; nextnode (node))
+    {
+      listnode cn;
+      
+      if ((ifp = getdata (node)) == NULL)
+	continue;
+
+      if (memcmp (ifp->name, "VLINK", 5) == 0)
+	continue;
+	
+      /* if interface prefix is match specified prefix,
+	 then create socket and join multicast group. */
+      for (cn = listhead (ifp->connected); cn; nextnode (cn))
+	{
+	  struct connected *co = getdata (cn);
+	  struct prefix *addr;
+
+	  if (if_is_pointopoint (ifp))
+	    addr = co->destination;
+	  else 
+	    addr = co->address;
+
+	  if (p->family == co->address->family &&
+	      ! ospf_if_is_configured (&(addr->u.prefix4)))
+	    if ((if_is_pointopoint (ifp) &&
+		 IPV4_ADDR_SAME (&(addr->u.prefix4), &(p->u.prefix4))) ||
+		prefix_match (p, addr)) 
+	    {
+	        struct ospf_interface *oi;
+		
+		oi = ospf_if_new (ifp, co->address);
+		oi->connected = co;
+		
+		oi->nbr_self->address = *oi->address;
+
+		area->act_ints++;
+		oi->area = area;
+
+		oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
+		oi->output_cost = ospf_if_get_output_cost (oi);
+		
+		if (area->external_routing != OSPF_AREA_DEFAULT)
+		  UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+		oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
+		
+		/* Add pseudo neighbor. */
+		ospf_nbr_add_self (oi);
+
+		/* Make sure pseudo neighbor's router_id. */
+		oi->nbr_self->router_id = ospf_top->router_id;
+		oi->nbr_self->src = oi->address->u.prefix4;
+		
+		/* Relate ospf interface to ospf instance. */
+		oi->ospf = ospf_top;
+
+		/* update network type as interface flag */
+		/* If network type is specified previously,
+		   skip network type setting. */
+		oi->type = IF_DEF_PARAMS (ifp)->type;
+		
+		/* Set area flag. */
+		switch (area->external_routing)
+		  {
+		  case OSPF_AREA_DEFAULT:
+		    SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+		    break;
+		  case OSPF_AREA_STUB:
+		    UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+		    break;
+#ifdef HAVE_NSSA
+		  case OSPF_AREA_NSSA:
+		    UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+		    SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
+		    break;
+#endif /* HAVE_NSSA */
+		  }
+
+		ospf_area_add_if (oi->area, oi);
+
+		if (if_is_up (ifp)) 
+		  ospf_if_up (oi);
+
+		break;
+	      }
+	}
+    }
+}
+
+void
+ospf_ls_upd_queue_empty (struct ospf_interface *oi)
+{
+  struct route_node *rn;
+  listnode node;
+  list lst;
+  struct ospf_lsa *lsa;
+
+  /* empty ls update queue */
+  for (rn = route_top (oi->ls_upd_queue); rn;
+       rn = route_next (rn))
+    if ((lst = (list) rn->info))
+      {
+	for (node = listhead (lst); node; nextnode (node))
+	  if ((lsa = getdata (node)))
+	    ospf_lsa_unlock (lsa);
+	list_free (lst);
+	rn->info = NULL;
+      }
+  
+  /* remove update event */
+  if (oi->t_ls_upd_event)
+    {
+      thread_cancel (oi->t_ls_upd_event);
+      oi->t_ls_upd_event = NULL;
+    }
+}
+
+void
+ospf_if_update ()
+{
+  struct route_node *rn;
+  listnode node;
+  listnode next;
+  struct ospf_network *network;
+  struct ospf_area *area;
+
+  if (ospf_top != NULL)
+    {
+      /* Update Router ID scheduled. */
+      if (ospf_top->router_id_static.s_addr == 0)
+        if (ospf_top->t_router_id_update == NULL)
+          {
+            ospf_top->t_router_id_update =
+              thread_add_timer (master, ospf_router_id_update_timer, NULL,
+                                OSPF_ROUTER_ID_UPDATE_DELAY);
+          }
+
+      /* Find interfaces that not configured already.  */
+      for (node = listhead (ospf_top->oiflist); node; node = next)
+	{
+	  int found = 0;
+	  struct ospf_interface *oi = getdata (node);
+	  struct connected *co = oi->connected;
+	  
+	  next = nextnode (node);
+
+	  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+	    continue;
+	  
+	  for (rn = route_top (ospf_top->networks); rn; rn = route_next (rn))
+	    {
+	      if (rn->info == NULL)
+		continue;
+	      
+	      if ((oi->type == OSPF_IFTYPE_POINTOPOINT
+		   && IPV4_ADDR_SAME (&(co->destination->u.prefix4),
+				      &(rn->p.u.prefix4)))
+		  || prefix_match (&(rn->p), co->address))
+		{
+		  found = 1;
+		  route_unlock_node (rn);
+		  break;
+		}
+	    }
+
+	  if (found == 0)
+	    ospf_if_free (oi);
+	}
+	
+      /* Run each interface. */
+      for (rn = route_top (ospf_top->networks); rn; rn = route_next (rn))
+	if (rn->info != NULL)
+	  {
+	    network = (struct ospf_network *) rn->info;
+	    area = ospf_area_get (network->area_id, network->format);
+	    ospf_network_run (ospf_top, &rn->p, area);
+	  }
+    }
+}
+
+void
+ospf_remove_vls_through_area (struct ospf_area *area)
+{
+  listnode node, next;
+  struct ospf_vl_data *vl_data;
+
+  for (node = listhead (ospf_top->vlinks); node; node = next)
+    {
+      next = node->next;
+      if ((vl_data = getdata (node)) != NULL)
+	if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
+	  ospf_vl_delete (vl_data);
+    }
+}
+
+
+struct message ospf_area_type_msg[] =
+{
+  { OSPF_AREA_DEFAULT,	"Default" },
+  { OSPF_AREA_STUB,     "Stub" },
+  { OSPF_AREA_NSSA,     "NSSA" },
+};
+int ospf_area_type_msg_max = OSPF_AREA_TYPE_MAX;
+
+void
+ospf_area_type_set (struct ospf_area *area, int type)
+{
+  listnode node;
+  struct ospf_interface *oi;
+
+  if (area->external_routing == type)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("Area[%s]: Types are the same, ignored.",
+		   inet_ntoa (area->area_id));
+      return;
+    }
+
+  area->external_routing = type;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("Area[%s]: Configured as %s", inet_ntoa (area->area_id),
+	       LOOKUP (ospf_area_type_msg, type));
+
+  switch (area->external_routing)
+    {
+    case OSPF_AREA_DEFAULT:
+      for (node = listhead (area->oiflist); node; nextnode (node))
+	if ((oi = getdata (node)) != NULL)
+	  if (oi->nbr_self != NULL)
+	    SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+      break;
+    case OSPF_AREA_STUB:
+      for (node = listhead (area->oiflist); node; nextnode (node))
+	if ((oi = getdata (node)) != NULL)
+	  if (oi->nbr_self != NULL)
+	    {
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("setting options on %s accordingly", IF_NAME (oi));
+	      UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+	      if (IS_DEBUG_OSPF_EVENT)
+		zlog_info ("options set on %s: %x",
+			   IF_NAME (oi), OPTIONS (oi));
+	    }
+      break;
+    case OSPF_AREA_NSSA:
+#ifdef HAVE_NSSA
+      for (node = listhead (area->oiflist); node; nextnode (node))
+	if ((oi = getdata (node)) != NULL)
+	  if (oi->nbr_self != NULL)
+	    {
+	      zlog_info ("setting nssa options on %s accordingly", IF_NAME (oi));
+	      UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E);
+	      SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP);
+	      zlog_info ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi));
+	    }
+#endif /* HAVE_NSSA */
+      break;
+    default:
+      break;
+    }
+
+  ospf_router_lsa_timer_add (area);
+  ospf_schedule_abr_task ();
+}
+
+int
+ospf_area_shortcut_set (struct ospf_area *area, int mode)
+{
+  if (area->shortcut_configured == mode)
+    return 0;
+
+  area->shortcut_configured = mode;
+  ospf_router_lsa_timer_add (area);
+  ospf_schedule_abr_task ();
+
+  ospf_area_check_free (area->area_id);
+
+  return 1;
+}
+
+int
+ospf_area_shortcut_unset (struct ospf_area *area)
+{
+  area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
+  ospf_router_lsa_timer_add (area);
+  ospf_area_check_free (area->area_id);
+  ospf_schedule_abr_task ();
+
+  return 1;
+}
+
+int
+ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area)
+{
+  struct ospf_vl_data *vl;
+  listnode node;
+  int count = 0;
+
+  for (node = listhead (ospf->vlinks); node; nextnode (node))
+    {
+      vl = getdata (node);
+      if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id))
+	count++;
+    }
+
+  return count;
+}
+
+int
+ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id)
+{
+  struct ospf_area *area;
+  int format = OSPF_AREA_ID_FORMAT_DECIMAL;
+
+  area = ospf_area_get (area_id, format);
+  if (ospf_area_vlink_count (ospf, area))
+    return 0;
+
+  if (area->external_routing != OSPF_AREA_STUB)
+    ospf_area_type_set (area, OSPF_AREA_STUB);
+
+  return 1;
+}
+
+int
+ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id)
+{
+  struct ospf_area *area;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return 1;
+
+  if (area->external_routing == OSPF_AREA_STUB)
+    ospf_area_type_set (area, OSPF_AREA_DEFAULT);
+
+  ospf_area_check_free (area_id);
+
+  return 1;
+}
+
+int
+ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id)
+{
+  struct ospf_area *area;
+  int format = OSPF_AREA_ID_FORMAT_DECIMAL;
+
+  area = ospf_area_get (area_id, format);
+  area->no_summary = 1;
+
+  return 1;
+}
+
+int
+ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id)
+{
+  struct ospf_area *area;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return 0;
+
+  area->no_summary = 0;
+  ospf_area_check_free (area_id);
+
+  return 1;
+}
+
+int
+ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id)
+{
+  struct ospf_area *area;
+  int format = OSPF_AREA_ID_FORMAT_DECIMAL;
+
+  area = ospf_area_get (area_id, format);
+  if (ospf_area_vlink_count (ospf, area))
+    return 0;
+
+  if (area->external_routing != OSPF_AREA_NSSA)
+    {
+      ospf_area_type_set (area, OSPF_AREA_NSSA);
+      ospf->anyNSSA++;
+    }
+
+  return 1;
+}
+
+int
+ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id)
+{
+  struct ospf_area *area;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return 0;
+
+  if (area->external_routing == OSPF_AREA_NSSA)
+    {
+      ospf->anyNSSA--;
+      ospf_area_type_set (area, OSPF_AREA_DEFAULT);
+    }
+
+  ospf_area_check_free (area_id);
+
+  return 1;
+}
+
+int
+ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id,
+				    int role)
+{
+  struct ospf_area *area;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return 0;
+
+  area->NSSATranslator = role;
+
+  return 1;
+}
+
+int
+ospf_area_nssa_translator_role_unset (struct ospf *ospf,
+				      struct in_addr area_id)
+{
+  struct ospf_area *area;
+
+  area = ospf_area_lookup_by_area_id (area_id);
+  if (area == NULL)
+    return 0;
+
+  area->NSSATranslator = OSPF_NSSA_ROLE_CANDIDATE;
+
+  ospf_area_check_free (area_id);
+
+  return 1;
+}
+
+int
+ospf_area_export_list_set (struct ospf_area *area, char *list_name)
+{
+  struct access_list *list;
+  list = access_list_lookup (AFI_IP, list_name);
+
+  EXPORT_LIST (area) = list;
+
+  if (EXPORT_NAME (area))
+    free (EXPORT_NAME (area));
+
+  EXPORT_NAME (area) = strdup (list_name);
+  ospf_schedule_abr_task ();
+
+  return 1;
+}
+
+int
+ospf_area_export_list_unset (struct ospf_area * area)
+{
+
+  EXPORT_LIST (area) = 0;
+
+  if (EXPORT_NAME (area))
+    free (EXPORT_NAME (area));
+
+  EXPORT_NAME (area) = NULL;
+
+  ospf_area_check_free (area->area_id);
+  
+  ospf_schedule_abr_task ();
+
+  return 1;
+}
+
+int
+ospf_area_import_list_set (struct ospf_area *area, char *name)
+{
+  struct access_list *list;
+  list = access_list_lookup (AFI_IP, name);
+
+  IMPORT_LIST (area) = list;
+
+  if (IMPORT_NAME (area))
+    free (IMPORT_NAME (area));
+
+  IMPORT_NAME (area) = strdup (name);
+  ospf_schedule_abr_task ();
+
+  return 1;
+}
+
+int
+ospf_area_import_list_unset (struct ospf_area * area)
+{
+  IMPORT_LIST (area) = 0;
+
+  if (IMPORT_NAME (area))
+    free (IMPORT_NAME (area));
+
+  IMPORT_NAME (area) = NULL;
+  ospf_area_check_free (area->area_id);
+
+  ospf_schedule_abr_task ();
+
+  return 1;
+}
+
+int
+ospf_timers_spf_set (struct ospf *ospf, u_int32_t delay, u_int32_t hold)
+{
+  ospf->spf_delay = delay;
+  ospf->spf_holdtime = hold;
+
+  return 1;
+}
+
+int
+ospf_timers_spf_unset (struct ospf *ospf)
+{
+  ospf->spf_delay = OSPF_SPF_DELAY_DEFAULT;
+  ospf->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
+
+  return 1;
+}
+
+int
+ospf_timers_refresh_set (struct ospf *ospf, int interval)
+{
+  int time_left;
+
+  if (ospf->lsa_refresh_interval == interval)
+    return 1;
+
+  time_left = ospf->lsa_refresh_interval -
+    (time (NULL) - ospf->lsa_refresher_started);
+  
+  if (time_left > interval)
+    {
+      OSPF_TIMER_OFF (ospf->t_lsa_refresher);
+      ospf->t_lsa_refresher =
+	thread_add_timer (master, ospf_lsa_refresh_walker, ospf, interval);
+    }
+  ospf->lsa_refresh_interval = interval;
+
+  return 1;
+}
+
+int
+ospf_timers_refresh_unset (struct ospf *ospf)
+{
+  int time_left;
+
+  time_left = ospf->lsa_refresh_interval -
+    (time (NULL) - ospf->lsa_refresher_started);
+
+  if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT)
+    {
+      OSPF_TIMER_OFF (ospf->t_lsa_refresher);
+      ospf->t_lsa_refresher =
+	thread_add_timer (master, ospf_lsa_refresh_walker, ospf,
+			  OSPF_LSA_REFRESH_INTERVAL_DEFAULT);
+    }
+
+  ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
+
+  return 1;
+}
+
+
+struct ospf_nbr_nbma *
+ospf_nbr_nbma_new ()
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  nbr_nbma = XMALLOC (MTYPE_OSPF_NEIGHBOR_STATIC,
+		      sizeof (struct ospf_nbr_nbma));
+  memset (nbr_nbma, 0, sizeof (struct ospf_nbr_nbma));
+
+  nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
+  nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
+
+  return nbr_nbma;
+}
+
+void
+ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma)
+{
+  XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma);
+}
+
+void
+ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma)
+{
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+
+  p.family = AF_INET;
+  p.prefix = nbr_nbma->addr;
+  p.prefixlen = IPV4_MAX_BITLEN;
+
+  rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
+  if (rn)
+    {
+      ospf_nbr_nbma_free (rn->info);
+      rn->info = NULL;
+      route_unlock_node (rn);
+      route_unlock_node (rn);
+    }
+}
+
+void
+ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma)
+{
+  OSPF_TIMER_OFF (nbr_nbma->t_poll);
+
+  if (nbr_nbma->nbr)
+    {
+      nbr_nbma->nbr->nbr_nbma = NULL;
+      OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr);
+    }
+
+  if (nbr_nbma->oi)
+    listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma);
+}
+
+void
+ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma,
+		   struct ospf_interface *oi)
+{
+  struct ospf_neighbor *nbr;
+  struct route_node *rn;
+  struct prefix p;
+
+  if (oi->type != OSPF_IFTYPE_NBMA)
+    return;
+
+  if (nbr_nbma->nbr != NULL)
+    return;
+
+  if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr))
+    return;
+      
+  nbr_nbma->oi = oi;
+  listnode_add (oi->nbr_nbma, nbr_nbma);
+
+  /* Get neighbor information from table. */
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+  p.u.prefix4 = nbr_nbma->addr;
+
+  rn = route_node_get (oi->nbrs, (struct prefix *)&p);
+  if (rn->info)
+    {
+      nbr = rn->info;
+      nbr->nbr_nbma = nbr_nbma;
+      nbr_nbma->nbr = nbr;
+
+      route_unlock_node (rn);
+    }
+  else
+    {
+      nbr = rn->info = ospf_nbr_new (oi);
+      nbr->state = NSM_Down;
+      nbr->src = nbr_nbma->addr;
+      nbr->nbr_nbma = nbr_nbma;
+      nbr->priority = nbr_nbma->priority;
+      nbr->address = p;
+
+      nbr_nbma->nbr = nbr;
+
+      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start);
+    }
+}
+
+void
+ospf_nbr_nbma_if_update (struct ospf_interface *oi)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+
+  if (oi->type != OSPF_IFTYPE_NBMA)
+    return;
+
+  for (rn = route_top (ospf_top->nbr_nbma); rn; rn = route_next (rn))
+    if ((nbr_nbma = rn->info))
+      if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL)
+	{
+	  p.family = AF_INET;
+	  p.prefix = nbr_nbma->addr;
+	  p.prefixlen = IPV4_MAX_BITLEN;
+
+	  if (prefix_match (oi->address, (struct prefix *)&p))
+	    ospf_nbr_nbma_add (nbr_nbma, oi);
+	}
+}
+
+struct ospf_nbr_nbma *
+ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr)
+{
+  struct route_node *rn;
+  struct prefix_ipv4 p;
+
+  p.family = AF_INET;
+  p.prefix = nbr_addr;
+  p.prefixlen = IPV4_MAX_BITLEN;
+
+  rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p);
+  if (rn)
+    {
+      route_unlock_node (rn);
+      return rn->info;
+    }
+  return NULL;
+}
+
+struct ospf_nbr_nbma *
+ospf_nbr_nbma_lookup_next (struct in_addr *addr, int first)
+{
+#if 0
+  struct ospf_nbr_nbma *nbr_nbma;
+  listnode node;
+#endif
+
+  if (! ospf_top)
+    return NULL;
+
+#if 0
+  for (node = listhead (ospf_top->nbr_nbma); node; nextnode (node))
+    {
+      nbr_nbma = getdata (node);
+
+      if (first)
+	{
+	  *addr = nbr_nbma->addr;
+	  return nbr_nbma;
+	}
+      else if (ntohl (nbr_nbma->addr.s_addr) > ntohl (addr->s_addr))
+	{
+	  *addr = nbr_nbma->addr;
+	  return nbr_nbma;
+	}
+    }
+#endif
+  return NULL;
+}
+
+int
+ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+  struct ospf_interface *oi;
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+  listnode node;
+
+  nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
+  if (nbr_nbma)
+    return 0;
+
+  nbr_nbma = ospf_nbr_nbma_new ();
+  nbr_nbma->addr = nbr_addr;
+
+  p.family = AF_INET;
+  p.prefix = nbr_addr;
+  p.prefixlen = IPV4_MAX_BITLEN;
+
+  rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p);
+  rn->info = nbr_nbma;
+
+  for (node = listhead (ospf->oiflist); node; nextnode (node))
+    {
+      oi = getdata (node);
+      if (oi->type == OSPF_IFTYPE_NBMA)
+	if (prefix_match (oi->address, (struct prefix *)&p))
+	  {
+	    ospf_nbr_nbma_add (nbr_nbma, oi);
+	    break;
+	  }
+    }
+
+  return 1;
+}
+
+int
+ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
+  if (nbr_nbma == NULL)
+    return 0;
+
+  ospf_nbr_nbma_down (nbr_nbma);
+  ospf_nbr_nbma_delete (ospf, nbr_nbma);
+
+  return 1;
+}
+
+int
+ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr,
+			    u_char priority)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
+  if (nbr_nbma == NULL)
+    return 0;
+
+  if (nbr_nbma->priority != priority)
+    nbr_nbma->priority = priority;
+
+  return 1;
+}
+
+int
+ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
+  if (nbr_nbma == NULL)
+    return 0;
+
+  if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT)
+    nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
+
+  return 1;
+}
+
+int
+ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr,
+				 int interval)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr);
+  if (nbr_nbma == NULL)
+    return 0;
+
+  if (nbr_nbma->v_poll != interval)
+    {
+      nbr_nbma->v_poll = interval;
+      if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi))
+	{
+	  OSPF_TIMER_OFF (nbr_nbma->t_poll);
+	  OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
+			      nbr_nbma->v_poll);
+	}
+    }
+
+  return 1;
+}
+
+int
+ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr)
+{
+  struct ospf_nbr_nbma *nbr_nbma;
+
+  nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr);
+  if (nbr_nbma == NULL)
+    return 0;
+
+  if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT)
+    nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT;
+
+  return 1;
+}
+
+
+void
+ospf_prefix_list_update (struct prefix_list *plist)
+{
+  struct ospf_area *area;
+  listnode node;
+  int abr_inv = 0;
+
+  /* If OSPF instatnce does not exist, return right now. */
+  if (!ospf_top)
+    return;
+
+  /* Update Area prefix-list. */
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      area = getdata (node);
+
+      /* Update filter-list in. */
+      if (PREFIX_NAME_IN (area))
+	if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0)
+	  {
+	    PREFIX_LIST_IN (area) = 
+	      prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
+	    abr_inv++;
+	  }
+
+      /* Update filter-list out. */
+      if (PREFIX_NAME_OUT (area))
+	if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0)
+	  {
+	    PREFIX_LIST_IN (area) = 
+	      prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
+	    abr_inv++;
+	  }
+    }
+
+  /* Schedule ABR tasks. */
+  if (OSPF_IS_ABR && abr_inv)
+    ospf_schedule_abr_task ();
+}
+
+void
+ospf_init ()
+{
+  /* Make empty list of ospf list. */
+  ospf_top = NULL;
+
+  prefix_list_add_hook (ospf_prefix_list_update);
+  prefix_list_delete_hook (ospf_prefix_list_update);
+}
diff --git a/ospfd/ospfd.conf.sample b/ospfd/ospfd.conf.sample
new file mode 100644
index 0000000..0e8ac67
--- /dev/null
+++ b/ospfd/ospfd.conf.sample
@@ -0,0 +1,13 @@
+! -*- ospf -*-
+!
+! OSPFd sample configuration file
+!
+!
+hostname ospfd
+password zebra
+!enable password please-set-at-here
+!
+!router ospf
+!  network 192.168.1.0/24 area 0
+!
+log stdout
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
new file mode 100644
index 0000000..a83231b
--- /dev/null
+++ b/ospfd/ospfd.h
@@ -0,0 +1,559 @@
+/*
+ * OSPFd main header.
+ * Copyright (C) 1998, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPFD_H
+#define _ZEBRA_OSPFD_H
+
+#include "filter.h"
+
+#define OSPF_VERSION            2
+
+/* Default protocol, port number. */
+#ifndef IPPROTO_OSPFIGP
+#define IPPROTO_OSPFIGP         89
+#endif /* IPPROTO_OSPFIGP */
+
+/* VTY port number. */
+#define OSPF_VTY_PORT          2604
+#define OSPF_VTYSH_PATH        "/tmp/.ospfd"
+
+/* IP TTL for OSPF protocol. */
+#define OSPF_IP_TTL             1
+#define OSPF_VL_IP_TTL          100
+
+/* Default configuration file name for ospfd. */
+#define OSPF_DEFAULT_CONFIG   "ospfd.conf"
+
+/* Architectual Constants */
+#ifdef DEBUG
+#define OSPF_LS_REFRESH_TIME                    60
+#else
+#define OSPF_LS_REFRESH_TIME                  1800
+#endif
+#define OSPF_MIN_LS_INTERVAL                     5
+#define OSPF_MIN_LS_ARRIVAL                      1
+#define OSPF_LSA_MAXAGE                       3600
+#define OSPF_CHECK_AGE                         300
+#define OSPF_LSA_MAXAGE_DIFF                   900
+#define OSPF_LS_INFINITY                  0xffffff
+#define OSPF_DEFAULT_DESTINATION        0x00000000      /* 0.0.0.0 */
+#define OSPF_INITIAL_SEQUENCE_NUMBER    0x80000001
+#define OSPF_MAX_SEQUENCE_NUMBER        0x7fffffff
+
+#define OSPF_LSA_MAXAGE_CHECK_INTERVAL          30
+
+#define OSPF_ALLSPFROUTERS              0xe0000005      /* 224.0.0.5 */
+#define OSPF_ALLDROUTERS                0xe0000006      /* 224.0.0.6 */
+
+#ifdef HAVE_NSSA
+#define OSPF_LOOPer                     0x7f000000      /* 127.0.0.0 */
+#endif /* HAVE_NSSA */
+
+#define OSPF_AREA_BACKBONE              0x00000000      /* 0.0.0.0 */
+
+/* OSPF Authentication Type. */
+#define OSPF_AUTH_NULL                      0
+#define OSPF_AUTH_SIMPLE                    1
+#define OSPF_AUTH_CRYPTOGRAPHIC             2
+/* For Interface authentication setting default */
+#define OSPF_AUTH_NOTSET                   -1
+/* For the consumption and sanity of the command handler */ 
+/* DO NIOT REMOVE!!! Need to detect whether a value has
+   been given or not in VLink command handlers */
+#define OSPF_AUTH_CMD_NOTSEEN              -2
+
+/* OSPF SPF timer values. */
+#define OSPF_SPF_DELAY_DEFAULT              5
+#define OSPF_SPF_HOLDTIME_DEFAULT          10
+
+/* OSPF interface default values. */
+#define OSPF_OUTPUT_COST_DEFAULT           10
+#define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT  40
+#define OSPF_HELLO_INTERVAL_DEFAULT        10
+#define OSPF_ROUTER_PRIORITY_DEFAULT        1
+#define OSPF_RETRANSMIT_INTERVAL_DEFAULT    5
+#define OSPF_TRANSMIT_DELAY_DEFAULT         1
+#define OSPF_DEFAULT_BANDWIDTH		 10000	/* Kbps */
+
+#define OSPF_DEFAULT_REF_BANDWIDTH	100000  /* Kbps */
+
+#define OSPF_POLL_INTERVAL_DEFAULT         60
+#define OSPF_NEIGHBOR_PRIORITY_DEFAULT      0
+
+/* OSPF options. */
+#define OSPF_OPTION_T                    0x01  /* TOS. */
+#define OSPF_OPTION_E                    0x02
+#define OSPF_OPTION_MC                   0x04
+#define OSPF_OPTION_NP                   0x08
+#define OSPF_OPTION_EA                   0x10
+#define OSPF_OPTION_DC                   0x20
+#define OSPF_OPTION_O                    0x40
+
+/* OSPF Database Description flags. */
+#define OSPF_DD_FLAG_MS                  0x01
+#define OSPF_DD_FLAG_M                   0x02
+#define OSPF_DD_FLAG_I                   0x04
+#define OSPF_DD_FLAG_ALL                 0x07
+
+/* Timer value. */
+#define OSPF_ROUTER_ID_UPDATE_DELAY             1
+
+#define OSPF_LS_REFRESH_SHIFT       (60 * 15)
+#define OSPF_LS_REFRESH_JITTER      60
+
+/* OSPF instance structure. */
+struct ospf
+{
+  /* OSPF Router ID. */
+  struct in_addr router_id;		/* Configured automatically. */
+  struct in_addr router_id_static;	/* Configured manually. */
+
+  /* ABR/ASBR internal flags. */
+  u_char flags;
+#define OSPF_FLAG_ABR           0x0001
+#define OSPF_FLAG_ASBR          0x0002
+
+  /* ABR type. */
+  u_char abr_type;
+#define OSPF_ABR_UNKNOWN	0
+#define OSPF_ABR_STAND          1
+#define OSPF_ABR_IBM            2
+#define OSPF_ABR_CISCO          3
+#define OSPF_ABR_SHORTCUT       4
+
+  /* NSSA ABR */
+  u_char anyNSSA;		/* Bump for every NSSA attached. */
+
+  /* Configured variables. */
+  u_char config;
+#define OSPF_RFC1583_COMPATIBLE         (1 << 0)
+#define OSPF_OPAQUE_CAPABLE		(1 << 2)
+
+#ifdef HAVE_OPAQUE_LSA
+  /* Opaque-LSA administrative flags. */
+  u_char opaque;
+#define OPAQUE_OPERATION_READY_BIT	(1 << 0)
+#define OPAQUE_BLOCK_TYPE_09_LSA_BIT	(1 << 1)
+#define OPAQUE_BLOCK_TYPE_10_LSA_BIT	(1 << 2)
+#define OPAQUE_BLOCK_TYPE_11_LSA_BIT	(1 << 3)
+#endif /* HAVE_OPAQUE_LSA */
+
+  int spf_delay;			/* SPF delay time. */
+  int spf_holdtime;			/* SPF hold time. */
+  int default_originate;		/* Default information originate. */
+#define DEFAULT_ORIGINATE_NONE		0
+#define DEFAULT_ORIGINATE_ZEBRA		1
+#define DEFAULT_ORIGINATE_ALWAYS	2
+  u_int32_t ref_bandwidth;		/* Reference Bandwidth (Kbps). */
+  struct route_table *networks;         /* OSPF config networks. */
+  list vlinks;                          /* Configured Virtual-Links. */
+  list areas;                           /* OSPF areas. */
+  struct route_table *nbr_nbma;
+  struct ospf_area *backbone;           /* Pointer to the Backbone Area. */
+
+  list iflist;                          /* Zebra derived interfaces. */
+  list oiflist;                         /* ospf interfaces */
+
+  /* LSDB of AS-external-LSAs. */
+  struct ospf_lsdb *lsdb;
+  
+  /* Redistributed external information. */
+  struct route_table *external_info[ZEBRA_ROUTE_MAX + 1];
+#define EXTERNAL_INFO(T)      ospf_top->external_info[T]
+
+  /* Flags. */
+  int external_origin;			/* AS-external-LSA origin flag. */
+  int ase_calc;				/* ASE calculation flag. */
+
+#ifdef HAVE_OPAQUE_LSA
+  list opaque_lsa_self;			/* Type-11 Opaque-LSAs */
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* Routing tables. */
+  struct route_table *old_table;        /* Old routing table. */
+  struct route_table *new_table;        /* Current routing table. */
+
+  struct route_table *old_rtrs;         /* Old ABR/ASBR RT. */
+  struct route_table *new_rtrs;         /* New ABR/ASBR RT. */
+
+  struct route_table *new_external_route;   /* New External Route. */
+  struct route_table *old_external_route;   /* Old External Route. */
+  
+  struct route_table *external_lsas;    /* Database of external LSAs,
+					   prefix is LSA's adv. network*/
+
+  /* Time stamps. */
+  time_t ts_spf;			/* SPF calculation time stamp. */
+
+  list maxage_lsa;                      /* List of MaxAge LSA for deletion. */
+  int redistribute;                     /* Num of redistributed protocols. */
+
+  /* Threads. */
+  struct thread *t_router_id_update;	/* Router ID update timer. */
+  struct thread *t_router_lsa_update;   /* router-LSA update timer. */
+  struct thread *t_abr_task;            /* ABR task timer. */
+  struct thread *t_asbr_check;          /* ASBR check timer. */
+  struct thread *t_distribute_update;   /* Distirbute list update timer. */
+  struct thread *t_spf_calc;	        /* SPF calculation timer. */
+  struct thread *t_ase_calc;		/* ASE calculation timer. */
+  struct thread *t_external_lsa;	/* AS-external-LSA origin timer. */
+#ifdef HAVE_OPAQUE_LSA
+  struct thread *t_opaque_lsa_self;	/* Type-11 Opaque-LSAs origin event. */
+#endif /* HAVE_OPAQUE_LSA */
+  struct thread *t_maxage;              /* MaxAge LSA remover timer. */
+  struct thread *t_maxage_walker;       /* MaxAge LSA checking timer. */
+
+  struct thread *t_write;
+  struct thread *t_read;
+  int fd;
+  list oi_write_q;
+  
+  /* Distribute lists out of other route sources. */
+  struct 
+  {
+    char *name;
+    struct access_list *list;
+  } dlist[ZEBRA_ROUTE_MAX];
+#define DISTRIBUTE_NAME(T)    ospf_top->dlist[T].name
+#define DISTRIBUTE_LIST(T)    ospf_top->dlist[T].list
+
+  /* Redistribute metric info. */
+  struct 
+  {
+    int type;                   /* External metric type (E1 or E2).  */
+    int value;		        /* Value for static metric (24-bit).
+				   -1 means metric value is not set. */
+  } dmetric [ZEBRA_ROUTE_MAX + 1];
+
+  /* For redistribute route map. */
+  struct
+  {
+    char *name;
+    struct route_map *map;
+  } route_map [ZEBRA_ROUTE_MAX + 1]; /* +1 is for default-information */
+#define ROUTEMAP_NAME(T)   ospf_top->route_map[T].name
+#define ROUTEMAP(T)        ospf_top->route_map[T].map
+  
+  int default_metric;		/* Default metric for redistribute. */
+
+#define OSPF_LSA_REFRESHER_GRANULARITY 10
+#define OSPF_LSA_REFRESHER_SLOTS ((OSPF_LS_REFRESH_TIME + \
+                                  OSPF_LS_REFRESH_SHIFT)/10 + 1)
+  struct
+  {
+    u_int16_t index;
+    list qs[OSPF_LSA_REFRESHER_SLOTS];
+  } lsa_refresh_queue;
+  
+  struct thread *t_lsa_refresher;
+  time_t lsa_refresher_started;
+#define OSPF_LSA_REFRESH_INTERVAL_DEFAULT 10
+  u_int16_t lsa_refresh_interval;
+  
+  /* Distance parameter. */
+  u_char distance_all;
+  u_char distance_intra;
+  u_char distance_inter;
+  u_char distance_external;
+
+  /* Statistics for LSA origination. */
+  u_int32_t lsa_originate_count;
+
+  /* Statistics for LSA used for new instantiation. */
+  u_int32_t rx_lsa_count;
+ 
+  struct route_table *distance_table;
+};
+
+/* OSPF area structure. */
+struct ospf_area
+{
+  /* OSPF instance. */
+  struct ospf *top;
+
+  /* Zebra interface list belonging to the area. */
+  list oiflist;
+
+  /* Area ID. */
+  struct in_addr area_id;
+
+  /* Area ID format. */
+  char format;
+#define OSPF_AREA_ID_FORMAT_ADDRESS         1
+#define OSPF_AREA_ID_FORMAT_DECIMAL         2
+
+  /* Address range. */
+  list address_range;
+
+  /* Configured variables. */
+  int external_routing;                 /* ExternalRoutingCapability. */
+#define OSPF_AREA_DEFAULT       0
+#define OSPF_AREA_STUB          1
+#define OSPF_AREA_NSSA          2
+#define OSPF_AREA_TYPE_MAX	3
+  int no_summary;                       /* Don't inject summaries into stub.*/
+  int shortcut_configured;              /* Area configured as shortcut. */
+#define OSPF_SHORTCUT_DEFAULT	0
+#define OSPF_SHORTCUT_ENABLE	1
+#define OSPF_SHORTCUT_DISABLE	2
+  int shortcut_capability;              /* Other ABRs agree on S-bit */
+  u_int32_t default_cost;               /* StubDefaultCost. */
+  int auth_type;                        /* Authentication type. */
+
+  u_char NSSATranslatorRole;          /* NSSA Role during configuration */
+#define OSPF_NSSA_ROLE_NEVER     0
+#define OSPF_NSSA_ROLE_ALWAYS    1
+#define OSPF_NSSA_ROLE_CANDIDATE 2
+  u_char NSSATranslator;              /* NSSA Role after election process */
+
+  u_char transit;			/* TransitCapability. */
+#define OSPF_TRANSIT_FALSE      0
+#define OSPF_TRANSIT_TRUE       1
+  struct route_table *ranges;		/* Configured Area Ranges. */
+
+  /* Area related LSDBs[Type1-4]. */
+  struct ospf_lsdb *lsdb;
+
+  /* Self-originated LSAs. */
+  struct ospf_lsa *router_lsa_self;
+#ifdef HAVE_OPAQUE_LSA
+  list opaque_lsa_self;			/* Type-10 Opaque-LSAs */
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* Area announce list. */
+  struct 
+  {
+    char *name;
+    struct access_list *list;
+  } export;
+#define EXPORT_NAME(A)  (A)->export.name
+#define EXPORT_LIST(A)  (A)->export.list
+
+  /* Area acceptance list. */
+  struct 
+  {
+    char *name;
+    struct access_list *list;
+  } import;
+#define IMPORT_NAME(A)  (A)->import.name
+#define IMPORT_LIST(A)  (A)->import.list
+
+  /* Type 3 LSA Area prefix-list. */
+  struct 
+  {
+    char *name;
+    struct prefix_list *list;
+  } plist_in;
+#define PREFIX_LIST_IN(A)   (A)->plist_in.list
+#define PREFIX_NAME_IN(A)   (A)->plist_in.name
+
+  struct
+  {
+    char *name;
+    struct prefix_list *list;
+  } plist_out;
+#define PREFIX_LIST_OUT(A)  (A)->plist_out.list
+#define PREFIX_NAME_OUT(A)  (A)->plist_out.name
+
+  /* Shortest Path Tree. */
+  struct vertex *spf;
+
+  /* Threads. */
+  struct thread *t_router_lsa_self;/* Self-originated router-LSA timer. */
+#ifdef HAVE_OPAQUE_LSA
+  struct thread *t_opaque_lsa_self;	/* Type-10 Opaque-LSAs origin. */
+#endif /* HAVE_OPAQUE_LSA */
+
+  /* Statistics field. */
+  u_int32_t spf_calculation;	/* SPF Calculation Count. */
+
+  /* Router count. */
+  u_int32_t abr_count;		/* ABR router in this area. */
+  u_int32_t asbr_count;		/* ASBR router in this area. */
+
+  /* Counters. */
+  u_int32_t act_ints;		/* Active interfaces. */
+  u_int32_t full_nbrs;		/* Fully adjacent neighbors. */
+  u_int32_t full_vls;		/* Fully adjacent virtual neighbors. */
+};
+
+/* OSPF config network structure. */
+struct ospf_network
+{
+  /* Area ID. */
+  struct in_addr area_id;
+  int format;
+};
+
+/* OSPF NBMA neighbor structure. */
+struct ospf_nbr_nbma
+{
+  /* Neighbor IP address. */
+  struct in_addr addr;
+
+  /* OSPF interface. */
+  struct ospf_interface *oi;
+
+  /* OSPF neighbor structure. */
+  struct ospf_neighbor *nbr;
+
+  /* Neighbor priority. */
+  u_char priority;
+
+  /* Poll timer value. */
+  u_int32_t v_poll;
+
+  /* Poll timer thread. */
+  struct thread *t_poll;
+
+  /* State change. */
+  u_int32_t state_change;
+};
+
+/* Macro. */
+#define OSPF_AREA_SAME(X,Y) \
+        (memcmp ((X->area_id), (Y->area_id), IPV4_MAX_BYTELEN) == 0)
+
+#define OSPF_IS_ABR		(ospf_top->flags & OSPF_FLAG_ABR)
+#define OSPF_IS_ASBR		(ospf_top->flags & OSPF_FLAG_ASBR)
+
+#define OSPF_IS_AREA_ID_BACKBONE(I) ((I).s_addr == OSPF_AREA_BACKBONE)
+#define OSPF_IS_AREA_BACKBONE(A) OSPF_IS_AREA_ID_BACKBONE ((A)->area_id)
+
+#ifdef roundup
+#  define ROUNDUP(val, gran)	roundup(val, gran)
+#else /* roundup */
+#  define ROUNDUP(val, gran)	(((val) - 1 | (gran) - 1) + 1)
+#endif /* roundup */
+
+#define LSA_OPTIONS_GET(area) \
+        (((area)->external_routing == OSPF_AREA_DEFAULT) ? OSPF_OPTION_E : 0)
+#ifdef HAVE_NSSA
+#define LSA_NSSA_GET(area) \
+        (((area)->external_routing == OSPF_AREA_NSSA) ? \
+          (area)->NSSATranslator : 0)
+#endif /* HAVE_NSSA */
+
+#define OSPF_TIMER_ON(T,F,V)                                                  \
+    do {                                                                      \
+      if (!(T))                                                               \
+	(T) = thread_add_timer (master, (F), NULL, (V));                      \
+    } while (0)
+
+#define OSPF_AREA_TIMER_ON(T,F,V)                                             \
+    do {                                                                      \
+      if (!(T))                                                               \
+        (T) = thread_add_timer (master, (F), area, (V));                      \
+    } while (0)
+
+#define OSPF_POLL_TIMER_ON(T,F,V)                                             \
+    do {                                                                      \
+      if (!(T))                                                               \
+        (T) = thread_add_timer (master, (F), nbr_nbma, (V));                  \
+    } while (0)
+
+#define OSPF_POLL_TIMER_OFF(X)		OSPF_TIMER_OFF((X))
+
+#define OSPF_TIMER_OFF(X)                                                     \
+    do {                                                                      \
+      if (X)                                                                  \
+        {                                                                     \
+          thread_cancel (X);                                                  \
+          (X) = NULL;                                                         \
+        }                                                                     \
+    } while (0)
+
+#define OSPF_SCHEDULE_MAXAGE(T, F)                                            \
+    do {                                                                      \
+      if (!(T))                                                               \
+        (T) = thread_add_timer (master, (F), 0, 2);                           \
+    } while (0)
+
+/* Messages */
+extern struct message ospf_ism_state_msg[];
+extern struct message ospf_nsm_state_msg[];
+extern struct message ospf_lsa_type_msg[];
+extern struct message ospf_link_state_id_type_msg[];
+extern struct message ospf_redistributed_proto[];
+extern struct message ospf_network_type_msg[];
+extern int ospf_ism_state_msg_max;
+extern int ospf_nsm_state_msg_max;
+extern int ospf_lsa_type_msg_max;
+extern int ospf_link_state_id_type_msg_max;
+extern int ospf_redistributed_proto_max;
+extern int ospf_network_type_msg_max;
+extern struct zclient *zclient;
+extern struct thread_master *master;
+extern struct ospf *ospf_top;
+extern int ospf_zlog;
+
+/* Prototypes. */
+struct ospf *ospf_get ();
+void ospf_finish (struct ospf *);
+int ospf_router_id_update_timer (struct thread *);
+void ospf_router_id_update ();
+int ospf_network_set (struct ospf *, struct prefix_ipv4 *, struct in_addr);
+int ospf_network_unset (struct ospf *, struct prefix_ipv4 *, struct in_addr);
+int ospf_area_stub_set (struct ospf *, struct in_addr);
+int ospf_area_stub_unset (struct ospf *, struct in_addr);
+int ospf_area_no_summary_set (struct ospf *, struct in_addr);
+int ospf_area_no_summary_unset (struct ospf *, struct in_addr);
+int ospf_area_nssa_set (struct ospf *, struct in_addr);
+int ospf_area_nssa_unset (struct ospf *, struct in_addr);
+int ospf_area_nssa_translator_role_set (struct ospf *, struct in_addr, int);
+int ospf_area_export_list_set (struct ospf_area *, char *);
+int ospf_area_export_list_unset (struct ospf_area *);
+int ospf_area_import_list_set (struct ospf_area *, char *);
+int ospf_area_import_list_unset (struct ospf_area *);
+int ospf_area_shortcut_set (struct ospf_area *, int);
+int ospf_area_shortcut_unset (struct ospf_area *);
+int ospf_timers_spf_set (struct ospf *, u_int32_t, u_int32_t);
+int ospf_timers_spf_unset (struct ospf *);
+int ospf_timers_refresh_set (struct ospf *, int);
+int ospf_timers_refresh_unset (struct ospf *);
+int ospf_nbr_nbma_set (struct ospf *, struct in_addr);
+int ospf_nbr_nbma_unset (struct ospf *, struct in_addr);
+int ospf_nbr_nbma_priority_set (struct ospf *, struct in_addr, u_char);
+int ospf_nbr_nbma_priority_unset (struct ospf *, struct in_addr);
+int ospf_nbr_nbma_poll_interval_set (struct ospf *, struct in_addr, int);
+int ospf_nbr_nbma_poll_interval_unset (struct ospf *, struct in_addr);
+void ospf_prefix_list_update (struct prefix_list *);
+void ospf_init ();
+void ospf_if_update ();
+void ospf_ls_upd_queue_empty (struct ospf_interface *);
+void ospf_terminate ();
+void ospf_nbr_nbma_if_update (struct ospf_interface *);
+struct ospf_nbr_nbma *ospf_nbr_nbma_lookup (struct ospf *, struct in_addr);
+struct ospf_nbr_nbma *ospf_nbr_nbma_lookup_next (struct in_addr *, int);
+int ospf_oi_count (struct interface *);
+
+struct ospf_area *ospf_area_new (struct in_addr);
+struct ospf_area *ospf_area_get (struct in_addr, int);
+void ospf_area_check_free (struct in_addr);
+struct ospf_area *ospf_area_lookup_by_area_id (struct in_addr);
+void ospf_area_add_if (struct ospf_area *, struct ospf_interface *);
+void ospf_area_del_if (struct ospf_area *, struct ospf_interface *);
+
+void ospf_route_map_init ();
+void ospf_snmp_init ();
+
+#endif /* _ZEBRA_OSPFD_H */