Initial revision
diff --git a/isisd/AUTHORS b/isisd/AUTHORS
new file mode 100644
index 0000000..d9f98b2
--- /dev/null
+++ b/isisd/AUTHORS
@@ -0,0 +1,3 @@
+Sampo Saaristo <sambo@cs.tut.fi>
+Ofer Wald      <ofersf@islands.co.il>
+Hannes Gredler <hannes@gredler.at>
diff --git a/isisd/COPYING b/isisd/COPYING
new file mode 100644
index 0000000..08d6e50
--- /dev/null
+++ b/isisd/COPYING
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program 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 of the License, or
+    (at your option) any later version.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/isisd/ChangeLog b/isisd/ChangeLog
new file mode 100644
index 0000000..78580ea
--- /dev/null
+++ b/isisd/ChangeLog
@@ -0,0 +1,69 @@
+Version 0.0.7 to 0.0.8
+======================
+
+o A bug in handling of other ISs fragments fixed
+o hello interval now specified in *seconds*
+o replaced the adj->ipv[46]_addr tables with linked lists
+
+Version 0.0.6 to 0.0.7 (Oct 29 2002)
+======================
+
+o changed to zebra-0.93b
+o fixed a seg in SPF
+o handling/generation of LSP fragments
+o domain/area/circuit password
+
+Version 0.0.5 to 0.0.6 (Jul 4 2002)
+======================
+
+o lots of changes to SPF
+ - runs the SPF for IPv4 and IPv6 separately
+ - a number of bugs fixed
+ - simplified the implementation 
+ - "7.2.7 Removal of excess paths" implemented
+o ported to freebsd  (tested in 4.5-STABLE and 4.6-STABLE) 
+o moved to zebra-0.93-pre2
+o "show isis topology" command added 
+o "show (ip|ipv6) route isis commands added to zebra
+o a number of fixes and additions (e.g. checksum calculation and DIS state
+change event) by BeomSeok Gwak added
+
+Version 0.0.4 to 0.0.5 (Apr 26 2002)
+======================
+
+o changed to zebra-0.93-pre1
+o number of memory leaks + small bugs fixed
+o a bug related to processing of neigbors when installing routes fixed
+
+Version 0.0.3 to 0.0.4 (Feb 27 2002)
+======================
+
+o initial version of SPT algorithm
+o installing routes though zebrad
+o isis debug commands
+o work on IS-IS events (e.g. circuit state change)
+
+Version 0.0.2 to 0.0.3 (Jan 17 2002)
+======================
+
+o LSP handling improved
+o generation of pseudonode LSPs
+o DR election enhanced
+o support for p2p interfaces
+o support for topology simulation 
+o more detailed output for show commands
+
+Version 0.0.1 to 0.0.2 (Dec 13 2001)
+======================
+
+o circuit state machine (isis_csm.[ch]) added
+o lot of work on LSP generation 
+o ISO checksum 
+o uses DGRAM sockets instead of RAW
+o gets IP(v6) addresses from zebra
+o debug can be controlled with "debug isis" command
+o read support for TE tlvs
+o work started on p2p interfaces
+o work started on isis events 
+
+
diff --git a/isisd/INSTALL-0.0.4 b/isisd/INSTALL-0.0.4
new file mode 100644
index 0000000..c984391
--- /dev/null
+++ b/isisd/INSTALL-0.0.4
@@ -0,0 +1,18 @@
+ISISd package for zebra 0.92a installation instructions:
+
+1. grab the zebra 0.92a package from www.zebra.org
+2. unpack the package using tar -zxvf zebra-0.92a.tar.gz
+3. enter the zebra-092a directory
+4. copy the contents of the isisd package into the zebra dir
+5. enter the isisd/modified directory
+6. use the README file and copy the files to the appropriate zebra dirs
+   (the simplest way to do so would be 'source README')
+7. enter the main zebra directory and issue 'automake','autoconf' and 
+   'autoheader'. if using automake version 1.5 and up use the '-i' option.
+8. run './configure --enable-isisd' (you may use other zebra config commands)
+9. run 'make'
+10. find your self something entertaining to do for the next couple of minutes
+11. you can issue 'make install' or simply work from the isisd directory
+
+for any problems, contact the developers at the sourceforge site
+http://www.sf.net/projects/isisd
diff --git a/isisd/Makefile.am b/isisd/Makefile.am
new file mode 100644
index 0000000..b9a0c7c
--- /dev/null
+++ b/isisd/Makefile.am
@@ -0,0 +1,55 @@
+## Process this file with automake to produce Makefile.in.
+
+# INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -Itopology
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib 
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+INSTALL_SDATA=@INSTALL@ -m 600
+LIBS = @LIBS@ 
+noinst_LIBRARIES = libisis.a
+sbin_PROGRAMS = isisd 
+
+libisis_a_SOURCES = \
+	isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \
+	isis_tlv.c isisd.c isis_misc.c isis_network.c isis_zebra.c isis_dr.c \
+	isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \
+	isis_spf.c isis_route.c isis_routemap.c
+
+
+noinst_HEADERS = \
+	isisd.h isis_pdu.h isis_tlv.h isis_adjacency.h isis_constants.h \
+	isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \
+	isis_zebra.h isis_dr.h isis_flags.h isis_dynhn.h isis_common.h \
+	iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_route.h
+
+isisd_SOURCES = \
+	isis_main.c $(libisis_a_SOURCES)
+
+isisd_LDADD = ../lib/libzebra.a 
+
+sysconf_DATA = isisd.conf.sample
+
+EXTRA_DIST = $(sysconf_DATA)
+
+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
+
+depend:
+	@$(CPP) -MM $(INCLUDES) $(LDFLAGS) *.c
+
+## File dependency.
+isis_adjacency.o : isis_adjacency.c ../lib/version.h ../lib/log.h \
+ ../isisd/isis_adjacency.h
+isis_pdu.o : isis_pdu.c ../lib/log.h ../isisd/isisd.h \
+ ../isisd/isis_constants.h ../isisd/isis_adjacency.h \
+ ../isisd/isis_pdu.h
+isis_circuit.o : isis_circuit.c ../isisd/isis_circuit.h
diff --git a/isisd/Makefile.in b/isisd/Makefile.in
new file mode 100644
index 0000000..46aae73
--- /dev/null
+++ b/isisd/Makefile.in
@@ -0,0 +1,463 @@
+# Makefile.in generated by automake 1.6.2 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@
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+AMTAR = @AMTAR@
+AR = @AR@
+AWK = @AWK@
+BGPD = @BGPD@
+CC = @CC@
+CPP = @CPP@
+CURSES = @CURSES@
+DEPDIR = @DEPDIR@
+IF_METHOD = @IF_METHOD@
+IF_PROC = @IF_PROC@
+
+# INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -Itopology
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib 
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPFORWARD = @IPFORWARD@
+ISISD = @ISISD@
+KERNEL_METHOD = @KERNEL_METHOD@
+LIBPAM = @LIBPAM@
+LIB_IPV6 = @LIB_IPV6@
+LIB_REGEX = @LIB_REGEX@
+MULTIPATH_NUM = @MULTIPATH_NUM@
+OSPF6D = @OSPF6D@
+OSPFD = @OSPFD@
+OTHER_METHOD = @OTHER_METHOD@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+RIPD = @RIPD@
+RIPNGD = @RIPNGD@
+RTREAD_METHOD = @RTREAD_METHOD@
+RT_METHOD = @RT_METHOD@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VTYSH = @VTYSH@
+ZEBRA = @ZEBRA@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+INSTALL_SDATA = @INSTALL@ -m 600
+LIBS = @LIBS@ 
+noinst_LIBRARIES = libisis.a
+sbin_PROGRAMS = isisd 
+
+libisis_a_SOURCES = \
+	isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \
+	isis_tlv.c isisd.c isis_misc.c isis_network.c isis_zebra.c isis_dr.c \
+	isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \
+	isis_spf.c isis_route.c isis_routemap.c
+
+
+noinst_HEADERS = \
+	isisd.h isis_pdu.h isis_tlv.h isis_adjacency.h isis_constants.h \
+	isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \
+	isis_zebra.h isis_dr.h isis_flags.h isis_dynhn.h isis_common.h \
+	iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_route.h
+
+
+isisd_SOURCES = \
+	isis_main.c $(libisis_a_SOURCES)
+
+
+isisd_LDADD = ../lib/libzebra.a 
+
+sysconf_DATA = isisd.conf.sample
+
+EXTRA_DIST = $(sysconf_DATA)
+subdir = isisd
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+libisis_a_AR = $(AR) cru
+libisis_a_LIBADD =
+am_libisis_a_OBJECTS = isis_adjacency.$(OBJEXT) isis_lsp.$(OBJEXT) \
+	dict.$(OBJEXT) isis_circuit.$(OBJEXT) isis_pdu.$(OBJEXT) \
+	isis_tlv.$(OBJEXT) isisd.$(OBJEXT) isis_misc.$(OBJEXT) \
+	isis_network.$(OBJEXT) isis_zebra.$(OBJEXT) isis_dr.$(OBJEXT) \
+	isis_flags.$(OBJEXT) isis_dynhn.$(OBJEXT) \
+	iso_checksum.$(OBJEXT) isis_csm.$(OBJEXT) isis_events.$(OBJEXT) \
+	isis_spf.$(OBJEXT) isis_route.$(OBJEXT) isis_routemap.$(OBJEXT)
+libisis_a_OBJECTS = $(am_libisis_a_OBJECTS)
+sbin_PROGRAMS = isisd$(EXEEXT)
+PROGRAMS = $(sbin_PROGRAMS)
+
+am__objects_1 = isis_adjacency.$(OBJEXT) isis_lsp.$(OBJEXT) \
+	dict.$(OBJEXT) isis_circuit.$(OBJEXT) isis_pdu.$(OBJEXT) \
+	isis_tlv.$(OBJEXT) isisd.$(OBJEXT) isis_misc.$(OBJEXT) \
+	isis_network.$(OBJEXT) isis_zebra.$(OBJEXT) isis_dr.$(OBJEXT) \
+	isis_flags.$(OBJEXT) isis_dynhn.$(OBJEXT) \
+	iso_checksum.$(OBJEXT) isis_csm.$(OBJEXT) isis_events.$(OBJEXT) \
+	isis_spf.$(OBJEXT) isis_route.$(OBJEXT) isis_routemap.$(OBJEXT)
+am_isisd_OBJECTS = isis_main.$(OBJEXT) $(am__objects_1)
+isisd_OBJECTS = $(am_isisd_OBJECTS)
+isisd_DEPENDENCIES = ../lib/libzebra.a
+isisd_LDFLAGS =
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dict.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_adjacency.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_circuit.Po ./$(DEPDIR)/isis_csm.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_dr.Po ./$(DEPDIR)/isis_dynhn.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_events.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_flags.Po ./$(DEPDIR)/isis_lsp.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_main.Po ./$(DEPDIR)/isis_misc.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_network.Po ./$(DEPDIR)/isis_pdu.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_route.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_routemap.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_spf.Po ./$(DEPDIR)/isis_tlv.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/isis_zebra.Po ./$(DEPDIR)/isisd.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/iso_checksum.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+DIST_SOURCES = $(libisis_a_SOURCES) $(isisd_SOURCES)
+DATA = $(sysconf_DATA)
+
+HEADERS = $(noinst_HEADERS)
+
+DIST_COMMON = README $(noinst_HEADERS) AUTHORS COPYING ChangeLog \
+	Makefile.am Makefile.in TODO
+SOURCES = $(libisis_a_SOURCES) $(isisd_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  isisd/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)
+libisis.a: $(libisis_a_OBJECTS) $(libisis_a_DEPENDENCIES) 
+	-rm -f libisis.a
+	$(libisis_a_AR) libisis.a $(libisis_a_OBJECTS) $(libisis_a_LIBADD)
+	$(RANLIB) libisis.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 \
+	    p1=`echo "$$p1" | sed -e 's,^.*/,,'`; \
+	    f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \
+	   $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  f=`echo "$$f" | sed -e 's,^.*/,,'`; \
+	  echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \
+	  rm -f $(DESTDIR)$(sbindir)/$$f; \
+	done
+
+clean-sbinPROGRAMS:
+	-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+isisd$(EXEEXT): $(isisd_OBJECTS) $(isisd_DEPENDENCIES) 
+	@rm -f isisd$(EXEEXT)
+	$(LINK) $(isisd_LDFLAGS) $(isisd_OBJECTS) $(isisd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dict.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_adjacency.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_circuit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_csm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_dr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_dynhn.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_events.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_flags.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_lsp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_misc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_network.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_pdu.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_route.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_routemap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_spf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_tlv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isis_zebra.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isisd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso_checksum.Po@am__quote@
+
+distclean-depend:
+	-rm -rf ./$(DEPDIR)
+
+.c.o:
+@AMDEP_TRUE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+	$(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+@AMDEP_TRUE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+	$(COMPILE) -c `cygpath -w $<`
+CCDEPMODE = @CCDEPMODE@
+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 =
+
+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
+
+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
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@list='$(DISTFILES)'; for file in $$list; do \
+	  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
+
+uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS \
+	uninstall-sysconfDATA
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstLIBRARIES clean-sbinPROGRAMS 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 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
+
+depend:
+	@$(CPP) -MM $(INCLUDES) $(LDFLAGS) *.c
+
+isis_adjacency.o : isis_adjacency.c ../lib/version.h ../lib/log.h \
+ ../isisd/isis_adjacency.h
+isis_pdu.o : isis_pdu.c ../lib/log.h ../isisd/isisd.h \
+ ../isisd/isis_constants.h ../isisd/isis_adjacency.h \
+ ../isisd/isis_pdu.h
+isis_circuit.o : isis_circuit.c ../isisd/isis_circuit.h
+# 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/isisd/README b/isisd/README
new file mode 100644
index 0000000..6e2198d
--- /dev/null
+++ b/isisd/README
@@ -0,0 +1,20 @@
+Modified files in the ZEBRA-0.92a package.
+
+ ../configure.in
+ ../Makefile.am
+ ../acconfig.h
+ ../lib/log.h
+ ../lib/memory.h
+ ../lib/vty.c
+   - case ISIS_NODE:
+ ../lib/command.c
+   - case ISIS_NODE:
+ ../lib/command.h
+   - ISIS_NODE,                    /* IS-IS protocol mode */
+   - str #definitions
+
+
+Constraints
+
+  o Maximum number of interfaces 255
+
diff --git a/isisd/TODO b/isisd/TODO
new file mode 100644
index 0000000..e3c1352
--- /dev/null
+++ b/isisd/TODO
@@ -0,0 +1,10 @@
+Things in the TODO list for the near future
+
+o select nearest L2 when running SPF for L1
+o remove the routes when holding time for nexthop expires
+o redist 
+o autosummary
+
+Not so urgent:
+
+o Mesh groups
diff --git a/isisd/dict.c b/isisd/dict.c
new file mode 100644
index 0000000..4c787ac
--- /dev/null
+++ b/isisd/dict.c
@@ -0,0 +1,1496 @@
+/*
+ * Dictionary Abstract Data Type
+ * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
+ *
+ * Free Software License:
+ *
+ * All rights are reserved by the author, with the following exceptions:
+ * Permission is granted to freely reproduce and distribute this software,
+ * possibly in exchange for a fee, provided that this copyright notice appears
+ * intact. Permission is also granted to adapt this software to produce
+ * derivative works, as long as the modified versions carry this copyright
+ * notice and additional notices stating that the work has been modified.
+ * This source code may be translated into executable form and incorporated
+ * into proprietary software; there is no requirement for such software to
+ * contain a copyright notice related to this source.
+ *
+ * $Id: dict.c,v 1.1 2003/12/23 08:09:47 jardin Exp $
+ * $Name:  $
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#define DICT_IMPLEMENTATION
+#include "dict.h"
+
+#ifdef KAZLIB_RCSID
+static const char rcsid[] = "$Id: dict.c,v 1.1 2003/12/23 08:09:47 jardin Exp $";
+#endif
+
+/*
+ * These macros provide short convenient names for structure members,
+ * which are embellished with dict_ prefixes so that they are
+ * properly confined to the documented namespace. It's legal for a 
+ * program which uses dict to define, for instance, a macro called ``parent''.
+ * Such a macro would interfere with the dnode_t struct definition.
+ * In general, highly portable and reusable C modules which expose their
+ * structures need to confine structure member names to well-defined spaces.
+ * The resulting identifiers aren't necessarily convenient to use, nor
+ * readable, in the implementation, however!
+ */
+
+#define left dict_left
+#define right dict_right
+#define parent dict_parent
+#define color dict_color
+#define key dict_key
+#define data dict_data
+
+#define nilnode dict_nilnode
+#define nodecount dict_nodecount
+#define maxcount dict_maxcount
+#define compare dict_compare
+#define allocnode dict_allocnode
+#define freenode dict_freenode
+#define context dict_context
+#define dupes dict_dupes
+
+#define dictptr dict_dictptr
+
+#define dict_root(D) ((D)->nilnode.left)
+#define dict_nil(D) (&(D)->nilnode)
+#define DICT_DEPTH_MAX 64
+
+static dnode_t *dnode_alloc(void *context);
+static void dnode_free(dnode_t *node, void *context);
+
+/*
+ * Perform a ``left rotation'' adjustment on the tree.  The given node P and
+ * its right child C are rearranged so that the P instead becomes the left
+ * child of C.   The left subtree of C is inherited as the new right subtree
+ * for P.  The ordering of the keys within the tree is thus preserved.
+ */
+
+static void rotate_left(dnode_t *upper)
+{
+    dnode_t *lower, *lowleft, *upparent;
+
+    lower = upper->right;
+    upper->right = lowleft = lower->left;
+    lowleft->parent = upper;
+
+    lower->parent = upparent = upper->parent;
+
+    /* don't need to check for root node here because root->parent is
+       the sentinel nil node, and root->parent->left points back to root */
+
+    if (upper == upparent->left) {
+	upparent->left = lower;
+    } else {
+	assert (upper == upparent->right);
+	upparent->right = lower;
+    }
+
+    lower->left = upper;
+    upper->parent = lower;
+}
+
+/*
+ * This operation is the ``mirror'' image of rotate_left. It is
+ * the same procedure, but with left and right interchanged.
+ */
+
+static void rotate_right(dnode_t *upper)
+{
+    dnode_t *lower, *lowright, *upparent;
+
+    lower = upper->left;
+    upper->left = lowright = lower->right;
+    lowright->parent = upper;
+
+    lower->parent = upparent = upper->parent;
+
+    if (upper == upparent->right) {
+	upparent->right = lower;
+    } else {
+	assert (upper == upparent->left);
+	upparent->left = lower;
+    }
+
+    lower->right = upper;
+    upper->parent = lower;
+}
+
+/*
+ * Do a postorder traversal of the tree rooted at the specified
+ * node and free everything under it.  Used by dict_free().
+ */
+
+static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
+{
+    if (node == nil)
+	return;
+    free_nodes(dict, node->left, nil);
+    free_nodes(dict, node->right, nil);
+    dict->freenode(node, dict->context);
+}
+
+/*
+ * This procedure performs a verification that the given subtree is a binary
+ * search tree. It performs an inorder traversal of the tree using the
+ * dict_next() successor function, verifying that the key of each node is
+ * strictly lower than that of its successor, if duplicates are not allowed,
+ * or lower or equal if duplicates are allowed.  This function is used for
+ * debugging purposes. 
+ */
+
+static int verify_bintree(dict_t *dict)
+{
+    dnode_t *first, *next;
+
+    first = dict_first(dict);
+
+    if (dict->dupes) {
+	while (first && (next = dict_next(dict, first))) {
+	    if (dict->compare(first->key, next->key) > 0)
+		return 0;
+	    first = next;
+	}
+    } else {
+	while (first && (next = dict_next(dict, first))) {
+	    if (dict->compare(first->key, next->key) >= 0)
+		return 0;
+	    first = next;
+	}
+    }
+    return 1;
+}
+
+
+/*
+ * This function recursively verifies that the given binary subtree satisfies
+ * three of the red black properties. It checks that every red node has only
+ * black children. It makes sure that each node is either red or black. And it
+ * checks that every path has the same count of black nodes from root to leaf.
+ * It returns the blackheight of the given subtree; this allows blackheights to
+ * be computed recursively and compared for left and right siblings for
+ * mismatches. It does not check for every nil node being black, because there
+ * is only one sentinel nil node. The return value of this function is the
+ * black height of the subtree rooted at the node ``root'', or zero if the
+ * subtree is not red-black.
+ */
+
+static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
+{
+    unsigned height_left, height_right;
+
+    if (root != nil) {
+	height_left = verify_redblack(nil, root->left);
+	height_right = verify_redblack(nil, root->right);
+	if (height_left == 0 || height_right == 0)
+	    return 0;
+	if (height_left != height_right)
+	    return 0;
+	if (root->color == dnode_red) {
+	    if (root->left->color != dnode_black)
+		return 0;
+	    if (root->right->color != dnode_black)
+		return 0;
+	    return height_left;
+	}
+	if (root->color != dnode_black)
+	    return 0;
+	return height_left + 1;
+    } 
+    return 1;
+}
+
+/*
+ * Compute the actual count of nodes by traversing the tree and
+ * return it. This could be compared against the stored count to
+ * detect a mismatch.
+ */
+
+static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
+{
+    if (root == nil)
+	return 0;
+    else
+	return 1 + verify_node_count(nil, root->left)
+	    + verify_node_count(nil, root->right);
+}
+
+/*
+ * Verify that the tree contains the given node. This is done by
+ * traversing all of the nodes and comparing their pointers to the
+ * given pointer. Returns 1 if the node is found, otherwise
+ * returns zero. It is intended for debugging purposes.
+ */
+
+static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
+{
+    if (root != nil) {
+	return root == node
+		|| verify_dict_has_node(nil, root->left, node)
+		|| verify_dict_has_node(nil, root->right, node);
+    }
+    return 0;
+}
+
+
+/*
+ * Dynamically allocate and initialize a dictionary object.
+ */
+
+dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
+{
+    dict_t *new = malloc(sizeof *new);
+
+    if (new) {
+	new->compare = comp;
+	new->allocnode = dnode_alloc;
+	new->freenode = dnode_free;
+	new->context = NULL;
+	new->nodecount = 0;
+	new->maxcount = maxcount;
+	new->nilnode.left = &new->nilnode;
+	new->nilnode.right = &new->nilnode;
+	new->nilnode.parent = &new->nilnode;
+	new->nilnode.color = dnode_black;
+	new->dupes = 0;
+    }
+    return new;
+}
+
+/*
+ * Select a different set of node allocator routines.
+ */
+
+void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
+	dnode_free_t fr, void *context)
+{
+    assert (dict_count(dict) == 0);
+    assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
+
+    dict->allocnode = al ? al : dnode_alloc;
+    dict->freenode = fr ? fr : dnode_free;
+    dict->context = context;
+}
+
+/*
+ * Free a dynamically allocated dictionary object. Removing the nodes
+ * from the tree before deleting it is required.
+ */
+
+void dict_destroy(dict_t *dict)
+{
+    assert (dict_isempty(dict));
+    free(dict);
+}
+
+/*
+ * Free all the nodes in the dictionary by using the dictionary's
+ * installed free routine. The dictionary is emptied.
+ */
+
+void dict_free_nodes(dict_t *dict)
+{
+    dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
+    free_nodes(dict, root, nil);
+    dict->nodecount = 0;
+    dict->nilnode.left = &dict->nilnode;
+    dict->nilnode.right = &dict->nilnode;
+}
+
+/*
+ * Obsolescent function, equivalent to dict_free_nodes
+ */
+
+void dict_free(dict_t *dict)
+{
+#ifdef KAZLIB_OBSOLESCENT_DEBUG
+    assert ("call to obsolescent function dict_free()" && 0);
+#endif
+    dict_free_nodes(dict);
+}
+
+/*
+ * Initialize a user-supplied dictionary object.
+ */
+
+dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
+{
+    dict->compare = comp;
+    dict->allocnode = dnode_alloc;
+    dict->freenode = dnode_free;
+    dict->context = NULL;
+    dict->nodecount = 0;
+    dict->maxcount = maxcount;
+    dict->nilnode.left = &dict->nilnode;
+    dict->nilnode.right = &dict->nilnode;
+    dict->nilnode.parent = &dict->nilnode;
+    dict->nilnode.color = dnode_black;
+    dict->dupes = 0;
+    return dict;
+}
+
+/* 
+ * Initialize a dictionary in the likeness of another dictionary
+ */
+
+void dict_init_like(dict_t *dict, const dict_t *template)
+{
+    dict->compare = template->compare;
+    dict->allocnode = template->allocnode;
+    dict->freenode = template->freenode;
+    dict->context = template->context;
+    dict->nodecount = 0;
+    dict->maxcount = template->maxcount;
+    dict->nilnode.left = &dict->nilnode;
+    dict->nilnode.right = &dict->nilnode;
+    dict->nilnode.parent = &dict->nilnode;
+    dict->nilnode.color = dnode_black;
+    dict->dupes = template->dupes;
+
+    assert (dict_similar(dict, template));
+}
+
+/*
+ * Remove all nodes from the dictionary (without freeing them in any way).
+ */
+
+static void dict_clear(dict_t *dict)
+{
+    dict->nodecount = 0;
+    dict->nilnode.left = &dict->nilnode;
+    dict->nilnode.right = &dict->nilnode;
+    dict->nilnode.parent = &dict->nilnode;
+    assert (dict->nilnode.color == dnode_black);
+}
+
+
+/*
+ * Verify the integrity of the dictionary structure.  This is provided for
+ * debugging purposes, and should be placed in assert statements.   Just because
+ * this function succeeds doesn't mean that the tree is not corrupt. Certain
+ * corruptions in the tree may simply cause undefined behavior.
+ */ 
+
+int dict_verify(dict_t *dict)
+{
+    dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
+
+    /* check that the sentinel node and root node are black */
+    if (root->color != dnode_black)
+	return 0;
+    if (nil->color != dnode_black)
+	return 0;
+    if (nil->right != nil)
+	return 0;
+    /* nil->left is the root node; check that its parent pointer is nil */
+    if (nil->left->parent != nil)
+	return 0;
+    /* perform a weak test that the tree is a binary search tree */
+    if (!verify_bintree(dict))
+	return 0;
+    /* verify that the tree is a red-black tree */
+    if (!verify_redblack(nil, root))
+	return 0;
+    if (verify_node_count(nil, root) != dict_count(dict))
+	return 0;
+    return 1;
+}
+
+/*
+ * Determine whether two dictionaries are similar: have the same comparison and
+ * allocator functions, and same status as to whether duplicates are allowed.
+ */
+
+int dict_similar(const dict_t *left, const dict_t *right)
+{
+    if (left->compare != right->compare)
+	return 0;
+
+    if (left->allocnode != right->allocnode)
+	return 0;
+
+    if (left->freenode != right->freenode)
+	return 0;
+
+    if (left->context != right->context)
+	return 0;
+
+    if (left->dupes != right->dupes)
+	return 0;
+
+    return 1;
+}
+
+/*
+ * Locate a node in the dictionary having the given key.
+ * If the node is not found, a null a pointer is returned (rather than 
+ * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
+ * located node is returned.
+ */
+
+dnode_t *dict_lookup(dict_t *dict, const void *key)
+{
+    dnode_t *root = dict_root(dict);
+    dnode_t *nil = dict_nil(dict);
+    dnode_t *saved;
+    int result;
+
+    /* simple binary search adapted for trees that contain duplicate keys */
+
+    while (root != nil) {
+	result = dict->compare(key, root->key);
+	if (result < 0)
+	    root = root->left;
+	else if (result > 0)
+	    root = root->right;
+	else {
+	    if (!dict->dupes) {	/* no duplicates, return match		*/
+		return root;
+	    } else {		/* could be dupes, find leftmost one	*/
+		do {
+		    saved = root;
+		    root = root->left;
+		    while (root != nil && dict->compare(key, root->key))
+			root = root->right;
+		} while (root != nil);
+		return saved;
+	    }
+	}
+    }
+
+    return NULL;
+}
+
+/*
+ * Look for the node corresponding to the lowest key that is equal to or
+ * greater than the given key.  If there is no such node, return null.
+ */
+
+dnode_t *dict_lower_bound(dict_t *dict, const void *key)
+{
+    dnode_t *root = dict_root(dict);
+    dnode_t *nil = dict_nil(dict);
+    dnode_t *tentative = 0;
+
+    while (root != nil) {
+	int result = dict->compare(key, root->key);
+
+	if (result > 0) {
+	    root = root->right;
+	} else if (result < 0) {
+	    tentative = root;
+	    root = root->left;
+	} else {
+	    if (!dict->dupes) {
+	    	return root;
+	    } else {
+		tentative = root;
+		root = root->left;
+	    }
+	} 
+    }
+    
+    return tentative;
+}
+
+/*
+ * Look for the node corresponding to the greatest key that is equal to or
+ * lower than the given key.  If there is no such node, return null.
+ */
+
+dnode_t *dict_upper_bound(dict_t *dict, const void *key)
+{
+    dnode_t *root = dict_root(dict);
+    dnode_t *nil = dict_nil(dict);
+    dnode_t *tentative = 0;
+
+    while (root != nil) {
+	int result = dict->compare(key, root->key);
+
+	if (result < 0) {
+	    root = root->left;
+	} else if (result > 0) {
+	    tentative = root;
+	    root = root->right;
+	} else {
+	    if (!dict->dupes) {
+	    	return root;
+	    } else {
+		tentative = root;
+		root = root->right;
+	    }
+	} 
+    }
+    
+    return tentative;
+}
+
+/*
+ * Insert a node into the dictionary. The node should have been
+ * initialized with a data field. All other fields are ignored.
+ * The behavior is undefined if the user attempts to insert into
+ * a dictionary that is already full (for which the dict_isfull()
+ * function returns true).
+ */
+
+void dict_insert(dict_t *dict, dnode_t *node, const void *key)
+{
+    dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
+    dnode_t *parent = nil, *uncle, *grandpa;
+    int result = -1;
+
+    node->key = key;
+
+    assert (!dict_isfull(dict));
+    assert (!dict_contains(dict, node));
+    assert (!dnode_is_in_a_dict(node));
+
+    /* basic binary tree insert */
+
+    while (where != nil) {
+	parent = where;
+	result = dict->compare(key, where->key);
+	/* trap attempts at duplicate key insertion unless it's explicitly allowed */
+	assert (dict->dupes || result != 0);
+	if (result < 0)
+	    where = where->left;
+	else
+	    where = where->right;
+    }
+
+    assert (where == nil);
+
+    if (result < 0)
+	parent->left = node;
+    else
+	parent->right = node;
+
+    node->parent = parent;
+    node->left = nil;
+    node->right = nil;
+
+    dict->nodecount++;
+
+    /* red black adjustments */
+
+    node->color = dnode_red;
+
+    while (parent->color == dnode_red) {
+	grandpa = parent->parent;
+	if (parent == grandpa->left) {
+	    uncle = grandpa->right;
+	    if (uncle->color == dnode_red) {	/* red parent, red uncle */
+		parent->color = dnode_black;
+		uncle->color = dnode_black;
+		grandpa->color = dnode_red;
+		node = grandpa;
+		parent = grandpa->parent;
+	    } else {				/* red parent, black uncle */
+	    	if (node == parent->right) {
+		    rotate_left(parent);
+		    parent = node;
+		    assert (grandpa == parent->parent);
+		    /* rotation between parent and child preserves grandpa */
+		}
+		parent->color = dnode_black;
+		grandpa->color = dnode_red;
+		rotate_right(grandpa);
+		break;
+	    }
+	} else { 	/* symmetric cases: parent == parent->parent->right */
+	    uncle = grandpa->left;
+	    if (uncle->color == dnode_red) {
+		parent->color = dnode_black;
+		uncle->color = dnode_black;
+		grandpa->color = dnode_red;
+		node = grandpa;
+		parent = grandpa->parent;
+	    } else {
+	    	if (node == parent->left) {
+		    rotate_right(parent);
+		    parent = node;
+		    assert (grandpa == parent->parent);
+		}
+		parent->color = dnode_black;
+		grandpa->color = dnode_red;
+		rotate_left(grandpa);
+		break;
+	    }
+	}
+    }
+
+    dict_root(dict)->color = dnode_black;
+
+    assert (dict_verify(dict));
+}
+
+/*
+ * Delete the given node from the dictionary. If the given node does not belong
+ * to the given dictionary, undefined behavior results.  A pointer to the
+ * deleted node is returned.
+ */
+
+dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
+{
+    dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
+
+    /* basic deletion */
+
+    assert (!dict_isempty(dict));
+    assert (dict_contains(dict, delete));
+
+    /*
+     * If the node being deleted has two children, then we replace it with its
+     * successor (i.e. the leftmost node in the right subtree.) By doing this,
+     * we avoid the traditional algorithm under which the successor's key and
+     * value *only* move to the deleted node and the successor is spliced out
+     * from the tree. We cannot use this approach because the user may hold
+     * pointers to the successor, or nodes may be inextricably tied to some
+     * other structures by way of embedding, etc. So we must splice out the
+     * node we are given, not some other node, and must not move contents from
+     * one node to another behind the user's back.
+     */
+
+    if (delete->left != nil && delete->right != nil) {
+	dnode_t *next = dict_next(dict, delete);
+	dnode_t *nextparent = next->parent;
+	dnode_color_t nextcolor = next->color;
+
+	assert (next != nil);
+	assert (next->parent != nil);
+	assert (next->left == nil);
+
+	/*
+	 * First, splice out the successor from the tree completely, by
+	 * moving up its right child into its place.
+	 */
+
+	child = next->right;
+	child->parent = nextparent;
+
+	if (nextparent->left == next) {
+	    nextparent->left = child;
+	} else {
+	    assert (nextparent->right == next);
+	    nextparent->right = child;
+	}
+
+	/*
+	 * Now that the successor has been extricated from the tree, install it
+	 * in place of the node that we want deleted.
+	 */
+
+	next->parent = delparent;
+	next->left = delete->left;
+	next->right = delete->right;
+	next->left->parent = next;
+	next->right->parent = next;
+	next->color = delete->color;
+	delete->color = nextcolor;
+
+	if (delparent->left == delete) {
+	    delparent->left = next;
+	} else {
+	    assert (delparent->right == delete);
+	    delparent->right = next;
+	}
+
+    } else {
+	assert (delete != nil);
+	assert (delete->left == nil || delete->right == nil);
+
+	child = (delete->left != nil) ? delete->left : delete->right;
+
+	child->parent = delparent = delete->parent;	    
+
+	if (delete == delparent->left) {
+	    delparent->left = child;    
+	} else {
+	    assert (delete == delparent->right);
+	    delparent->right = child;
+	}
+    }
+
+    delete->parent = NULL;
+    delete->right = NULL;
+    delete->left = NULL;
+
+    dict->nodecount--;
+
+    assert (verify_bintree(dict));
+
+    /* red-black adjustments */
+
+    if (delete->color == dnode_black) {
+	dnode_t *parent, *sister;
+
+	dict_root(dict)->color = dnode_red;
+
+	while (child->color == dnode_black) {
+	    parent = child->parent;
+	    if (child == parent->left) {
+		sister = parent->right;
+		assert (sister != nil);
+		if (sister->color == dnode_red) {
+		    sister->color = dnode_black;
+		    parent->color = dnode_red;
+		    rotate_left(parent);
+		    sister = parent->right;
+		    assert (sister != nil);
+		}
+		if (sister->left->color == dnode_black
+			&& sister->right->color == dnode_black) {
+		    sister->color = dnode_red;
+		    child = parent;
+		} else {
+		    if (sister->right->color == dnode_black) {
+			assert (sister->left->color == dnode_red);
+			sister->left->color = dnode_black;
+			sister->color = dnode_red;
+			rotate_right(sister);
+			sister = parent->right;
+			assert (sister != nil);
+		    }
+		    sister->color = parent->color;
+		    sister->right->color = dnode_black;
+		    parent->color = dnode_black;
+		    rotate_left(parent);
+		    break;
+		}
+	    } else {	/* symmetric case: child == child->parent->right */
+		assert (child == parent->right);
+		sister = parent->left;
+		assert (sister != nil);
+		if (sister->color == dnode_red) {
+		    sister->color = dnode_black;
+		    parent->color = dnode_red;
+		    rotate_right(parent);
+		    sister = parent->left;
+		    assert (sister != nil);
+		}
+		if (sister->right->color == dnode_black
+			&& sister->left->color == dnode_black) {
+		    sister->color = dnode_red;
+		    child = parent;
+		} else {
+		    if (sister->left->color == dnode_black) {
+			assert (sister->right->color == dnode_red);
+			sister->right->color = dnode_black;
+			sister->color = dnode_red;
+			rotate_left(sister);
+			sister = parent->left;
+			assert (sister != nil);
+		    }
+		    sister->color = parent->color;
+		    sister->left->color = dnode_black;
+		    parent->color = dnode_black;
+		    rotate_right(parent);
+		    break;
+		}
+	    }
+	}
+
+	child->color = dnode_black;
+	dict_root(dict)->color = dnode_black;
+    }
+
+    assert (dict_verify(dict));
+
+    return delete;
+}
+
+/*
+ * Allocate a node using the dictionary's allocator routine, give it
+ * the data item.
+ */
+
+int dict_alloc_insert(dict_t *dict, const void *key, void *data)
+{
+    dnode_t *node = dict->allocnode(dict->context);
+
+    if (node) {
+	dnode_init(node, data);
+	dict_insert(dict, node, key);
+	return 1;
+    }
+    return 0;
+}
+
+void dict_delete_free(dict_t *dict, dnode_t *node)
+{
+    dict_delete(dict, node);
+    dict->freenode(node, dict->context);
+}
+
+/*
+ * Return the node with the lowest (leftmost) key. If the dictionary is empty
+ * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
+ */
+
+dnode_t *dict_first(dict_t *dict)
+{
+    dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
+
+    if (root != nil)
+	while ((left = root->left) != nil)
+	    root = left;
+
+    return (root == nil) ? NULL : root;
+}
+
+/*
+ * Return the node with the highest (rightmost) key. If the dictionary is empty
+ * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
+ */
+
+dnode_t *dict_last(dict_t *dict)
+{
+    dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
+
+    if (root != nil)
+	while ((right = root->right) != nil)
+	    root = right;
+
+    return (root == nil) ? NULL : root;
+}
+
+/*
+ * Return the given node's successor node---the node which has the
+ * next key in the the left to right ordering. If the node has
+ * no successor, a null pointer is returned rather than a pointer to
+ * the nil node.
+ */
+
+dnode_t *dict_next(dict_t *dict, dnode_t *curr)
+{
+    dnode_t *nil = dict_nil(dict), *parent, *left;
+
+    if (curr->right != nil) {
+	curr = curr->right;
+	while ((left = curr->left) != nil)
+	    curr = left;
+	return curr;
+    }
+
+    parent = curr->parent;
+
+    while (parent != nil && curr == parent->right) {
+	curr = parent;
+	parent = curr->parent;
+    }
+
+    return (parent == nil) ? NULL : parent;
+}
+
+/*
+ * Return the given node's predecessor, in the key order.
+ * The nil sentinel node is returned if there is no predecessor.
+ */
+
+dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
+{
+    dnode_t *nil = dict_nil(dict), *parent, *right;
+
+    if (curr->left != nil) {
+	curr = curr->left;
+	while ((right = curr->right) != nil)
+	    curr = right;
+	return curr;
+    }
+
+    parent = curr->parent;
+
+    while (parent != nil && curr == parent->left) {
+	curr = parent;
+	parent = curr->parent;
+    }
+
+    return (parent == nil) ? NULL : parent;
+}
+
+void dict_allow_dupes(dict_t *dict)
+{
+    dict->dupes = 1;
+}
+
+#undef dict_count
+#undef dict_isempty
+#undef dict_isfull
+#undef dnode_get
+#undef dnode_put
+#undef dnode_getkey
+
+dictcount_t dict_count(dict_t *dict)
+{
+    return dict->nodecount;
+}
+
+int dict_isempty(dict_t *dict)
+{
+    return dict->nodecount == 0;
+}
+
+int dict_isfull(dict_t *dict)
+{
+    return dict->nodecount == dict->maxcount;
+}
+
+int dict_contains(dict_t *dict, dnode_t *node)
+{
+    return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
+}
+
+static dnode_t *dnode_alloc(void *context)
+{
+    return malloc(sizeof *dnode_alloc(NULL));
+}
+
+static void dnode_free(dnode_t *node, void *context)
+{
+    free(node);
+}
+
+dnode_t *dnode_create(void *data)
+{
+    dnode_t *new = malloc(sizeof *new);
+    if (new) {
+	new->data = data;
+	new->parent = NULL;
+	new->left = NULL;
+	new->right = NULL;
+    }
+    return new;
+}
+
+dnode_t *dnode_init(dnode_t *dnode, void *data)
+{
+    dnode->data = data;
+    dnode->parent = NULL;
+    dnode->left = NULL;
+    dnode->right = NULL;
+    return dnode;
+}
+
+void dnode_destroy(dnode_t *dnode)
+{
+    assert (!dnode_is_in_a_dict(dnode));
+    free(dnode);
+}
+
+void *dnode_get(dnode_t *dnode)
+{
+    return dnode->data;
+}
+
+const void *dnode_getkey(dnode_t *dnode)
+{
+    return dnode->key;
+}
+
+void dnode_put(dnode_t *dnode, void *data)
+{
+    dnode->data = data;
+}
+
+int dnode_is_in_a_dict(dnode_t *dnode)
+{
+    return (dnode->parent && dnode->left && dnode->right);
+}
+
+void dict_process(dict_t *dict, void *context, dnode_process_t function)
+{
+    dnode_t *node = dict_first(dict), *next;
+
+    while (node != NULL) {
+	/* check for callback function deleting	*/
+	/* the next node from under us		*/
+	assert (dict_contains(dict, node));
+	next = dict_next(dict, node);
+	function(dict, node, context);
+	node = next;
+    }
+}
+
+static void load_begin_internal(dict_load_t *load, dict_t *dict)
+{
+    load->dictptr = dict;
+    load->nilnode.left = &load->nilnode;
+    load->nilnode.right = &load->nilnode;
+}
+
+void dict_load_begin(dict_load_t *load, dict_t *dict)
+{
+    assert (dict_isempty(dict));
+    load_begin_internal(load, dict);
+}
+
+void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
+{
+    dict_t *dict = load->dictptr;
+    dnode_t *nil = &load->nilnode;
+   
+    assert (!dnode_is_in_a_dict(newnode));
+    assert (dict->nodecount < dict->maxcount);
+
+    #ifndef NDEBUG
+    if (dict->nodecount > 0) {
+	if (dict->dupes)
+	    assert (dict->compare(nil->left->key, key) <= 0);
+	else
+	    assert (dict->compare(nil->left->key, key) < 0);
+    }
+    #endif
+
+    newnode->key = key;
+    nil->right->left = newnode;
+    nil->right = newnode;
+    newnode->left = nil;
+    dict->nodecount++;
+}
+
+void dict_load_end(dict_load_t *load)
+{
+    dict_t *dict = load->dictptr;
+    dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
+    dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
+    dnode_t *complete = 0;
+    dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
+    dictcount_t botrowcount;
+    unsigned baselevel = 0, level = 0, i;
+
+    assert (dnode_red == 0 && dnode_black == 1);
+
+    while (fullcount >= nodecount && fullcount)
+	fullcount >>= 1;
+
+    botrowcount = nodecount - fullcount;
+
+    for (curr = loadnil->left; curr != loadnil; curr = next) {
+	next = curr->left;
+
+	if (complete == NULL && botrowcount-- == 0) {
+	    assert (baselevel == 0);
+	    assert (level == 0);
+	    baselevel = level = 1;
+	    complete = tree[0];
+
+	    if (complete != 0) {
+		tree[0] = 0;
+		complete->right = dictnil;
+		while (tree[level] != 0) {
+		    tree[level]->right = complete;
+		    complete->parent = tree[level];
+		    complete = tree[level];
+		    tree[level++] = 0;
+		}
+	    }
+	}
+
+	if (complete == NULL) {
+	    curr->left = dictnil;
+	    curr->right = dictnil;
+	    curr->color = level % 2;
+	    complete = curr;
+
+	    assert (level == baselevel);
+	    while (tree[level] != 0) {
+		tree[level]->right = complete;
+		complete->parent = tree[level];
+		complete = tree[level];
+		tree[level++] = 0;
+	    }
+	} else {
+	    curr->left = complete;
+	    curr->color = (level + 1) % 2;
+	    complete->parent = curr;
+	    tree[level] = curr;
+	    complete = 0;
+	    level = baselevel;
+	}
+    }
+
+    if (complete == NULL)
+	complete = dictnil;
+
+    for (i = 0; i < DICT_DEPTH_MAX; i++) {
+	if (tree[i] != 0) {
+	    tree[i]->right = complete;
+	    complete->parent = tree[i];
+	    complete = tree[i];
+	}
+    }
+
+    dictnil->color = dnode_black;
+    dictnil->right = dictnil;
+    complete->parent = dictnil;
+    complete->color = dnode_black;
+    dict_root(dict) = complete;
+
+    assert (dict_verify(dict));
+}
+
+void dict_merge(dict_t *dest, dict_t *source)
+{
+    dict_load_t load;
+    dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
+
+    assert (dict_similar(dest, source));	
+
+    if (source == dest)
+	return;
+
+    dest->nodecount = 0;
+    load_begin_internal(&load, dest);
+
+    for (;;) {
+	if (leftnode != NULL && rightnode != NULL) {
+	    if (dest->compare(leftnode->key, rightnode->key) < 0)
+		goto copyleft;
+	    else
+		goto copyright;
+	} else if (leftnode != NULL) {
+	    goto copyleft;
+	} else if (rightnode != NULL) {
+	    goto copyright;
+	} else {
+	    assert (leftnode == NULL && rightnode == NULL);
+	    break;
+	}
+
+    copyleft:
+	{
+	    dnode_t *next = dict_next(dest, leftnode);
+	    #ifndef NDEBUG
+	    leftnode->left = NULL;	/* suppress assertion in dict_load_next */
+	    #endif
+	    dict_load_next(&load, leftnode, leftnode->key);
+	    leftnode = next;
+	    continue;
+	}
+	
+    copyright:
+	{
+	    dnode_t *next = dict_next(source, rightnode);
+	    #ifndef NDEBUG
+	    rightnode->left = NULL;
+	    #endif
+	    dict_load_next(&load, rightnode, rightnode->key);
+	    rightnode = next;
+	    continue;
+	}
+    }
+
+    dict_clear(source);
+    dict_load_end(&load);
+}
+
+#ifdef KAZLIB_TEST_MAIN
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+typedef char input_t[256];
+
+static int tokenize(char *string, ...)
+{
+    char **tokptr; 
+    va_list arglist;
+    int tokcount = 0;
+
+    va_start(arglist, string);
+    tokptr = va_arg(arglist, char **);
+    while (tokptr) {
+	while (*string && isspace((unsigned char) *string))
+	    string++;
+	if (!*string)
+	    break;
+	*tokptr = string;
+	while (*string && !isspace((unsigned char) *string))
+	    string++;
+	tokptr = va_arg(arglist, char **);
+	tokcount++;
+	if (!*string)
+	    break;
+	*string++ = 0;
+    }
+    va_end(arglist);
+
+    return tokcount;
+}
+
+static int comparef(const void *key1, const void *key2)
+{
+    return strcmp(key1, key2);
+}
+
+static char *dupstring(char *str)
+{
+    int sz = strlen(str) + 1;
+    char *new = malloc(sz);
+    if (new)
+	memcpy(new, str, sz);
+    return new;
+}
+
+static dnode_t *new_node(void *c)
+{
+    static dnode_t few[5];
+    static int count;
+
+    if (count < 5)
+	return few + count++;
+
+    return NULL;
+}
+
+static void del_node(dnode_t *n, void *c)
+{
+}
+
+static int prompt = 0;
+
+static void construct(dict_t *d)
+{
+    input_t in;
+    int done = 0;
+    dict_load_t dl;
+    dnode_t *dn;
+    char *tok1, *tok2, *val;
+    const char *key;
+    char *help = 
+	"p                      turn prompt on\n"
+	"q                      finish construction\n"
+	"a <key> <val>          add new entry\n";
+
+    if (!dict_isempty(d))
+	puts("warning: dictionary not empty!");
+
+    dict_load_begin(&dl, d);
+
+    while (!done) {
+	if (prompt)
+	    putchar('>');
+	fflush(stdout);
+
+	if (!fgets(in, sizeof(input_t), stdin))
+	    break;
+
+	switch (in[0]) {
+	    case '?':
+		puts(help);
+		break;
+	    case 'p':
+		prompt = 1;
+		break;
+	    case 'q':
+		done = 1;
+		break;
+	    case 'a':
+		if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
+		    puts("what?");
+		    break;
+		}
+		key = dupstring(tok1);
+		val = dupstring(tok2);
+		dn = dnode_create(val);
+
+		if (!key || !val || !dn) {
+		    puts("out of memory");
+		    free((void *) key);
+		    free(val);
+		    if (dn)
+			dnode_destroy(dn);
+		}
+
+		dict_load_next(&dl, dn, key);
+		break;
+	    default:
+		putchar('?');
+		putchar('\n');
+		break;
+	}
+    }
+
+    dict_load_end(&dl);
+}
+
+int main(void)
+{
+    input_t in;
+    dict_t darray[10];
+    dict_t *d = &darray[0];
+    dnode_t *dn;
+    int i;
+    char *tok1, *tok2, *val;
+    const char *key;
+
+    char *help =
+	"a <key> <val>          add value to dictionary\n"
+	"d <key>                delete value from dictionary\n"
+	"l <key>                lookup value in dictionary\n"
+	"( <key>                lookup lower bound\n"
+	") <key>                lookup upper bound\n"
+	"# <num>                switch to alternate dictionary (0-9)\n"
+	"j <num> <num>          merge two dictionaries\n"
+	"f                      free the whole dictionary\n"
+	"k                      allow duplicate keys\n"
+	"c                      show number of entries\n"
+	"t                      dump whole dictionary in sort order\n"
+	"m                      make dictionary out of sorted items\n"
+	"p                      turn prompt on\n"
+	"s                      switch to non-functioning allocator\n"
+	"q                      quit";
+
+    for (i = 0; i < sizeof darray / sizeof *darray; i++)
+	dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
+
+    for (;;) {
+	if (prompt)
+	    putchar('>');
+	fflush(stdout);
+
+	if (!fgets(in, sizeof(input_t), stdin))
+	    break;
+
+	switch(in[0]) {
+	    case '?':
+		puts(help);
+		break;
+	    case 'a':
+		if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
+		    puts("what?");
+		    break;
+		}
+		key = dupstring(tok1);
+		val = dupstring(tok2);
+
+		if (!key || !val) {
+		    puts("out of memory");
+		    free((void *) key);
+		    free(val);
+		}
+
+		if (!dict_alloc_insert(d, key, val)) {
+		    puts("dict_alloc_insert failed");
+		    free((void *) key);
+		    free(val);
+		    break;
+		}
+		break;
+	    case 'd':
+		if (tokenize(in+1, &tok1, (char **) 0) != 1) {
+		    puts("what?");
+		    break;
+		}
+		dn = dict_lookup(d, tok1);
+		if (!dn) {
+		    puts("dict_lookup failed");
+		    break;
+		}
+		val = dnode_get(dn);
+		key = dnode_getkey(dn);
+		dict_delete_free(d, dn);
+
+		free(val);
+		free((void *) key);
+		break;
+	    case 'f':
+		dict_free(d);
+		break;
+	    case 'l':
+	    case '(':
+	    case ')':
+		if (tokenize(in+1, &tok1, (char **) 0) != 1) {
+		    puts("what?");
+		    break;
+		}
+		dn = 0;
+		switch (in[0]) {
+		case 'l':
+		    dn = dict_lookup(d, tok1);
+		    break;
+		case '(':
+		    dn = dict_lower_bound(d, tok1);
+		    break;
+		case ')':
+		    dn = dict_upper_bound(d, tok1);
+		    break;
+		}
+		if (!dn) {
+		    puts("lookup failed");
+		    break;
+		}
+		val = dnode_get(dn);
+		puts(val);
+		break;
+	    case 'm':
+		construct(d);
+		break;
+	    case 'k':
+		dict_allow_dupes(d);
+		break;
+	    case 'c':
+		printf("%lu\n", (unsigned long) dict_count(d));
+		break;
+	    case 't':
+		for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
+		    printf("%s\t%s\n", (char *) dnode_getkey(dn),
+			    (char *) dnode_get(dn));
+		}
+		break;
+	    case 'q':
+		exit(0);
+		break;
+	    case '\0':
+		break;
+	    case 'p':
+		prompt = 1;
+		break;
+	    case 's':
+		dict_set_allocator(d, new_node, del_node, NULL);
+		break;
+	    case '#':
+		if (tokenize(in+1, &tok1, (char **) 0) != 1) {
+		    puts("what?");
+		    break;
+		} else {
+		    int dictnum = atoi(tok1);
+		    if (dictnum < 0 || dictnum > 9) {
+			puts("invalid number");
+			break;
+		    }
+		    d = &darray[dictnum];
+		}
+		break;
+	    case 'j':
+		if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
+		    puts("what?");
+		    break;
+		} else {
+		    int dict1 = atoi(tok1), dict2 = atoi(tok2);
+		    if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
+			puts("invalid number");
+			break;
+		    }
+		    dict_merge(&darray[dict1], &darray[dict2]);
+		}
+		break;
+	    default:
+		putchar('?');
+		putchar('\n');
+		break;
+	}
+    }
+
+    return 0;
+}
+
+#endif
diff --git a/isisd/dict.h b/isisd/dict.h
new file mode 100644
index 0000000..2977a90
--- /dev/null
+++ b/isisd/dict.h
@@ -0,0 +1,144 @@
+/*
+ * Dictionary Abstract Data Type
+ * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
+ *
+ * Free Software License:
+ *
+ * All rights are reserved by the author, with the following exceptions:
+ * Permission is granted to freely reproduce and distribute this software,
+ * possibly in exchange for a fee, provided that this copyright notice appears
+ * intact. Permission is also granted to adapt this software to produce
+ * derivative works, as long as the modified versions carry this copyright
+ * notice and additional notices stating that the work has been modified.
+ * This source code may be translated into executable form and incorporated
+ * into proprietary software; there is no requirement for such software to
+ * contain a copyright notice related to this source.
+ *
+ * $Id: dict.h,v 1.1 2003/12/23 08:09:48 jardin Exp $
+ * $Name:  $
+ */
+
+#ifndef DICT_H
+#define DICT_H
+
+#include <limits.h>
+#ifdef KAZLIB_SIDEEFFECT_DEBUG
+#include "sfx.h"
+#endif
+
+/*
+ * Blurb for inclusion into C++ translation units
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned long dictcount_t;
+#define DICTCOUNT_T_MAX ULONG_MAX
+
+/*
+ * The dictionary is implemented as a red-black tree
+ */
+
+typedef enum { dnode_red, dnode_black } dnode_color_t;
+
+typedef struct dnode_t {
+    #if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
+    struct dnode_t *dict_left;
+    struct dnode_t *dict_right;
+    struct dnode_t *dict_parent;
+    dnode_color_t dict_color;
+    const void *dict_key;
+    void *dict_data;
+    #else
+    int dict_dummy;
+    #endif
+} dnode_t;
+
+typedef int (*dict_comp_t)(const void *, const void *);
+typedef dnode_t *(*dnode_alloc_t)(void *);
+typedef void (*dnode_free_t)(dnode_t *, void *);
+
+typedef struct dict_t {
+    #if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
+    dnode_t dict_nilnode;
+    dictcount_t dict_nodecount;
+    dictcount_t dict_maxcount;
+    dict_comp_t dict_compare;
+    dnode_alloc_t dict_allocnode;
+    dnode_free_t dict_freenode;
+    void *dict_context;
+    int dict_dupes;
+    #else
+    int dict_dummmy;
+    #endif
+} dict_t;
+
+typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
+
+typedef struct dict_load_t {
+    #if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
+    dict_t *dict_dictptr;
+    dnode_t dict_nilnode;
+    #else
+    int dict_dummmy;
+    #endif
+} dict_load_t;
+
+extern dict_t *dict_create(dictcount_t, dict_comp_t);
+extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *);
+extern void dict_destroy(dict_t *);
+extern void dict_free_nodes(dict_t *);
+extern void dict_free(dict_t *);
+extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t);
+extern void dict_init_like(dict_t *, const dict_t *);
+extern int dict_verify(dict_t *);
+extern int dict_similar(const dict_t *, const dict_t *);
+extern dnode_t *dict_lookup(dict_t *, const void *);
+extern dnode_t *dict_lower_bound(dict_t *, const void *);
+extern dnode_t *dict_upper_bound(dict_t *, const void *);
+extern void dict_insert(dict_t *, dnode_t *, const void *);
+extern dnode_t *dict_delete(dict_t *, dnode_t *);
+extern int dict_alloc_insert(dict_t *, const void *, void *);
+extern void dict_delete_free(dict_t *, dnode_t *);
+extern dnode_t *dict_first(dict_t *);
+extern dnode_t *dict_last(dict_t *);
+extern dnode_t *dict_next(dict_t *, dnode_t *);
+extern dnode_t *dict_prev(dict_t *, dnode_t *);
+extern dictcount_t dict_count(dict_t *);
+extern int dict_isempty(dict_t *);
+extern int dict_isfull(dict_t *);
+extern int dict_contains(dict_t *, dnode_t *);
+extern void dict_allow_dupes(dict_t *);
+extern int dnode_is_in_a_dict(dnode_t *);
+extern dnode_t *dnode_create(void *);
+extern dnode_t *dnode_init(dnode_t *, void *);
+extern void dnode_destroy(dnode_t *);
+extern void *dnode_get(dnode_t *);
+extern const void *dnode_getkey(dnode_t *);
+extern void dnode_put(dnode_t *, void *);
+extern void dict_process(dict_t *, void *, dnode_process_t);
+extern void dict_load_begin(dict_load_t *, dict_t *);
+extern void dict_load_next(dict_load_t *, dnode_t *, const void *);
+extern void dict_load_end(dict_load_t *);
+extern void dict_merge(dict_t *, dict_t *);
+
+#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
+#ifdef KAZLIB_SIDEEFFECT_DEBUG
+#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount)
+#else
+#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount)
+#endif
+#define dict_count(D) ((D)->dict_nodecount)
+#define dict_isempty(D) ((D)->dict_nodecount == 0)
+#define dnode_get(N) ((N)->dict_data)
+#define dnode_getkey(N) ((N)->dict_key)
+#define dnode_put(N, X) ((N)->dict_data = (X))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/isisd/include-netbsd/clnp.h b/isisd/include-netbsd/clnp.h
new file mode 100644
index 0000000..6bc3d25
--- /dev/null
+++ b/isisd/include-netbsd/clnp.h
@@ -0,0 +1,547 @@
+/*	$NetBSD: clnp.h,v 1.13 2001/08/20 12:00:54 wiz Exp $	*/

+

+/*-

+ * Copyright (c) 1991, 1993, 1994

+ *	The Regents of the University of California.  All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions

+ * are met:

+ * 1. Redistributions of source code must retain the above copyright

+ *    notice, this list of conditions and the following disclaimer.

+ * 2. Redistributions in binary form must reproduce the above copyright

+ *    notice, this list of conditions and the following disclaimer in the

+ *    documentation and/or other materials provided with the distribution.

+ * 3. All advertising materials mentioning features or use of this software

+ *    must display the following acknowledgement:

+ *	This product includes software developed by the University of

+ *	California, Berkeley and its contributors.

+ * 4. Neither the name of the University nor the names of its contributors

+ *    may be used to endorse or promote products derived from this software

+ *    without specific prior written permission.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE

+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

+ * SUCH DAMAGE.

+ *

+ *	@(#)clnp.h	8.2 (Berkeley) 4/16/94

+ */

+

+/***********************************************************

+		Copyright IBM Corporation 1987

+

+                      All Rights Reserved

+

+Permission to use, copy, modify, and distribute this software and its

+documentation for any purpose and without fee is hereby granted,

+provided that the above copyright notice appear in all copies and that

+both that copyright notice and this permission notice appear in

+supporting documentation, and that the name of IBM not be

+used in advertising or publicity pertaining to distribution of the

+software without specific, written prior permission.

+

+IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING

+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL

+IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR

+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,

+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS

+SOFTWARE.

+

+******************************************************************/

+

+/*

+ * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison

+ */

+

+/* should be config option but cpp breaks with too many #defines */

+#define	DECBIT

+

+/*

+ *	Return true if the mbuf is a cluster mbuf

+ */

+#define	IS_CLUSTER(m)	((m)->m_flags & M_EXT)

+

+/*

+ *	Move the halfword into the two characters

+ */

+#define	HTOC(msb, lsb, hword)\

+	(msb) = (u_char)((hword) >> 8);\

+	(lsb) = (u_char)((hword) & 0xff)

+/*

+ *	Move the two charcters into the halfword

+ */

+#define	CTOH(msb, lsb, hword)\

+	(hword) = ((msb) << 8) | (lsb)

+

+/*

+ *	Return true if the checksum has been set - ie. the checksum is

+ *	not zero

+ */

+#define	CKSUM_REQUIRED(clnp)\

+	(((clnp)->cnf_cksum_msb != 0) || ((clnp)->cnf_cksum_lsb != 0))

+

+/*

+ *	Fixed part of clnp header

+ */

+struct clnp_fixed {

+	u_char          cnf_proto_id;	/* network layer protocol identifier */

+	u_char          cnf_hdr_len;	/* length indicator (octets) */

+	u_char          cnf_vers;	/* version/protocol identifier

+					 * extension */

+	u_char          cnf_ttl;/* lifetime (500 milliseconds) */

+	u_char          cnf_type;	/* type code */

+	/* Includes err_ok, more_segs, and seg_ok */

+	u_char          cnf_seglen_msb;	/* pdu segment length (octets) high

+					 * byte */

+	u_char          cnf_seglen_lsb;	/* pdu segment length (octets) low

+					 * byte */

+	u_char          cnf_cksum_msb;	/* checksum high byte */

+	u_char          cnf_cksum_lsb;	/* checksum low byte */

+} __attribute__((packed));

+#define CNF_TYPE	0x1f

+#define CNF_ERR_OK	0x20

+#define CNF_MORE_SEGS	0x40

+#define CNF_SEG_OK	0x80

+

+#define CLNP_CKSUM_OFF	0x07	/* offset of checksum */

+

+#define	clnl_fixed	clnp_fixed

+

+/*

+ *	Segmentation part of clnp header

+ */

+struct clnp_segment {

+	u_short         cng_id;	/* data unit identifier */

+	u_short         cng_off;/* segment offset */

+	u_short         cng_tot_len;	/* total length */

+};

+

+/*

+ *	Clnp fragment reassembly structures:

+ *

+ *	All packets undergoing reassembly are linked together in

+ *	clnp_fragl structures. Each clnp_fragl structure contains a

+ *	pointer to the original clnp packet header, as well as a

+ *	list of packet fragments. Each packet fragment

+ *	is headed by a clnp_frag structure. This structure contains the

+ *	offset of the first and last byte of the fragment, as well as

+ *	a pointer to the data (an mbuf chain) of the fragment.

+ */

+

+/*

+ *	NOTE:

+ *		The clnp_frag structure is stored in an mbuf immedately

+ *		preceding the fragment data. Since there are words in

+ *		this struct, it must be word aligned.

+ *

+ *	NOTE:

+ *		All the fragment code assumes that the entire clnp header is

+ *		contained in the first mbuf.

+ */

+struct clnp_frag {

+	u_int           cfr_first;	/* offset of first byte of this frag */

+	u_int           cfr_last;	/* offset of last byte of this frag */

+	u_int           cfr_bytes;	/* bytes to shave to get to data */

+	struct mbuf    *cfr_data;	/* ptr to data for this frag */

+	struct clnp_frag *cfr_next;	/* next fragment in list */

+};

+

+struct clnp_fragl {

+	struct iso_addr cfl_src;/* source of the pkt */

+	struct iso_addr cfl_dst;/* destination of the pkt */

+	u_short         cfl_id;	/* id of the pkt */

+	u_char          cfl_ttl;/* current ttl of pkt */

+	u_short         cfl_last;	/* offset of last byte of packet */

+	struct mbuf    *cfl_orighdr;	/* ptr to original header */

+	struct clnp_frag *cfl_frags;	/* linked list of fragments for pkt */

+	struct clnp_fragl *cfl_next;	/* next pkt being reassembled */

+};

+

+/*

+ *	The following structure is used to index into an options section

+ *	of a clnp datagram. These values can be used without worry that

+ *	offset or length fields are invalid or too big, etc. That is,

+ *	the consistancy of the options will be guaranteed before this

+ *	structure is filled in. Any pointer (field ending in p) is

+ *	actually the offset from the beginning of the mbuf the option

+ *	is contained in.  A value of NULL for any pointer

+ *	means that the option is not present. The length any option

+ *	does not include the option code or option length fields.

+ */

+struct clnp_optidx {

+	u_short         cni_securep;	/* ptr to start of security option */

+	char            cni_secure_len;	/* length of entire security option */

+

+	u_short         cni_srcrt_s;	/* offset of start of src rt option */

+	u_short         cni_srcrt_len;	/* length of entire src rt option */

+

+	u_short         cni_recrtp;	/* ptr to beginning of recrt option */

+	char            cni_recrt_len;	/* length of entire recrt option */

+

+	char            cni_priorp;	/* ptr to priority option */

+

+	u_short         cni_qos_formatp;	/* ptr to format of qos

+						 * option */

+	char            cni_qos_len;	/* length of entire qos option */

+

+	u_char          cni_er_reason;	/* reason from ER pdu option */

+

+	/* ESIS options */

+

+	u_short         cni_esct;	/* value from ISH ESCT option */

+

+	u_short         cni_netmaskp;	/* ptr to beginning of netmask option */

+	char            cni_netmask_len;	/* length of entire netmask

+						 * option */

+

+	u_short         cni_snpamaskp;	/* ptr to start of snpamask option */

+	char            cni_snpamask_len;	/* length of entire snpamask

+						 * option */

+

+};

+

+#define	ER_INVALREAS	0xff	/* code for invalid ER pdu discard reason */

+

+/* given an mbuf and addr of option, return offset from data of mbuf */

+#define CLNP_OPTTOOFF(m, opt) ((u_short) (opt - mtod(m, caddr_t)))

+

+/* given an mbuf and offset of option, return address of option */

+#define CLNP_OFFTOOPT(m, off) ((caddr_t) (mtod(m, caddr_t) + off))

+

+/* return true iff src route is valid */

+#define	CLNPSRCRT_VALID(oidx) ((oidx) && (oidx->cni_srcrt_s))

+

+/* return the offset field of the src rt */

+#define CLNPSRCRT_OFF(oidx, options)\

+	(*((u_char *)(CLNP_OFFTOOPT(options, oidx->cni_srcrt_s) + 1)))

+

+/* return the type field of the src rt */

+#define CLNPSRCRT_TYPE(oidx, options)\

+	((u_char)(*(CLNP_OFFTOOPT(options, oidx->cni_srcrt_s))))

+

+/* return the length of the current address */

+#define CLNPSRCRT_CLEN(oidx, options)\

+	((u_char)(*(CLNP_OFFTOOPT(options, oidx->cni_srcrt_s) + CLNPSRCRT_OFF(oidx, options) - 1)))

+

+/* return the address of the current address */

+#define CLNPSRCRT_CADDR(oidx, options)\

+	((caddr_t)(CLNP_OFFTOOPT(options, oidx->cni_srcrt_s) + CLNPSRCRT_OFF(oidx, options)))

+

+/*

+ * return true if the src route has run out of routes this is true if the

+ * offset of next route is greater than the end of the rt

+ */

+#define	CLNPSRCRT_TERM(oidx, options)\

+	(CLNPSRCRT_OFF(oidx, options) > oidx->cni_srcrt_len)

+

+/*

+ *	Options a user can set/get

+ */

+#define	CLNPOPT_FLAGS	0x01	/* flags: seg permitted, no er xmit, etc  */

+#define	CLNPOPT_OPTS	0x02	/* datagram options */

+

+/*

+ *	Values for particular datagram options

+ */

+#define	CLNPOVAL_PAD		0xcc	/* padding */

+#define	CLNPOVAL_SECURE		0xc5	/* security */

+#define	CLNPOVAL_SRCRT		0xc8	/* source routing */

+#define	CLNPOVAL_RECRT		0xcb	/* record route */

+#define	CLNPOVAL_QOS		0xc3	/* quality of service */

+#define	CLNPOVAL_PRIOR		0xcd	/* priority */

+#define CLNPOVAL_ERREAS		0xc1	/* ER PDU ONLY: reason for discard */

+

+#define	CLNPOVAL_SRCSPEC	0x40	/* source address specific */

+#define	CLNPOVAL_DSTSPEC	0x80	/* destination address specific */

+#define	CLNPOVAL_GLOBAL		0xc0	/* globally unique */

+

+/* Globally Unique QOS */

+#define	CLNPOVAL_SEQUENCING	0x10	/* sequencing preferred */

+#define CLNPOVAL_CONGESTED	0x08	/* congestion experienced */

+#define CLNPOVAL_LOWDELAY	0x04	/* low transit delay */

+

+#define	CLNPOVAL_PARTRT		0x00	/* partial source routing */

+#define CLNPOVAL_COMPRT		0x01	/* complete source routing */

+

+/*

+ *	Clnp flags used in a control block flags field.

+ *	NOTE: these must be out of the range of bits defined in ../net/raw_cb.h

+ */

+#define	CLNP_NO_SEG		0x010	/* segmentation not permitted */

+#define	CLNP_NO_ER		0x020	/* do not generate ERs */

+#define CLNP_SEND_RAW		0x080	/* send pkt as RAW DT not TP DT */

+#define	CLNP_NO_CKSUM		0x100	/* don't use clnp checksum */

+#define CLNP_ECHO		0x200	/* send echo request */

+#define	CLNP_NOCACHE		0x400	/* don't store cache information */

+#define CLNP_ECHOR		0x800	/* send echo reply */

+

+/* valid clnp flags */

+#define CLNP_VFLAGS \

+	(CLNP_SEND_RAW|CLNP_NO_SEG|CLNP_NO_ER|CLNP_NO_CKSUM|\

+	 CLNP_ECHO|CLNP_NOCACHE|CLNP_ECHOR)

+

+/*

+ * Constants used by clnp

+ */

+#define	CLNP_HDR_MIN	(sizeof (struct clnp_fixed))

+#define	CLNP_HDR_MAX	(254)

+#define	CLNP_TTL_UNITS	2	/* 500 milliseconds */

+#define CLNP_TTL	15*CLNP_TTL_UNITS	/* time to live (seconds) */

+#define	ISO8473_V1	0x01

+

+/*

+ *	Clnp packet types

+ *	In order to test raw clnp and tp/clnp simultaneously, a third type of

+ *	packet has been defined: CLNP_RAW. This is done so that the input

+ *	routine can switch to the correct input routine (rclnp_input or

+ *	tpclnp_input) based on the type field. If clnp had a higher level

+ *	protocol field, this would not be necessary.

+ */

+#define	CLNP_DT			0x1C	/* normal data */

+#define	CLNP_ER			0x01	/* error report */

+#define	CLNP_RAW		0x1D	/* debug only */

+#define CLNP_EC			0x1E	/* echo packet */

+#define CLNP_ECR		0x1F	/* echo reply */

+

+/*

+ *	ER pdu error codes

+ */

+#define GEN_NOREAS		0x00	/* reason not specified */

+#define GEN_PROTOERR		0x01	/* protocol procedure error */

+#define GEN_BADCSUM		0x02	/* incorrect checksum */

+#define GEN_CONGEST		0x03	/* pdu discarded due to congestion */

+#define GEN_HDRSYNTAX		0x04	/* header syntax error */

+#define GEN_SEGNEEDED		0x05	/* need segmentation but not allowed */

+#define GEN_INCOMPLETE		0x06	/* incomplete pdu received */

+#define GEN_DUPOPT		0x07	/* duplicate option */

+

+/* address errors */

+#define ADDR_DESTUNREACH	0x80	/* destination address unreachable */

+#define ADDR_DESTUNKNOWN	0x81	/* destination address unknown */

+

+/* source routing */

+#define SRCRT_UNSPECERR		0x90	/* unspecified src rt error */

+#define SRCRT_SYNTAX		0x91	/* syntax error in src rt field */

+#define SRCRT_UNKNOWNADDR	0x92	/* unknown addr in src rt field */

+#define SRCRT_BADPATH		0x93	/* path not acceptable */

+

+/* lifetime */

+#define TTL_EXPTRANSIT		0xa0	/* lifetime expired during transit */

+#define TTL_EXPREASS		0xa1	/* lifetime expired during reassembly */

+

+/* pdu discarded */

+#define DISC_UNSUPPOPT		0xb0	/* unsupported option not specified? */

+#define DISC_UNSUPPVERS		0xb1	/* unsupported protocol version */

+#define DISC_UNSUPPSECURE	0xb2	/* unsupported security option */

+#define DISC_UNSUPPSRCRT	0xb3	/* unsupported src rt option */

+#define DISC_UNSUPPRECRT	0xb4	/* unsupported rec rt option */

+

+/* reassembly */

+#define REASS_INTERFERE		0xc0	/* reassembly interference */

+#define CLNP_ERRORS		22

+

+

+#ifdef CLNP_ER_CODES

+u_char          clnp_er_codes[CLNP_ERRORS] = {

+	GEN_NOREAS, GEN_PROTOERR, GEN_BADCSUM, GEN_CONGEST,

+	GEN_HDRSYNTAX, GEN_SEGNEEDED, GEN_INCOMPLETE, GEN_DUPOPT,

+	ADDR_DESTUNREACH, ADDR_DESTUNKNOWN,

+	SRCRT_UNSPECERR, SRCRT_SYNTAX, SRCRT_UNKNOWNADDR, SRCRT_BADPATH,

+	TTL_EXPTRANSIT, TTL_EXPREASS,

+	DISC_UNSUPPOPT, DISC_UNSUPPVERS, DISC_UNSUPPSECURE,

+	DISC_UNSUPPSRCRT, DISC_UNSUPPRECRT, REASS_INTERFERE

+};

+#endif

+

+#ifdef	TROLL

+

+#define	TR_DUPEND		0x01	/* duplicate end of fragment */

+#define TR_DUPPKT		0x02	/* duplicate entire packet */

+#define	TR_DROPPKT		0x04	/* drop packet on output */

+#define TR_TRIM			0x08	/* trim bytes from packet */

+#define TR_CHANGE		0x10	/* change bytes in packet */

+#define TR_MTU			0x20	/* delta to change device mtu */

+#define	TR_CHUCK		0x40	/* drop packet in rclnp_input */

+#define	TR_BLAST		0x80	/* force rclnp_output to blast many

+					 * packet */

+#define	TR_RAWLOOP		0x100	/* make if_loop call clnpintr

+					 * directly */

+struct troll {

+	int             tr_ops;	/* operations to perform */

+	float           tr_dup_size;	/* % to duplicate */

+	float           tr_dup_freq;	/* frequency to duplicate packets */

+	float           tr_drop_freq;	/* frequence to drop packets */

+	int             tr_mtu_adj;	/* delta to adjust if mtu */

+	int             tr_blast_cnt;	/* # of pkts to blast out */

+};

+

+#define	SN_OUTPUT(clcp, m)\

+	troll_output(clcp->clc_ifp, m, clcp->clc_firsthop, clcp->clc_rt)

+

+#define	SN_MTU(ifp, rt) (((rt && rt->rt_rmx.rmx_mtu) ?\

+	rt->rt_rmx.rmx_mtu : clnp_badmtu(ifp, rt, __LINE__, __FILE__))\

+		- trollctl.tr_mtu_adj)

+

+#ifdef _KERNEL

+extern float    troll_random;

+#endif

+

+#else				/* NO TROLL */

+

+#define	SN_OUTPUT(clcp, m)\

+	(*clcp->clc_ifp->if_output)(clcp->clc_ifp, m, clcp->clc_firsthop, \

+				    clcp->clc_rt)

+

+#define	SN_MTU(ifp, rt) (((rt && rt->rt_rmx.rmx_mtu) ?\

+	rt->rt_rmx.rmx_mtu : clnp_badmtu(ifp, rt, __LINE__, __FILE__)))

+

+#endif				/* TROLL */

+

+/*

+ *	Macro to remove an address from a clnp header

+ */

+#define CLNP_EXTRACT_ADDR(isoa, hoff, hend)\

+	{\

+		isoa.isoa_len = (u_char)*hoff;\

+		if ((((++hoff) + isoa.isoa_len) > hend) ||\

+			(isoa.isoa_len > 20) || (isoa.isoa_len == 0)) {\

+			hoff = (caddr_t)0;\

+		} else {\

+			(void) bcopy(hoff, (caddr_t)isoa.isoa_genaddr, \

+				     isoa.isoa_len);\

+			hoff += isoa.isoa_len;\

+		}\

+	}

+

+/*

+ *	Macro to insert an address into a clnp header

+ */

+#define CLNP_INSERT_ADDR(hoff, isoa)\

+	*hoff++ = (isoa).isoa_len;\

+	(void) bcopy((caddr_t)((isoa).isoa_genaddr), hoff, (isoa).isoa_len);\

+	hoff += (isoa).isoa_len;

+

+/*

+ *	Clnp hdr cache.	Whenever a clnp packet is sent, a copy of the

+ *	header is made and kept in this cache. In addition to a copy of

+ *	the cached clnp hdr, the cache contains

+ *	information necessary to determine whether the new packet

+ *	to send requires a new header to be built.

+ */

+struct clnp_cache {

+	/* these fields are used to check the validity of the cache */

+	struct iso_addr clc_dst;/* destination of packet */

+	struct mbuf    *clc_options;	/* ptr to options mbuf */

+	int             clc_flags;	/* flags passed to clnp_output */

+

+	/* these fields are state that clnp_output requires to finish the pkt */

+	int             clc_segoff;	/* offset of seg part of header */

+	struct rtentry *clc_rt;	/* ptr to rtentry (points into the route

+				 * structure) */

+	struct sockaddr *clc_firsthop;	/* first hop of packet */

+	struct ifnet   *clc_ifp;/* ptr to interface structure */

+	struct iso_ifaddr

+	               *clc_ifa;/* ptr to interface address */

+	struct mbuf    *clc_hdr;/* cached pkt hdr (finally)! */

+};

+

+#ifdef	_KERNEL

+struct iso_addr;

+struct sockaddr_iso;

+struct mbuf;

+struct clnp_segment;

+struct sockaddr;

+struct rt_entry;

+struct clnp_fragl;

+struct clnp_optidx;

+struct isopcb;

+struct snpa_hdr;

+struct iso_ifaddr;

+struct route_iso;

+

+/* clnp_debug.c */

+char *clnp_hexp __P((char *, int, char *));

+char *clnp_iso_addrp __P((struct iso_addr *));

+char *clnp_saddr_isop __P((struct sockaddr_iso *));

+

+/* clnp_er.c */

+void clnp_er_input __P((struct mbuf *, struct iso_addr *, u_int));

+void clnp_discard __P((struct mbuf *, u_int));

+void clnp_emit_er __P((struct mbuf *, u_int));

+int clnp_er_index __P((u_int));

+

+int clnp_fragment __P((struct ifnet *, struct mbuf *, struct sockaddr *,

+		       int, int, int, struct rtentry *));

+struct mbuf *clnp_reass __P((struct mbuf *, struct iso_addr *,

+			     struct iso_addr *, struct clnp_segment *));

+int clnp_newpkt __P((struct mbuf *, struct iso_addr *, struct iso_addr *,

+		     struct clnp_segment *));

+void clnp_insert_frag __P((struct clnp_fragl *, struct mbuf *,

+			   struct clnp_segment *));

+struct mbuf    *clnp_comp_pdu __P((struct clnp_fragl *));

+#ifdef TROLL

+float troll_random __P((void));

+int troll_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,

+		      struct rtentry *));

+#endif

+

+/* clnp_input.c */

+void clnp_init  __P((void));

+void clnlintr    __P((void));

+void clnp_input __P((struct mbuf *, ...));

+

+/* clnp_options.c */

+void clnp_update_srcrt __P((struct mbuf *, struct clnp_optidx *));

+void clnp_dooptions __P((struct mbuf *, struct clnp_optidx *, struct ifnet *,

+			 struct iso_addr *));

+int clnp_set_opts __P((struct mbuf **, struct mbuf **));

+int clnp_opt_sanity __P((struct mbuf *, caddr_t, int, struct clnp_optidx *));

+

+/* clnp_output.c */

+int clnp_output __P((struct mbuf *, ...));

+void clnp_ctloutput __P((void));

+

+/* clnp_raw.c */

+void rclnp_input __P((struct mbuf *, ...));

+int rclnp_output __P((struct mbuf *, ...));

+int rclnp_ctloutput __P((int, struct socket *, int, int, struct mbuf **));

+int clnp_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *,

+		     struct mbuf *, struct proc *));

+

+/* clnp_subr.c */

+struct mbuf    *clnp_data_ck __P((struct mbuf *, int));

+caddr_t clnp_extract_addr __P((caddr_t, int, struct iso_addr *,

+			       struct iso_addr *));

+int clnp_ours   __P((struct iso_addr *));

+void clnp_forward __P((struct mbuf *, int, struct iso_addr *,

+		       struct clnp_optidx *, int, struct snpa_hdr *));

+caddr_t clnp_insert_addr __P((caddr_t, struct iso_addr *, struct iso_addr *));

+int clnp_route  __P((struct iso_addr *, struct route_iso *, int,

+		     struct sockaddr **, struct iso_ifaddr **));

+int clnp_srcroute __P((struct mbuf *, struct clnp_optidx *, struct route_iso *,

+		       struct sockaddr **, struct iso_ifaddr **,

+		       struct iso_addr *));

+int clnp_echoreply __P((struct mbuf *, int, struct sockaddr_iso *,

+		        struct sockaddr_iso *, struct clnp_optidx *));

+int clnp_badmtu __P((struct ifnet *, struct rtentry *, int, char *));

+void clnp_ypocb  __P((caddr_t, caddr_t, u_int));

+

+/* clnp_timer.c */

+struct clnp_fragl *clnp_freefrags __P((struct clnp_fragl *));

+void clnp_slowtimo __P((void));

+void clnp_drain __P((void));

+

+#ifdef	TROLL

+struct troll    trollctl;

+#endif /* TROLL */

+

+#endif /* _KERNEL */

diff --git a/isisd/include-netbsd/esis.h b/isisd/include-netbsd/esis.h
new file mode 100644
index 0000000..ded864e
--- /dev/null
+++ b/isisd/include-netbsd/esis.h
@@ -0,0 +1,146 @@
+/*	$NetBSD: esis.h,v 1.11 1997/11/03 15:01:19 is Exp $	*/

+

+/*-

+ * Copyright (c) 1991, 1993

+ *	The Regents of the University of California.  All rights reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions

+ * are met:

+ * 1. Redistributions of source code must retain the above copyright

+ *    notice, this list of conditions and the following disclaimer.

+ * 2. Redistributions in binary form must reproduce the above copyright

+ *    notice, this list of conditions and the following disclaimer in the

+ *    documentation and/or other materials provided with the distribution.

+ * 3. All advertising materials mentioning features or use of this software

+ *    must display the following acknowledgement:

+ *	This product includes software developed by the University of

+ *	California, Berkeley and its contributors.

+ * 4. Neither the name of the University nor the names of its contributors

+ *    may be used to endorse or promote products derived from this software

+ *    without specific prior written permission.

+ *

+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND

+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE

+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

+ * SUCH DAMAGE.

+ *

+ *	@(#)esis.h	8.1 (Berkeley) 6/10/93

+ */

+

+/***********************************************************

+		Copyright IBM Corporation 1987

+

+                      All Rights Reserved

+

+Permission to use, copy, modify, and distribute this software and its

+documentation for any purpose and without fee is hereby granted,

+provided that the above copyright notice appear in all copies and that

+both that copyright notice and this permission notice appear in

+supporting documentation, and that the name of IBM not be

+used in advertising or publicity pertaining to distribution of the

+software without specific, written prior permission.

+

+IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING

+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL

+IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR

+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,

+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS

+SOFTWARE.

+

+******************************************************************/

+

+/*

+ * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison

+ */

+

+#include <machine/endian.h>

+

+#define	SNPAC_AGE		60	/* seconds */

+#define	ESIS_CONFIG		60	/* seconds */

+#define	ESIS_HT			(ESIS_CONFIG * 2)

+

+/*

+ *	Fixed part of an ESIS header

+ */

+struct esis_fixed {

+	u_char          esis_proto_id;	/* network layer protocol identifier */

+	u_char          esis_hdr_len;	/* length indicator (octets) */

+	u_char          esis_vers;	/* version/protocol identifier

+					 * extension */

+	u_char          esis_res1;	/* reserved */

+	u_char          esis_type;	/* type code */

+	/* technically, type should be &='d 0x1f */

+#define ESIS_ESH	0x02	/* End System Hello */

+#define ESIS_ISH	0x04	/* Intermediate System Hello */

+#define ESIS_RD		0x06	/* Redirect */

+	u_char          esis_ht_msb;	/* holding time (seconds) high byte */

+	u_char          esis_ht_lsb;	/* holding time (seconds) low byte */

+	u_char          esis_cksum_msb;	/* checksum high byte */

+	u_char          esis_cksum_lsb;	/* checksum low byte */

+} __attribute__((packed));

+/*

+ * Values for ESIS datagram options

+ */

+#define ESISOVAL_NETMASK	0xe1	/* address mask option, RD PDU only */

+#define ESISOVAL_SNPAMASK	0xe2	/* snpa mask option, RD PDU only */

+#define ESISOVAL_ESCT		0xc6	/* end system conf. timer, ISH PDU

+					 * only */

+

+

+#define	ESIS_CKSUM_OFF		0x07

+#define ESIS_CKSUM_REQUIRED(pdu)\

+	((pdu->esis_cksum_msb != 0) || (pdu->esis_cksum_lsb != 0))

+

+#define	ESIS_VERSION	1

+

+struct esis_stat {

+	u_short         es_nomem;	/* insufficient memory to send hello */

+	u_short         es_badcsum;	/* incorrect checksum */

+	u_short         es_badvers;	/* incorrect version number */

+	u_short         es_badtype;	/* unknown pdu type field */

+	u_short         es_toosmall;	/* packet too small */

+	u_short         es_eshsent;	/* ESH sent */

+	u_short         es_eshrcvd;	/* ESH rcvd */

+	u_short         es_ishsent;	/* ISH sent */

+	u_short         es_ishrcvd;	/* ISH rcvd */

+	u_short         es_rdsent;	/* RD sent */

+	u_short         es_rdrcvd;	/* RD rcvd */

+};

+

+#ifdef	_KERNEL

+struct esis_stat esis_stat;

+struct socket;

+struct mbuf;

+struct snpa_hdr;

+struct clnp_optidx;

+struct iso_addr;

+struct rtentry;

+struct sockaddr_dl;

+

+void esis_init __P((void));

+int esis_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *,

+		     struct mbuf *, struct proc *));

+void esis_input __P((struct mbuf *, ...));

+void esis_rdoutput __P((struct snpa_hdr *, struct mbuf *, struct clnp_optidx *,

+			struct iso_addr *, struct rtentry *));

+int esis_insert_addr __P((caddr_t *, int *, struct iso_addr *, struct mbuf *,

+			  int));

+void esis_eshinput __P((struct mbuf *, struct snpa_hdr *));

+void esis_ishinput __P((struct mbuf *, struct snpa_hdr *));

+void esis_rdinput __P((struct mbuf *, struct snpa_hdr *));

+void esis_config __P((void *));

+void esis_shoutput __P((struct ifnet *, int, int, caddr_t, int,

+	               struct iso_addr *));

+void isis_input __P((struct mbuf *, ...));

+int isis_output __P((struct mbuf *, ...));

+void *esis_ctlinput __P((int, struct sockaddr *, void *));

+#endif /* _KERNEL */

diff --git a/isisd/include-netbsd/iso.h b/isisd/include-netbsd/iso.h
new file mode 100644
index 0000000..714b42d
--- /dev/null
+++ b/isisd/include-netbsd/iso.h
@@ -0,0 +1,208 @@
+/*	$NetBSD: iso.h,v 1.13 2000/07/28 12:13:34 kleink Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)iso.h	8.1 (Berkeley) 6/10/93
+ */
+
+/***********************************************************
+		Copyright IBM Corporation 1987
+
+                      All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of IBM not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
+ */
+
+#ifndef _NETISO_ISO_H_
+#define _NETISO_ISO_H_
+
+#if 0
+#include <sys/ansi.h>
+#endif
+
+#if 0
+#ifndef sa_family_t
+typedef __sa_family_t	sa_family_t;
+#define sa_family_t	__sa_family_t
+#endif
+#endif
+/*
+ *	Return true if this is a multicast address
+ *	This assumes that the bit transmission is lsb first. This
+ *	assumption is valid for 802.3 but not 802.5. There is a
+ *	kludge to get around this for 802.5 -- see if_lan.c
+ *	where subnetwork header is setup.
+ */
+#define	IS_MULTICAST(snpa)\
+	((snpa)[0] & 0x01)
+
+/*
+ * Protocols
+ */
+#define	ISOPROTO_TCP	6	/* IETF experiment */
+#define	ISOPROTO_UDP	17	/* IETF experiment */
+#define	ISOPROTO_TP0	25	/* connection oriented transport protocol */
+#define	ISOPROTO_TP1	26	/* not implemented */
+#define	ISOPROTO_TP2	27	/* not implemented */
+#define	ISOPROTO_TP3	28	/* not implemented */
+#define	ISOPROTO_TP4	29	/* connection oriented transport protocol */
+#define	ISOPROTO_TP		ISOPROTO_TP4	/* tp-4 with negotiation */
+#define	ISOPROTO_CLTP	30	/* connectionless transport (not yet impl.) */
+#define	ISOPROTO_CLNP	31	/* connectionless internetworking protocol */
+#define	ISOPROTO_X25	32	/* cons */
+#define	ISOPROTO_INACT_NL	33	/* inactive network layer! */
+#define	ISOPROTO_ESIS	34	/* ES-IS protocol */
+#define	ISOPROTO_INTRAISIS	35	/* IS-IS protocol */
+#define	ISOPROTO_IDRP	36	/* Interdomain Routing Protocol */
+
+#define	ISOPROTO_RAW	255	/* raw clnp */
+#define	ISOPROTO_MAX	256
+
+#define	ISO_PORT_RESERVED		1024
+#define	ISO_PORT_USERRESERVED	5000
+/*
+ * Port/socket numbers: standard network functions
+ * NOT PRESENTLY USED
+ */
+#define	ISO_PORT_MAINT		501
+#define	ISO_PORT_ECHO		507
+#define	ISO_PORT_DISCARD	509
+#define	ISO_PORT_SYSTAT		511
+#define	ISO_PORT_NETSTAT	515
+/*
+ * Port/socket numbers: non-standard application functions
+ */
+#define ISO_PORT_LOGIN		513
+/*
+ * Port/socket numbers: public use
+ */
+#define ISO_PORT_PUBLIC		1024	/* high bit set --> public */
+
+/*
+ *	Network layer protocol identifiers
+ */
+#define ISO8473_CLNP	0x81
+#define	ISO9542_ESIS	0x82
+#define ISO9542X25_ESIS	0x8a
+#define ISO10589_ISIS	0x83
+#define ISO8878A_CONS	0x84
+#define ISO10747_IDRP	0x85
+
+
+#ifndef IN_CLASSA_NET
+#include <netinet/in.h>
+#endif				/* IN_CLASSA_NET */
+
+
+
+/*
+ * The following looks like a sockaddr to facilitate using tree lookup
+ * routines
+ */
+struct iso_addr {
+	u_char          isoa_len;	/* length (in bytes) */
+	char            isoa_genaddr[20];	/* general opaque address */
+};
+
+struct sockaddr_iso {
+	u_char          siso_len;	/* length */
+	sa_family_t     siso_family;	/* family */
+	u_char          siso_plen;	/* presentation selector length */
+	u_char          siso_slen;	/* session selector length */
+	u_char          siso_tlen;	/* transport selector length */
+	struct iso_addr siso_addr;	/* network address */
+	u_char          siso_pad[6];	/* space for gosip v2 sels */
+	/* makes struct 32 bytes long */
+};
+#define siso_nlen siso_addr.isoa_len
+#define siso_data siso_addr.isoa_genaddr
+
+#define TSEL(s) ((caddr_t)((s)->siso_data + (s)->siso_nlen))
+
+#define SAME_ISOADDR(a, b) \
+	(bcmp((a)->siso_data, (b)->siso_data, (unsigned)(a)->siso_nlen)==0)
+#define SAME_ISOIFADDR(a, b) (bcmp((a)->siso_data, (b)->siso_data, \
+	(unsigned)((b)->siso_nlen - (b)->siso_tlen)) == 0)
+/*
+ * The following are specific values for siso->siso_data[0],
+ * otherwise known as the AFI:
+ */
+#define	AFI_37		0x37	/* bcd of "37" */
+#define AFI_OSINET	0x47	/* bcd of "47" */
+#define AFI_RFC986	0x47	/* bcd of "47" */
+#define	AFI_SNA		0x00	/* SubNetwork Address; invalid really... */
+
+#ifdef _KERNEL
+
+extern struct domain isodomain;
+extern struct protosw isosw[];
+
+#define	satosiso(sa)	((struct sockaddr_iso *)(sa))
+#define	sisotosa(siso)	((struct sockaddr *)(siso))
+
+#else
+/* user utilities definitions from the iso library */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+struct iso_addr *iso_addr __P((const char *));
+char           *iso_ntoa __P((const struct iso_addr *));
+
+/* THESE DON'T EXIST YET */
+struct hostent *iso_gethostbyname __P((const char *));
+struct hostent *iso_gethostbyaddr __P((const char *, int, int));
+__END_DECLS
+
+#endif /* _KERNEL */
+
+#endif /* _NETISO_ISO_H_ */
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
new file mode 100644
index 0000000..8079bd1
--- /dev/null
+++ b/isisd/isis_adjacency.c
@@ -0,0 +1,508 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_adjacency.c   
+ *                             handling of IS-IS adjacencies
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+
+#include "log.h"
+#include "memory.h"
+#include "hash.h"
+#include "vty.h"
+#include "linklist.h"
+#include "thread.h"
+#include "if.h"
+#include "stream.h"
+
+#include "isisd/dict.h"
+#include "isisd/include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_dr.h"
+#include "isisd/isis_dynhn.h"
+#include "isisd/isis_pdu.h"
+
+
+extern struct isis *isis;
+
+
+struct isis_adjacency *
+adj_alloc (u_char *id)
+{
+    struct isis_adjacency *adj;
+
+    adj = XMALLOC (MTYPE_ISIS_ADJACENCY, sizeof (struct isis_adjacency));
+    memset (adj, 0, sizeof (struct isis_adjacency));
+    memcpy (adj->sysid, id, ISIS_SYS_ID_LEN);
+    
+    return adj;
+}
+
+struct isis_adjacency *
+isis_new_adj (u_char *id, u_char *snpa, int level, 
+	      struct isis_circuit *circuit)
+{
+
+  struct isis_adjacency *adj;
+  int i;  
+
+  adj = adj_alloc (id); /* P2P kludge */
+  
+  if (adj == NULL){
+    zlog_err ("Out of memory!");
+    return NULL;
+  }
+
+  memcpy (adj->snpa, snpa, 6);
+  adj->circuit = circuit;
+  adj->level = level;
+  adj->flaps = 0;
+  adj->last_flap = time (NULL);
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    listnode_add (circuit->u.bc.adjdb[level-1], adj);
+    adj->dischanges[level - 1] = 0;
+    for (i = 0; i < DIS_RECORDS; i++) /* clear N DIS state change records */
+	{
+	  adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis 
+	    = ISIS_UNKNOWN_DIS;
+	  adj->dis_record[(i * ISIS_LEVELS) + level - 1].last_dis_change 
+            = time (NULL);
+	}
+  }
+
+  return adj;
+}
+
+struct isis_adjacency *
+isis_adj_lookup (u_char *sysid,  struct list *adjdb)
+{
+  struct isis_adjacency *adj;
+  struct listnode *node;
+
+  for (node = listhead (adjdb); node; nextnode (node)) {
+    adj = getdata (node);
+    if (memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0)
+      return adj;
+  }
+  
+  return NULL;
+}
+
+
+struct isis_adjacency *
+isis_adj_lookup_snpa (u_char *ssnpa, struct list *adjdb)
+{
+  struct listnode *node;
+  struct isis_adjacency *adj;
+
+  for (node = listhead (adjdb); node; nextnode (node)) {
+    adj = getdata (node);
+    if (memcmp (adj->snpa, ssnpa, ETH_ALEN) == 0)
+      return adj;
+  }
+  
+  return NULL;
+}
+
+/*
+ * When we recieve a NULL list, we will know its p2p
+ */
+void 
+isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb)
+{
+  struct isis_adjacency *adj2;
+  struct listnode *node;
+  
+  if (adjdb) {
+    for (node = listhead (adjdb); node; nextnode (node)) {
+      adj2 = getdata (node);
+      if (adj2 == adj)
+        break;
+    }
+    listnode_delete (adjdb, node);
+  }
+  
+  if (adj->ipv4_addrs)
+    list_delete (adj->ipv4_addrs);
+#ifdef HAVE_IPV6
+  if (adj->ipv6_addrs)
+    list_delete (adj->ipv6_addrs);
+#endif
+  if (adj) {
+    XFREE (MTYPE_ISIS_ADJACENCY,adj);
+  } else {
+    zlog_info ("tried to delete a non-existent adjacency");
+  }
+  
+  
+
+  return;
+}
+
+void 
+isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state, 
+                       char *reason)
+
+{
+  int old_state;
+  int level = adj->level;
+  struct isis_circuit *circuit;
+  
+  old_state = adj->adj_state;
+  adj->adj_state = state;
+
+  circuit = adj->circuit;
+  
+  if (isis->debugs & DEBUG_ADJ_PACKETS) {
+    zlog_info ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
+               circuit->area->area_tag,
+               old_state,
+               state, 
+               reason ? reason : "unspecified");
+  }
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    if (state == ISIS_ADJ_UP)
+      circuit->upadjcount[level-1]++;
+    if (state == ISIS_ADJ_DOWN) {
+      isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]);
+      circuit->upadjcount[level-1]--;
+    }
+
+    list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
+    isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
+                               circuit->u.bc.lan_neighs[level - 1]);
+  } else if (state == ISIS_ADJ_UP) { /* p2p interface */
+    if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
+      send_hello (circuit, 1);
+    
+    /* update counter & timers for debugging purposes */
+    adj->last_flap = time(NULL);
+    adj->flaps++;
+
+    /* 7.3.17 - going up on P2P -> send CSNP */
+    /* FIXME: yup, I know its wrong... but i will do it! (for now) */
+    send_csnp (circuit,1);
+    send_csnp (circuit,2);
+  } else if (state == ISIS_ADJ_DOWN) { /* p2p interface */
+    adj->circuit->u.p2p.neighbor = NULL;
+    isis_delete_adj (adj, NULL);
+  }
+  return;
+}
+
+
+void
+isis_adj_print (struct isis_adjacency *adj)
+{
+  struct isis_dynhn *dyn;
+  struct listnode *node;
+  struct in_addr *ipv4_addr;
+#ifdef HAVE_IPV6 
+  struct in6_addr *ipv6_addr;
+  u_char ip6 [INET6_ADDRSTRLEN];
+#endif /* HAVE_IPV6 */
+  
+  if(!adj)
+    return;
+  dyn = dynhn_find_by_id (adj->sysid);
+  if (dyn)
+    zlog_info ("%s", dyn->name.name);
+  
+  zlog_info ("SystemId %20s SNPA %s, level %d\nHolding Time %d",
+             adj->sysid ? sysid_print (adj->sysid) : "unknown" , 
+             snpa_print (adj->snpa),
+             adj->level, adj->hold_time);
+  if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) {
+    zlog_info ("IPv4 Addresses:");
+    
+    for (node = listhead (adj->ipv4_addrs); node; nextnode (node)) {
+      ipv4_addr = getdata (node);
+      zlog_info ("%s", inet_ntoa(*ipv4_addr));
+    }
+  }
+
+#ifdef HAVE_IPV6  
+  if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) {
+    zlog_info ("IPv6 Addresses:");
+    for (node = listhead (adj->ipv6_addrs); node; nextnode (node)) {
+      ipv6_addr = getdata (node);
+      inet_ntop (AF_INET6, ipv6_addr, ip6, INET6_ADDRSTRLEN); 
+      zlog_info ("%s", ip6);
+    }
+  }
+#endif /* HAVE_IPV6 */
+  zlog_info ("Speaks: %s", nlpid2string(&adj->nlpids));
+  
+
+  return;
+}
+
+int 
+isis_adj_expire (struct thread *thread)
+{
+  struct isis_adjacency *adj;
+  int level;
+
+  /*
+   * Get the adjacency
+   */
+  adj = THREAD_ARG (thread);
+  assert (adj);
+  level = adj->level;
+
+  /* trigger the adj expire event */
+  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "holding time expired");
+
+  return 0;
+}
+
+const char *
+adj_state2string (int state)
+{
+  
+  switch (state) {
+  case ISIS_ADJ_INITIALIZING:
+    return "Initializing";
+  case ISIS_ADJ_UP:
+    return "Up";
+  case ISIS_ADJ_DOWN:
+    return "Down";
+  default:
+    return "Unknown";
+  }
+  
+  return NULL; /* not reached */
+}
+
+/*
+ * show clns/isis neighbor (detail)
+ */
+void
+isis_adj_print_vty2 (struct isis_adjacency *adj, struct vty *vty, char detail)
+{
+
+#ifdef HAVE_IPV6
+  struct in6_addr *ipv6_addr;
+  u_char ip6 [INET6_ADDRSTRLEN];
+#endif /* HAVE_IPV6 */
+  struct in_addr *ip_addr;
+  time_t now;
+  struct isis_dynhn *dyn;
+  int level;
+  struct listnode *node;
+
+  dyn = dynhn_find_by_id (adj->sysid);
+  if (dyn)
+    vty_out (vty, "  %-20s", dyn->name.name);
+  else if (adj->sysid){
+    vty_out (vty, "  %-20s", sysid_print (adj->sysid));
+  } else {
+    vty_out (vty, "  unknown ");
+  }
+
+  if (detail == ISIS_UI_LEVEL_BRIEF) {
+    if (adj->circuit)
+      vty_out (vty, "%-12s",adj->circuit->interface->name); 
+    else
+      vty_out (vty, "NULL circuit!");
+    vty_out (vty, "%-3u", adj->level); /* level */
+    vty_out (vty, "%-13s", adj_state2string (adj->adj_state));
+    now = time (NULL);
+    vty_out (vty, "%-9lu", adj->last_upd + adj->hold_time - now);
+    vty_out (vty, "%-10s", snpa_print (adj->snpa)); 
+    vty_out (vty, "%s", VTY_NEWLINE);
+  }
+
+  if (detail == ISIS_UI_LEVEL_DETAIL) {
+    level = adj->level;
+    if (adj->circuit)
+      vty_out (vty, "%s    Interface: %s",
+               VTY_NEWLINE,
+               adj->circuit->interface->name); /* interface name */
+    else
+      vty_out (vty, "NULL circuit!%s", VTY_NEWLINE);
+    vty_out (vty, ", Level: %u", adj->level); /* level */
+    vty_out (vty, ", State: %s", adj_state2string (adj->adj_state));
+    now = time (NULL);
+    vty_out (vty, ", Expires in %s", 
+             time2string (adj->last_upd + adj->hold_time - now));
+    vty_out (vty, "%s    Adjacency flaps: %u",
+	     VTY_NEWLINE,
+	     adj->flaps);
+    vty_out (vty, ", Last: %s ago", time2string(now - adj->last_flap));
+    vty_out (vty, "%s    Circuit type: %s",
+	     VTY_NEWLINE,
+	     circuit_t2string(adj->circuit_t));
+    vty_out (vty, ", Speaks: %s", nlpid2string(&adj->nlpids));
+    vty_out (vty, "%s    SNPA: %s",
+	     VTY_NEWLINE,
+	     snpa_print (adj->snpa));   
+    dyn = dynhn_find_by_id (adj->lanid);
+    if (dyn)
+      vty_out (vty, ", LAN id: %s.%02x",
+	       dyn->name.name,
+	       adj->lanid[ISIS_SYS_ID_LEN]);
+    else 
+      vty_out (vty, ", LAN id: %s.%02x",
+	       sysid_print (adj->lanid),
+	       adj->lanid[ISIS_SYS_ID_LEN]);
+    
+    vty_out (vty, "%s    Priority: %u",
+	     VTY_NEWLINE,
+	     adj->prio[adj->level-1]);
+
+    vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago%s",
+	     isis_disflag2string(adj->dis_record[ISIS_LEVELS+level-1].dis),
+	     adj->dischanges[level-1],
+	     time2string (now - 
+                   (adj->dis_record[ISIS_LEVELS + level - 1].last_dis_change)),
+	     VTY_NEWLINE);    
+             	
+    if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) {
+      vty_out (vty, "    IPv4 Addresses:%s", VTY_NEWLINE);
+      for (node = listhead (adj->ipv4_addrs);node; nextnode (node)) {
+        ip_addr = getdata (node);
+        vty_out (vty, "      %s%s", inet_ntoa(*ip_addr), VTY_NEWLINE);
+      }
+    }
+#ifdef HAVE_IPV6  
+    if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) {
+      vty_out (vty, "    IPv6 Addresses:%s", VTY_NEWLINE);
+      for (node = listhead (adj->ipv6_addrs); node; nextnode (node)) {
+        ipv6_addr = getdata (node);
+        inet_ntop (AF_INET6, ipv6_addr, ip6, INET6_ADDRSTRLEN); 
+        vty_out (vty, "      %s%s", ip6, VTY_NEWLINE);
+      }
+    }
+#endif /* HAVE_IPV6 */
+    vty_out (vty, "%s", VTY_NEWLINE);
+  }
+  return;
+}
+
+void
+isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty) {
+  isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
+}
+
+void
+isis_adj_print_vty_detail (struct isis_adjacency *adj, struct vty *vty) {
+  isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
+}
+
+void
+isis_adj_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty) {
+  isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
+}
+
+void
+isis_adj_p2p_print_vty (struct isis_adjacency *adj, struct vty *vty)
+{
+  isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_BRIEF);
+}
+
+void 
+isis_adj_p2p_print_vty_detail (struct isis_adjacency *adj, struct vty *vty) 
+{
+  isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_DETAIL);
+}
+
+void 
+isis_adj_p2p_print_vty_extensive (struct isis_adjacency *adj, struct vty *vty)
+{
+  isis_adj_print_vty2 (adj, vty, ISIS_UI_LEVEL_EXTENSIVE);
+}
+
+void
+isis_adjdb_iterate (struct list *adjdb, void (*func)(struct isis_adjacency*, 
+                                                 void *), void *arg)
+{
+  struct listnode *node;
+  struct isis_adjacency *adj;
+  for (node = listhead (adjdb); node; nextnode (node)) {
+    adj = getdata (node);
+    (*func)(adj, arg);
+  }
+}
+
+void
+isis_adj_build_neigh_list (struct list *adjdb, struct list *list)
+
+{
+  struct isis_adjacency *adj;
+  struct listnode *node;
+  
+  
+  if (!list) {
+    zlog_warn ("isis_adj_build_neigh_list(): NULL list");
+    return;
+  }
+  
+  for (node = listhead (adjdb); node; nextnode (node)) {
+    adj = getdata (node);
+    if (!adj) {
+      zlog_warn ("isis_adj_build_neigh_list(): NULL adj");
+      return;
+    }
+  
+    if ((adj->adj_state == ISIS_ADJ_UP || 
+       adj->adj_state == ISIS_ADJ_INITIALIZING))
+      listnode_add (list, adj->snpa);
+  }
+  return;
+}
+
+void
+isis_adj_build_up_list (struct list *adjdb, struct list *list)
+{
+  struct isis_adjacency *adj;
+  struct listnode *node;
+
+  if (!list) {
+    zlog_warn ("isis_adj_build_up_list(): NULL list");
+    return;
+  }
+
+  for (node = listhead (adjdb); node; nextnode (node)) {
+    adj = getdata (node);
+    
+    if (!adj) {
+      zlog_warn ("isis_adj_build_up_list(): NULL adj");
+      return;
+    }
+
+    if (adj->adj_state == ISIS_ADJ_UP)
+      listnode_add (list, adj);
+  }
+  
+  return;
+}
+
diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h
new file mode 100644
index 0000000..5c0772c
--- /dev/null
+++ b/isisd/isis_adjacency.h
@@ -0,0 +1,126 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_adjacency.h   
+ *                             IS-IS adjacency handling
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_ADJACENCY_H
+#define _ZEBRA_ISIS_ADJACENCY_H
+
+enum isis_adj_usage
+{
+  ISIS_ADJ_NONE,
+  ISIS_ADJ_LEVEL1,
+  ISIS_ADJ_LEVEL2,
+  ISIS_ADJ_LEVEL1AND2
+};
+
+enum isis_system_type 
+{
+  ISIS_SYSTYPE_UNKNOWN,
+  ISIS_SYSTYPE_ES,
+  ISIS_SYSTYPE_IS,
+  ISIS_SYSTYPE_L1_IS,
+  ISIS_SYSTYPE_L2_IS
+};
+
+enum isis_adj_state 
+{
+  ISIS_ADJ_INITIALIZING,
+  ISIS_ADJ_UP,
+  ISIS_ADJ_DOWN
+};
+
+/*
+ * we use the following codes to give an indication _why_
+ * a specific adjacency is up or down
+ */
+enum isis_adj_updown_reason
+{
+  ISIS_ADJ_REASON_SEENSELF,
+  ISIS_ADJ_REASON_AREA_MISMATCH,
+  ISIS_ADJ_REASON_HOLDTIMER_EXPIRED,
+  ISIS_ADJ_REASON_AUTH_FAILED,
+  ISIS_ADJ_REASON_CHECKSUM_FAILED
+};
+
+#define DIS_RECORDS 8 /* keep the last 8 DIS state changes on record */
+
+struct isis_dis_record {
+  int                              dis; /* is our neighbor the DIS ? */          time_t               last_dis_change; /* timestamp for last dis change */
+};
+
+struct isis_adjacency{
+  u_char snpa[ETH_ALEN];           /* NeighbourSNPAAddress */ 
+  u_char sysid[ISIS_SYS_ID_LEN];   /* neighbourSystemIdentifier */
+  u_char lanid[ISIS_SYS_ID_LEN+1]; /* LAN id on bcast circuits */
+  int dischanges[ISIS_LEVELS];     /* how many DIS changes ?*/ 
+  /* an array of N levels for M records */
+  struct isis_dis_record  dis_record[DIS_RECORDS * ISIS_LEVELS]; 
+  enum isis_adj_state adj_state;  /* adjacencyState */
+  enum isis_adj_usage adj_usage;  /* adjacencyUsage */
+  struct list *area_addrs;        /* areaAdressesOfNeighbour */
+  struct nlpids nlpids;           /* protocols spoken ... */
+  struct list *ipv4_addrs;
+#ifdef HAVE_IPV6
+  struct list *ipv6_addrs;
+#endif /* HAVE_IPV6 */
+  u_char prio[ISIS_LEVELS];        /* priorityOfNeighbour for DIS*/
+  int circuit_t;                   /* from hello PDU hdr */
+  int level;                       /* level (1 or 2) */
+  enum  isis_system_type sys_type; /* neighbourSystemType */
+  u_int16_t hold_time;             /* entryRemainingTime */
+  u_int32_t last_upd;
+  u_int32_t last_flap;             /* last time the adj flapped */
+  int flaps;                       /* number of adjacency flaps  */
+  struct thread *t_expire;         /* expire after hold_time  */
+  struct isis_circuit *circuit;    /* back pointer */     
+};
+
+
+struct isis_adjacency *isis_adj_lookup (u_char *sysid, struct list *adjdb);
+struct isis_adjacency *isis_adj_lookup_snpa (u_char *ssnpa, 
+					     struct list *adjdb);
+struct isis_adjacency *isis_new_adj (u_char *id, u_char *snpa, int level, 
+                                     struct isis_circuit *circuit); 
+void isis_delete_adj (struct isis_adjacency *adj, struct list *adjdb); 
+void isis_adj_state_change (struct isis_adjacency *adj, 
+                            enum isis_adj_state state, char *reason); 
+void isis_adj_print (struct isis_adjacency *adj); 
+int  isis_adj_expire (struct thread *thread);
+void isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty);
+void isis_adj_print_vty_detail (struct isis_adjacency *adj, struct vty *vty);
+void isis_adj_print_vty_extensive (struct isis_adjacency *adj, 
+                                   struct vty *vty);
+void isis_adj_p2p_print_vty (struct isis_adjacency *adj, struct vty *vty);
+void isis_adj_p2p_print_vty_detail (struct isis_adjacency *adj, 
+                                    struct vty *vty);
+void isis_adj_p2p_print_vty_extensive (struct isis_adjacency *adj, 
+                                       struct vty *vty);
+
+void isis_adj_build_neigh_list (struct list *adjdb, struct list *list);
+void isis_adj_build_up_list (struct list *adjdb, struct list *list);
+void isis_adjdb_iterate (struct list *adjdb, 
+                         void (*func)(struct isis_adjacency*, 
+                                      void *), void *arg);
+
+#endif /* ISIS_ADJACENCY_H */
+
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
new file mode 100644
index 0000000..f37c314
--- /dev/null
+++ b/isisd/isis_circuit.c
@@ -0,0 +1,2200 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_circuit.h
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "log.h"
+#include "memory.h"
+#include "if.h"
+#include "linklist.h"
+#include "command.h"
+#include "thread.h"
+#include "hash.h"
+#include "prefix.h"
+#include "stream.h"
+
+#include "isisd/dict.h"
+#include "isisd/include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_network.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_dr.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_csm.h"
+#include "isisd/isis_events.h"
+
+extern struct thread_master *master;
+extern struct isis *isis;
+
+struct isis_circuit *
+isis_circuit_new ()
+{
+  struct isis_circuit *circuit;
+  int i;
+
+  circuit = XMALLOC (MTYPE_ISIS_CIRCUIT, sizeof (struct isis_circuit));
+  if (circuit) {
+    memset (circuit, 0, sizeof (struct isis_circuit));
+    /* set default metrics for circuit */
+    for (i = 0; i < 2; i++) {
+      circuit->metrics[i].metric_default = DEFAULT_CIRCUIT_METRICS;
+      circuit->metrics[i].metric_expense = METRICS_UNSUPPORTED;
+      circuit->metrics[i].metric_error = METRICS_UNSUPPORTED;
+      circuit->metrics[i].metric_delay = METRICS_UNSUPPORTED;
+    }
+  } else {
+    zlog_err ("Can't malloc isis circuit");
+    return  NULL;
+  }
+  
+  return circuit;
+}
+
+
+void
+isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area)
+{
+  int i;
+  circuit->area = area;
+  /*
+   * The level for the circuit is same as for the area, unless configured
+   * otherwise.
+   */
+  circuit->circuit_is_type = area->is_type;
+  /*
+   * Default values
+   */
+  for (i = 0; i < 2; i++) {
+    circuit->hello_interval[i] = HELLO_INTERVAL;
+    circuit->hello_multiplier[i] = HELLO_MULTIPLIER;
+    circuit->csnp_interval[i] = CSNP_INTERVAL;
+    circuit->psnp_interval[i] = PSNP_INTERVAL;
+    circuit->u.bc.priority[i] = DEFAULT_PRIORITY;
+  }
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    circuit->u.bc.adjdb[0] = list_new ();
+    circuit->u.bc.adjdb[1] = list_new ();
+    circuit->u.bc.pad_hellos = 1;
+  }
+  circuit->lsp_interval = LSP_INTERVAL;
+
+  /*
+   * Add the circuit into area
+   */
+  listnode_add (area->circuit_list, circuit);
+
+  circuit->idx = flags_get_index (&area->flags);
+  circuit->lsp_queue = list_new ();
+
+  return;
+}
+
+void 
+isis_circuit_deconfigure (struct isis_circuit *circuit,
+                          struct isis_area *area) 
+{
+  
+  /* Remove circuit from area */
+  listnode_delete (area->circuit_list, circuit);
+  /* Free the index of SRM and SSN flags */
+  flags_free_index (&area->flags, circuit->idx);
+
+  return;
+}
+
+struct isis_circuit *
+circuit_lookup_by_ifp (struct interface *ifp, struct list *list)
+{
+  struct isis_circuit *circuit = NULL;
+  struct listnode *node;
+  
+  if (!list)
+    return NULL;
+  
+  for (node = listhead (list); node; nextnode (node)) {
+    circuit = getdata (node);
+    if (circuit->interface == ifp)
+      return circuit;
+  }
+  
+  return NULL;
+}
+
+struct isis_circuit *
+circuit_scan_by_ifp (struct interface *ifp)
+{
+  struct isis_area *area;
+  struct listnode *node;
+  struct isis_circuit *circuit;
+
+  if (!isis->area_list)
+    return NULL;
+
+  for (node = listhead (isis->area_list); node; nextnode (node)) {
+    area = getdata (node);
+    circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
+    if (circuit)
+      return circuit;
+  }
+  
+  return circuit_lookup_by_ifp (ifp, isis->init_circ_list);
+}
+
+void
+isis_circuit_del (struct isis_circuit *circuit)
+{
+
+  if (!circuit)
+    return;
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    /* destroy adjacency databases */
+    list_delete (circuit->u.bc.adjdb[0]);
+    list_delete (circuit->u.bc.adjdb[1]);
+    /* destroy neighbour lists */
+    if (circuit->u.bc.lan_neighs[0])
+      list_delete (circuit->u.bc.lan_neighs[0]);
+    if (circuit->u.bc.lan_neighs[1])
+      list_delete (circuit->u.bc.lan_neighs[1]);
+    /* destroy addresses */
+  }
+  if (circuit->ip_addrs)
+    list_delete (circuit->ip_addrs);
+#ifdef HAVE_IPV6
+  if (circuit->ipv6_link)
+    list_delete (circuit->ipv6_link);
+  if (circuit->ipv6_non_link)
+    list_delete (circuit->ipv6_non_link);
+#endif /* HAVE_IPV6 */
+  
+  /* and lastly the circuit itself */
+  XFREE (MTYPE_ISIS_CIRCUIT, circuit);
+
+  return;
+}
+
+void
+isis_circuit_add_addr (struct isis_circuit *circuit, 
+                       struct connected *conn)
+{
+  struct prefix_ipv4 *ipv4;
+  u_char buf [BUFSIZ];
+#ifdef HAVE_IPV6
+  struct prefix_ipv6 *ipv6;
+#endif /* HAVE_IPV6 */
+  if (!circuit->ip_addrs) {
+    circuit->ip_addrs = list_new ();
+  }
+#ifdef HAVE_IPV6
+  if (!circuit->ipv6_link) {
+    circuit->ipv6_link = list_new ();
+  }
+  if (!circuit->ipv6_non_link) {
+    circuit->ipv6_non_link = list_new ();
+  }
+#endif /* HAVE_IPV6 */
+
+  memset (&buf, 0, BUFSIZ);
+  if (conn->address->family == AF_INET) {
+    ipv4 = prefix_ipv4_new ();
+    ipv4->prefixlen = conn->address->prefixlen;
+    ipv4->prefix = conn->address->u.prefix4;
+    listnode_add (circuit->ip_addrs, ipv4);
+    prefix2str (conn->address, buf, BUFSIZ);
+#ifdef EXTREME_DEBUG
+    zlog_info ("Added IP address %s to circuit %d", buf,
+               circuit->circuit_id);
+#endif /* EXTREME_DEBUG */	
+  }
+#ifdef HAVE_IPV6
+  if (conn->address->family == AF_INET6) {
+    ipv6 = prefix_ipv6_new ();
+    ipv6->prefixlen = conn->address->prefixlen;
+    ipv6->prefix = conn->address->u.prefix6;
+    if (IN6_IS_ADDR_LINKLOCAL(&ipv6->prefix)) {
+      listnode_add (circuit->ipv6_link, ipv6);
+    } else {
+      listnode_add (circuit->ipv6_non_link, ipv6);
+    }
+    prefix2str (conn->address, buf, BUFSIZ);
+#ifdef EXTREME_DEBUG
+    zlog_info ("Added IPv6 address %s to circuit %d", buf, 
+               circuit->circuit_id);
+#endif /* EXTREME_DEBUG */ 
+  }
+#endif /* HAVE_IPV6 */
+  
+
+  return;
+}
+
+void
+isis_circuit_del_addr (struct isis_circuit *circuit,
+                       struct connected *connected)
+{
+
+}
+
+void
+isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp)
+{
+  struct listnode *node;
+  struct connected *conn;
+
+  circuit->interface = ifp;
+  ifp->info = circuit;
+  
+  circuit->circuit_id = ifp->ifindex % 255; /* FIXME: Why not ? */
+
+  /*  isis_circuit_update_addrs (circuit, ifp); */
+
+  if (if_is_broadcast (ifp)) {
+    circuit->circ_type = CIRCUIT_T_BROADCAST;
+    /*
+     * Get the Hardware Address
+     */
+#ifdef HAVE_SOCKADDR_DL
+    if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN)
+      zlog_warn ("unsupported link layer");
+    else
+      memcpy (circuit->u.bc.snpa, LLADDR(&circuit->interface->sdl), ETH_ALEN);
+#else
+    if (circuit->interface->hw_addr_len != ETH_ALEN) {
+      zlog_warn ("unsupported link layer");
+    } else {
+      memcpy (circuit->u.bc.snpa, circuit->interface->hw_addr, ETH_ALEN);
+    }
+#ifdef EXTREME_DEGUG
+    zlog_info ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s", 
+	       circuit->interface->ifindex, ISO_MTU (circuit), 
+	       snpa_print (circuit->u.bc.snpa));
+
+#endif /* EXTREME_DEBUG */
+#endif /* HAVE_SOCKADDR_DL */   
+  } else if (if_is_pointopoint (ifp)) {
+    circuit->circ_type = CIRCUIT_T_P2P;
+  } else {
+    zlog_warn ("isis_circuit_if_add: unsupported media");
+  }
+  
+  for (node = ifp->connected ? listhead (ifp->connected) : NULL; node; 
+       nextnode (node)) {
+    conn = getdata (node);
+    isis_circuit_add_addr (circuit, conn);
+  }
+
+  return;
+}
+
+void
+isis_circuit_update_params (struct isis_circuit *circuit, 
+                            struct interface *ifp)
+{
+  assert (circuit);
+  
+  if (circuit->circuit_id != ifp->ifindex) {
+    zlog_warn ("changing circuit_id %d->%d", circuit->circuit_id, 
+               ifp->ifindex);    
+    circuit->circuit_id = ifp->ifindex % 255; 
+  }
+
+  /* FIXME: Why is this needed? shouldn't we compare to the area's mtu */
+  /* Ofer, this was here in case someone changes the mtu (e.g. with ifconfig) 
+     The areas MTU is the minimum of mtu's of circuits in the area
+     now we can't catch the change
+     if (circuit->mtu != ifp->mtu) {
+     zlog_warn ("changing circuit mtu %d->%d", circuit->mtu, 
+     ifp->mtu);    
+     circuit->mtu = ifp->mtu;
+     }
+  */
+  /*
+   * Get the Hardware Address
+   */
+#ifdef HAVE_SOCKADDR_DL
+  if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN)
+      zlog_warn ("unsupported link layer");
+    else
+      memcpy (circuit->u.bc.snpa, LLADDR(&circuit->interface->sdl), ETH_ALEN);
+#else
+  if (circuit->interface->hw_addr_len != ETH_ALEN) {
+    zlog_warn ("unsupported link layer");
+  } else {
+    if (memcmp(circuit->u.bc.snpa, circuit->interface->hw_addr, ETH_ALEN)) {
+      zlog_warn ("changing circuit snpa %s->%s", 
+		 snpa_print (circuit->u.bc.snpa), 
+		 snpa_print (circuit->interface->hw_addr));
+    }
+  }
+#endif 
+
+
+
+  if (if_is_broadcast (ifp)) {
+    circuit->circ_type = CIRCUIT_T_BROADCAST;
+  } else if (if_is_pointopoint (ifp)) {
+    circuit->circ_type = CIRCUIT_T_P2P;
+  } else {
+    zlog_warn ("isis_circuit_update_params: unsupported media");
+  }
+  
+  return;
+}
+
+void
+isis_circuit_if_del (struct isis_circuit *circuit) 
+{
+  circuit->interface->info = NULL;
+  circuit->interface = NULL;
+  
+  return;
+}
+
+void
+isis_circuit_up (struct isis_circuit *circuit)
+{
+  
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    if (circuit->area->min_bcast_mtu == 0 || 
+        ISO_MTU(circuit) < circuit->area->min_bcast_mtu )
+      circuit->area->min_bcast_mtu = ISO_MTU(circuit);
+    /*
+     * ISO 10589 - 8.4.1 Enabling of broadcast circuits
+     */
+
+    /* initilizing the hello sending threads
+     * for a broadcast IF
+     */
+
+    /* 8.4.1 a) commence sending of IIH PDUs */
+
+    if (circuit->circuit_is_type & IS_LEVEL_1) {
+      thread_add_event (master, send_lan_l1_hello, circuit, 0);
+      circuit->u.bc.lan_neighs[0] = list_new ();
+    }
+
+    if (circuit->circuit_is_type & IS_LEVEL_2) {
+      thread_add_event (master, send_lan_l2_hello, circuit, 0);
+      circuit->u.bc.lan_neighs[1] = list_new ();
+    }
+
+    /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */
+    /* 8.4.1 c) FIXME: listen for ESH PDUs */
+
+    /* 8.4.1 d) */
+    /* dr election will commence in... */
+    if (circuit->circuit_is_type & IS_LEVEL_1) 
+      circuit->u.bc.t_run_dr[0] = 
+        thread_add_timer (master, isis_run_dr_l1, circuit,
+        2 * circuit->hello_multiplier[0] * circuit->hello_interval[0]); 
+    if (circuit->circuit_is_type & IS_LEVEL_2) 
+      circuit->u.bc.t_run_dr[1] = 
+        thread_add_timer (master, isis_run_dr_l2, circuit,
+       2 * circuit->hello_multiplier[1] * circuit->hello_interval[1]); 
+  } else {
+    /* initializing the hello send threads
+     * for a ptp IF
+     */
+    thread_add_event (master, send_p2p_hello, circuit, 0);
+
+  }
+
+  /* initializing PSNP timers */
+  if (circuit->circuit_is_type & IS_LEVEL_1) {
+    circuit->t_send_psnp[0] = thread_add_timer (master,
+                                                send_l1_psnp,
+                                                circuit,
+                                                isis_jitter
+                                                (circuit->psnp_interval[0],
+                                                 PSNP_JITTER));
+  }
+  
+  if (circuit->circuit_is_type & IS_LEVEL_2) {
+    circuit->t_send_psnp[1] = thread_add_timer (master,
+                                                send_l2_psnp,
+                                                circuit,
+                                                isis_jitter
+                                                (circuit->psnp_interval[1], 
+                                                 PSNP_JITTER));
+
+  }
+  
+  /* initialize the circuit streams */
+  if (circuit->rcv_stream == NULL)
+    circuit->rcv_stream = stream_new (ISO_MTU(circuit));
+
+  if (circuit->snd_stream == NULL)
+    circuit->snd_stream = stream_new (ISO_MTU(circuit));
+
+  /* unified init for circuits */
+  isis_sock_init (circuit);
+
+#ifdef GNU_LINUX
+  circuit->t_read = thread_add_read (master, isis_receive, circuit, 
+                                     circuit->fd);
+#else
+  circuit->t_read = thread_add_timer (master, isis_receive, circuit, 
+                                      circuit->fd);
+#endif
+  return;
+}
+
+void
+isis_circuit_down (struct isis_circuit *circuit)
+{
+  /* Cancel all active threads -- FIXME: wrong place*/
+  if (circuit->t_read)
+    thread_cancel (circuit->t_read);
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    if (circuit->u.bc.t_send_lan_hello[0])
+      thread_cancel (circuit->u.bc.t_send_lan_hello[0]);
+    if (circuit->u.bc.t_send_lan_hello[1])
+      thread_cancel (circuit->u.bc.t_send_lan_hello[1]);
+  } else if (circuit->circ_type == CIRCUIT_T_P2P) {
+    if (circuit->u.p2p.t_send_p2p_hello)
+      thread_cancel (circuit->u.p2p.t_send_p2p_hello);
+  }
+  /* close the socket */
+  close (circuit->fd);
+
+  return;
+}
+
+void
+circuit_update_nlpids (struct isis_circuit *circuit)
+{
+  circuit->nlpids.count = 0;
+  
+  if (circuit->ip_router) {
+    circuit->nlpids.nlpids[0] = NLPID_IP;
+    circuit->nlpids.count++;
+  }
+#ifdef HAVE_IPV6
+  if (circuit->ipv6_router) {
+    circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6;
+    circuit->nlpids.count++;
+  }
+#endif /* HAVE_IPV6 */
+  return;
+}
+
+int
+isis_interface_config_write (struct vty *vty) 
+{
+
+  int write = 0;
+  listnode node;
+  listnode node2;
+  listnode node3;
+  struct interface *ifp;
+  struct isis_area *area;
+  struct isis_circuit *c;
+  struct prefix_ipv4 *ip;
+  int i;
+#ifdef HAVE_IPV6
+  struct prefix_ipv6 *ipv6;
+#endif /*HAVE_IPV6 */
+
+  char buf[BUFSIZ];
+
+
+  LIST_LOOP (iflist, ifp, node)
+  {
+    /* IF name */
+    vty_out (vty, "interface %s%s", ifp->name,VTY_NEWLINE);
+    write++;
+    /* IF desc */
+    if (ifp->desc) {
+      vty_out (vty, " description %s%s", ifp->desc,VTY_NEWLINE);
+      write++;
+    }
+    /* ISIS Circuit */
+    LIST_LOOP (isis->area_list, area, node2)
+    {
+      c = circuit_lookup_by_ifp (ifp, area->circuit_list);
+      if (c) {
+        if (c->ip_router) {
+          vty_out (vty, " ip router isis %s%s",area->area_tag,VTY_NEWLINE);
+          write++;
+        }
+#ifdef HAVE_IPV6
+        if (c->ipv6_router) {
+          vty_out (vty, " ipv6 router isis %s%s",area->area_tag,VTY_NEWLINE);
+          write++;
+        }
+#endif /* HAVE_IPV6 */
+        /* ipv4 addresses - FIXME: those should be related to interface*/
+        if (c->ip_addrs) {LIST_LOOP (c->ip_addrs,ip, node3)
+        {
+           vty_out (vty, " ip%s address %s/%d%s",
+           ip->family == AF_INET ? "" : "v6",
+           inet_ntop (ip->family, &ip->prefix, buf, BUFSIZ), ip->prefixlen, 
+		    VTY_NEWLINE);
+           write++;
+        }}
+
+        /* ipv6 addresses - FIXME: those should be related to interface*/
+#ifdef HAVE_IPV6
+        if (c->ipv6_link) {LIST_LOOP (c->ipv6_link, ipv6, node3)
+          {
+            vty_out (vty, " ip%s address %s/%d%s",
+                     ipv6->family == AF_INET ? "" : "v6",
+                     inet_ntop (ipv6->family, &ipv6->prefix, buf, BUFSIZ),
+                     ipv6->prefixlen,VTY_NEWLINE);
+            write++;
+          }}
+        if (c->ipv6_non_link) {LIST_LOOP (c->ipv6_non_link, ipv6, node3)
+          {
+            vty_out (vty, " ip%s address %s/%d%s",
+                     ipv6->family == AF_INET ? "" : "v6",
+                     inet_ntop (ipv6->family, &ipv6->prefix, buf, BUFSIZ),
+                     ipv6->prefixlen, VTY_NEWLINE);
+            write++;
+          }}        
+#endif /* HAVE_IPV6 */
+
+        /* ISIS - circuit type */
+        if (c->circuit_is_type  == IS_LEVEL_1) {
+          vty_out (vty, " isis circuit-type level-1%s", VTY_NEWLINE);
+          write ++;
+        } else {if (c->circuit_is_type  == IS_LEVEL_2) {
+          vty_out (vty, " isis circuit-type level-2-only%s", VTY_NEWLINE);
+          write ++;
+        }}
+
+        /* ISIS - CSNP interval - FIXME: compare to cisco*/
+        if (c->csnp_interval[0] == c->csnp_interval[1]) {
+          if (c->csnp_interval[0] != CSNP_INTERVAL) {
+            vty_out (vty, " isis csnp-interval %d%s",  c->csnp_interval[0], 
+		     VTY_NEWLINE);
+            write ++;
+          }
+        } else {
+          for (i=0;i<2;i++) {
+            if (c->csnp_interval[1] != CSNP_INTERVAL) {
+              vty_out (vty, " isis csnp-interval %d level-%d%s",  
+		       c->csnp_interval[1],i+1, VTY_NEWLINE);
+              write ++;
+            }
+          }
+        }
+
+        /* ISIS - Hello padding - Defaults to true so only display if false */
+        if (c->circ_type == CIRCUIT_T_BROADCAST && !c->u.bc.pad_hellos) {
+          vty_out (vty, " no isis hello padding%s",  VTY_NEWLINE);
+          write ++;
+        }
+
+        /* ISIS - Hello interval - FIXME: compare to cisco */
+        if (c->hello_interval[0] == c->hello_interval[1]) {
+          if (c->hello_interval[0] != HELLO_INTERVAL) {
+            vty_out (vty, " isis hello-interval %d%s",  c->hello_interval[0], 
+		     VTY_NEWLINE);
+            write ++;
+          }
+        } else {
+          for (i=0;i<2;i++) {
+            if (c->hello_interval[i] != HELLO_INTERVAL) {
+              if (c->hello_interval[i] == HELLO_MINIMAL) {
+                vty_out (vty, " isis hello-interval minimal level-%d%s", i+1, 
+			 VTY_NEWLINE);
+              } else {
+                vty_out (vty, " isis hello-interval %d level-%d%s",  
+			 c->hello_interval[i],i+1, VTY_NEWLINE);
+              }
+              write ++;
+            }
+          }
+        }
+
+        /* ISIS - Hello Multiplier */
+        if (c->hello_multiplier[0] == c->hello_multiplier[1]) {
+          if (c->hello_multiplier[0] != HELLO_MULTIPLIER ) {
+            vty_out (vty, " isis hello-multiplier %d%s",  
+		     c->hello_multiplier[0], VTY_NEWLINE);
+            write ++;
+          }
+        } else {
+          for (i=0;i<2;i++) {
+            if (c->hello_multiplier[i] != HELLO_MULTIPLIER) {
+              vty_out (vty, " isis hello-multiplier %d level-%d%s",  
+		       c->hello_multiplier[i],i+1, VTY_NEWLINE);
+              write ++;
+            }
+          }
+        }
+        /* ISIS - Priority */
+        if (c->circ_type == CIRCUIT_T_BROADCAST) {
+          if (c->u.bc.priority[0] == c->u.bc.priority[1]) {
+            if (c->u.bc.priority[0] != DEFAULT_PRIORITY) {
+              vty_out (vty, " isis priority %d%s",  c->u.bc.priority[0], 
+                       VTY_NEWLINE);
+              write ++;
+            }
+          } else {
+            for (i=0;i<2;i++) {
+              if (c->u.bc.priority[i] != DEFAULT_PRIORITY) {
+                vty_out (vty, " isis priority %d level-%d%s",  
+                         c->u.bc.priority[i],i+1, VTY_NEWLINE);
+                write ++;
+              }
+            }
+          }
+        }
+        /* ISIS - Metric */
+        if (c->metrics[0].metric_default == c->metrics[1].metric_default) {
+          if (c->metrics[0].metric_default != DEFAULT_CIRCUIT_METRICS) {
+            vty_out (vty, " isis metric %d%s",  c->metrics[0].metric_default, 
+		     VTY_NEWLINE);
+            write ++;
+          }
+        } else {
+          for (i=0;i<2;i++) {
+            if (c->metrics[i].metric_default != DEFAULT_CIRCUIT_METRICS) {
+              vty_out (vty, " isis metric %d level-%d%s",  
+		       c->metrics[i].metric_default,i+1, VTY_NEWLINE);
+              write ++;
+            }
+          }
+        }
+
+      }
+    }
+  }
+  
+  return write;
+}
+  
+
+DEFUN (ip_router_isis,
+       ip_router_isis_cmd,
+       "ip router isis WORD",
+       "Interface Internet Protocol config commands\n"
+       "IP router interface commands\n"
+       "IS-IS Routing for IP\n"
+       "Routing process tag\n"
+       )
+{
+  struct isis_circuit *c;
+  struct interface *ifp;
+  struct isis_area *area;
+  
+  ifp = (struct interface *)vty->index;
+  assert (ifp);
+  
+  area = isis_area_lookup (argv[0]);
+
+  /* Prevent more than one circuit per interface */
+  if (area)
+    c = circuit_lookup_by_ifp (ifp, area->circuit_list);
+  else c = NULL;
+  if (c && (ifp->info != NULL)) {
+#ifdef HAVE_IPV6
+    if (c->ipv6_router == 0) {
+#endif /* HAVE_IPV6 */
+      vty_out (vty, "ISIS circuit is already defined%s", VTY_NEWLINE);
+      return CMD_WARNING;
+#ifdef HAVE_IPV6
+    }
+#endif /* HAVE_IPV6 */
+  }
+  
+  /* this is here for ciscopability */
+  if (!area) {
+    vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  if (!c) {
+    c = circuit_lookup_by_ifp (ifp, isis->init_circ_list); 
+    c = isis_csm_state_change (ISIS_ENABLE, c, area);
+    c->interface = ifp;  /* this is automatic */
+    ifp->info = c;       /* hardly related to the FSM */
+  }
+
+  if(!c) 
+    return CMD_WARNING;
+
+  c->ip_router = 1;
+  area->ip_circuits++;
+  circuit_update_nlpids (c);
+
+  vty->node = INTERFACE_NODE;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_router_isis,
+       no_ip_router_isis_cmd,
+       "no ip router isis WORD",
+       NO_STR
+       "Interface Internet Protocol config commands\n"
+       "IP router interface commands\n"
+       "IS-IS Routing for IP\n"
+       "Routing process tag\n"
+       ) 
+{
+  struct isis_circuit *circuit = NULL;
+  struct interface *ifp;
+  struct isis_area *area;
+  struct listnode *node;
+
+  ifp = (struct interface *)vty->index;
+  assert (ifp);
+  
+  area = isis_area_lookup (argv[0]);
+  if (!area) {
+    vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  LIST_LOOP (area->circuit_list, circuit, node)
+    if (circuit->interface == ifp)
+      break;
+  if (!circuit) {
+    vty_out (vty, "Can't find ISIS interface %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  circuit->ip_router = 0;
+  area->ip_circuits--;
+#ifdef HAVE_IPV6
+  if (circuit->ipv6_router == 0)
+#endif
+    isis_csm_state_change (ISIS_DISABLE, circuit, area);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (isis_circuit_type,
+       isis_circuit_type_cmd,
+       "isis circuit-type (level-1|level-1-2|level-2-only)",
+       "IS-IS commands\n"
+       "Configure circuit type for interface\n"
+       "Level-1 only adjacencies are formed\n"
+       "Level-1-2 adjacencies are formed\n"
+       "Level-2 only adjacencies are formed\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int circuit_t;
+  int is_type;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  /* UGLY - will remove l8r */
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+
+  assert (circuit);
+
+  circuit_t = string2circuit_t (argv[0]);
+
+  if (!circuit_t) { 
+    vty_out (vty, "Unknown circuit-type %s", VTY_NEWLINE);
+    return CMD_SUCCESS;
+  }
+  
+  is_type = circuit->area->is_type;
+  if (is_type == IS_LEVEL_1_AND_2 || is_type == circuit_t)
+   isis_event_circuit_type_change (circuit, circuit_t);
+  else {
+    vty_out (vty, "invalid circuit level for area %s.%s", 
+	     circuit->area->area_tag, VTY_NEWLINE);
+  }
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_circuit_type,
+       no_isis_circuit_type_cmd,
+       "no isis circuit-type (level-1|level-1-2|level-2-only)",
+       NO_STR
+       "IS-IS commands\n"
+       "Configure circuit type for interface\n"
+       "Level-1 only adjacencies are formed\n"
+       "Level-1-2 adjacencies are formed\n"
+       "Level-2 only adjacencies are formed\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+
+  assert(circuit);
+  
+  /*
+   * Set the circuits level to its default value which is that of the area
+   */
+  isis_event_circuit_type_change (circuit, circuit->area->is_type);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (isis_passwd,
+       isis_passwd_cmd,
+       "isis password WORD",
+       "IS-IS commands\n"
+       "Configure the authentication password for interface\n"
+       "Password\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int len;
+ 
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  
+  len = strlen (argv[0]);
+  if (len > 254) {
+    vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  circuit->passwd.len = len;
+  circuit->passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
+  strncpy (circuit->passwd.passwd, argv[0], 255);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_passwd,
+       no_isis_passwd_cmd,
+       "no isis password",
+       NO_STR
+       "IS-IS commands\n"
+       "Configure the authentication password for interface\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+    
+  memset (&circuit->passwd, 0, sizeof (struct isis_passwd));
+  
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (isis_priority,
+       isis_priority_cmd,
+       "isis priority <0-127>",
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Priority value\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int prio;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  prio = atoi (argv[0]);
+
+  circuit->u.bc.priority[0] = prio;
+  circuit->u.bc.priority[1] = prio;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_priority,
+       no_isis_priority_cmd,
+       "no isis priority",
+       NO_STR
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  circuit->u.bc.priority[0] = DEFAULT_PRIORITY;
+  circuit->u.bc.priority[1] = DEFAULT_PRIORITY;
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_priority,
+       no_isis_priority_arg_cmd,
+       "no isis priority <0-127>",
+       NO_STR
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Priority value\n"
+       )
+
+DEFUN (isis_priority_l1,
+       isis_priority_l1_cmd,
+       "isis priority <0-127> level-1", 
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Priority value\n"
+       "Specify priority for level-1 routing\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int prio;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  prio = atoi (argv[0]);
+
+  circuit->u.bc.priority[0] = prio;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_priority_l1,
+       no_isis_priority_l1_cmd,
+       "no isis priority level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Specify priority for level-1 routing\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  circuit->u.bc.priority[0] = DEFAULT_PRIORITY;
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_priority_l1,
+       no_isis_priority_l1_arg_cmd,
+       "no isis priority <0-127> level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Priority value\n"
+       "Specify priority for level-1 routing\n"
+       )
+
+DEFUN (isis_priority_l2,
+       isis_priority_l2_cmd,
+       "isis priority <0-127> level-2", 
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Priority value\n"
+       "Specify priority for level-2 routing\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int prio;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  prio = atoi (argv[0]);
+
+  circuit->u.bc.priority[1] = prio;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_priority_l2,
+       no_isis_priority_l2_cmd,
+       "no isis priority level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Specify priority for level-2 routing\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  circuit->u.bc.priority[1] = DEFAULT_PRIORITY;
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_priority_l2,
+       no_isis_priority_l2_arg_cmd,
+       "no isis priority <0-127> level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set priority for Designated Router election\n"
+       "Priority value\n"
+       "Specify priority for level-2 routing\n"
+       )
+
+/* Metric command */
+
+DEFUN (isis_metric,
+       isis_metric_cmd,
+       "isis metric <0-63>",
+       "IS-IS commands\n"
+       "Set default metric for circuit\n"
+       "Default metric value\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int met;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  met = atoi (argv[0]);
+
+  circuit->metrics[0].metric_default = met;
+  circuit->metrics[1].metric_default = met;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_metric,
+       no_isis_metric_cmd,
+       "no isis metric",
+       NO_STR
+       "IS-IS commands\n"
+       "Set default metric for circuit\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  circuit->metrics[0].metric_default = DEFAULT_CIRCUIT_METRICS;
+  circuit->metrics[1].metric_default = DEFAULT_CIRCUIT_METRICS;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_metric,
+       no_isis_metric_arg_cmd,
+       "no isis metric <0-127>",
+       NO_STR
+       "IS-IS commands\n"
+       "Set default metric for circuit\n"
+       "Default metric value\n"
+       )
+/* end of metrics */
+
+
+DEFUN (isis_hello_interval,
+       isis_hello_interval_cmd,
+       "isis hello-interval (<1-65535>|minimal)",
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Hello interval value\n"
+       "Holdtime 1 seconds, interval depends on multiplier\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int interval;
+  char c;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit); 
+  c = *argv[0];
+  if (isdigit((int)c)) {
+    interval = atoi (argv[0]);
+  } else
+    interval = HELLO_MINIMAL; /* FIXME: should be calculated */
+
+  circuit->hello_interval[0] = (u_int16_t)interval;
+  circuit->hello_interval[1] = (u_int16_t)interval;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_interval,
+       no_isis_hello_interval_cmd,
+       "no isis hello-interval",
+       NO_STR
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+
+  circuit->hello_interval[0] = HELLO_INTERVAL; /* Default is 1 sec. */
+  circuit->hello_interval[1] = HELLO_INTERVAL;
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_interval,
+       no_isis_hello_interval_arg_cmd,
+       "no isis hello-interval (<1-65535>|minimal)",
+       NO_STR
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Hello interval value\n"
+       "Holdtime 1 second, interval depends on multiplier\n"
+       )
+
+DEFUN (isis_hello_interval_l1,
+       isis_hello_interval_l1_cmd,
+       "isis hello-interval (<1-65535>|minimal) level-1",
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Hello interval value\n"
+       "Holdtime 1 second, interval depends on multiplier\n"
+       "Specify hello-interval for level-1 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  long interval;
+  char c;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+ 
+  c = *argv[0];
+  if (isdigit((int)c)) {
+    interval = atoi (argv[0]);
+  } else
+    interval = HELLO_MINIMAL;
+
+  circuit->hello_interval[0] = (u_int16_t)interval;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_interval_l1,
+       no_isis_hello_interval_l1_cmd,
+       "no isis hello-interval level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Specify hello-interval for level-1 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+
+  circuit->hello_interval[0] = HELLO_INTERVAL; /* Default is 1 sec. */
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_interval_l1,
+       no_isis_hello_interval_l1_arg_cmd,
+       "no isis hello-interval (<1-65535>|minimal) level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Hello interval value\n"
+       "Holdtime 1 second, interval depends on multiplier\n"
+       "Specify hello-interval for level-1 IIHs\n"
+       )
+
+DEFUN (isis_hello_interval_l2,
+       isis_hello_interval_l2_cmd,
+       "isis hello-interval (<1-65535>|minimal) level-2",
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Hello interval value\n"
+       "Holdtime 1 second, interval depends on multiplier\n"
+       "Specify hello-interval for level-2 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  long interval;
+  char c;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+ 
+  c = *argv[0];
+  if (isdigit((int)c)) {
+    interval = atoi (argv[0]);
+  } else
+    interval = HELLO_MINIMAL;
+
+  circuit->hello_interval[1] = (u_int16_t)interval;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_interval_l2,
+       no_isis_hello_interval_l2_cmd,
+       "no isis hello-interval level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Specify hello-interval for level-2 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+
+  circuit->hello_interval[1] = HELLO_INTERVAL; /* Default is 1 sec. */
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_interval_l2,
+       no_isis_hello_interval_l2_arg_cmd,
+       "no isis hello-interval (<1-65535>|minimal) level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set Hello interval\n"
+       "Hello interval value\n"
+       "Holdtime 1 second, interval depends on multiplier\n"
+       "Specify hello-interval for level-2 IIHs\n"
+       )
+
+
+DEFUN (isis_hello_multiplier,
+       isis_hello_multiplier_cmd,
+       "isis hello-multiplier <3-1000>",
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Hello multiplier value\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int mult;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  mult = atoi (argv[0]);
+
+  circuit->hello_multiplier[0] = (u_int16_t)mult;
+  circuit->hello_multiplier[1] = (u_int16_t)mult;
+    
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_multiplier,
+       no_isis_hello_multiplier_cmd,
+       "no isis hello-multiplier",
+       NO_STR
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  circuit->hello_multiplier[0] = HELLO_MULTIPLIER;
+  circuit->hello_multiplier[1] = HELLO_MULTIPLIER;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_multiplier,
+       no_isis_hello_multiplier_arg_cmd,
+       "no isis hello-multiplier <3-1000>",
+       NO_STR
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Hello multiplier value\n"
+       )
+
+DEFUN (isis_hello_multiplier_l1,
+       isis_hello_multiplier_l1_cmd,
+       "isis hello-multiplier <3-1000> level-1",
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Hello multiplier value\n"
+       "Specify hello multiplier for level-1 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int mult;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  mult = atoi (argv[0]);
+
+  circuit->hello_multiplier[0] = (u_int16_t)mult;
+    
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_multiplier_l1,
+       no_isis_hello_multiplier_l1_cmd,
+       "no isis hello-multiplier level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Specify hello multiplier for level-1 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  circuit->hello_multiplier[0] = HELLO_MULTIPLIER;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_multiplier_l1,
+       no_isis_hello_multiplier_l1_arg_cmd,
+       "no isis hello-multiplier <3-1000> level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Hello multiplier value\n"
+       "Specify hello multiplier for level-1 IIHs\n"
+       )
+
+DEFUN (isis_hello_multiplier_l2,
+       isis_hello_multiplier_l2_cmd,
+       "isis hello-multiplier <3-1000> level-2",
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Hello multiplier value\n"
+       "Specify hello multiplier for level-2 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  int mult;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  mult = atoi (argv[0]);
+
+  circuit->hello_multiplier[1] = (u_int16_t)mult;
+    
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello_multiplier_l2,
+       no_isis_hello_multiplier_l2_cmd,
+       "no isis hello-multiplier level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Specify hello multiplier for level-2 IIHs\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  circuit->hello_multiplier[1] = HELLO_MULTIPLIER;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_isis_hello_multiplier_l2,
+       no_isis_hello_multiplier_l2_arg_cmd,
+       "no isis hello-multiplier <3-1000> level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set multiplier for Hello holding time\n"
+       "Hello multiplier value\n"
+       "Specify hello multiplier for level-2 IIHs\n"
+       )
+
+DEFUN (isis_hello,
+       isis_hello_cmd,
+       "isis hello padding",
+       "IS-IS commands\n"
+       "Add padding to IS-IS hello packets\n"
+       "Pad hello packets\n"
+       "<cr>\n")
+{
+  struct interface *ifp;
+  struct isis_circuit *circuit;
+  
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  circuit->u.bc.pad_hellos = 1;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (ip_address,
+       ip_address_cmd,
+       "ip address A.B.C.D/A",
+       "Interface Internet Protocol config commands\n"
+       "Set the IP address of an interface\n"
+       "IP address (e.g. 10.0.0.1/8\n")
+  
+{
+  struct interface *ifp;
+  struct isis_circuit *circuit;
+  struct prefix_ipv4 *ipv4, *ip;
+  struct listnode *node;
+  int ret, found = 1;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+
+  assert (circuit);
+#ifdef HAVE_IPV6
+  zlog_info ("ip_address_cmd circuit %d", circuit->interface->ifindex);
+#endif /* HAVE_IPV6 */
+
+  ipv4 = prefix_ipv4_new ();
+  
+  ret = str2prefix_ipv4 (argv[0], ipv4);
+  if (ret <= 0) {
+    zlog_warn ("ip_address_cmd(): malformed address");
+    vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  if (!circuit->ip_addrs) 
+    circuit->ip_addrs = list_new ();
+  else {
+    for (node = listhead (circuit->ip_addrs); node; nextnode (node)) {
+      ip = getdata (node);
+      if (prefix_same ((struct prefix *)ip, (struct prefix *)ipv4))
+	found = 1;
+    }
+    if (found) {
+    prefix_ipv4_free (ipv4);
+    return CMD_SUCCESS;
+    }
+  }
+
+  
+  listnode_add (circuit->ip_addrs, ipv4);
+#ifdef EXTREME_DEBUG  
+  zlog_info ("added IP address %s to circuit %d", argv[0], 
+	     circuit->interface->ifindex);
+#endif /* EXTREME_DEBUG */
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_address,
+       no_ip_address_cmd,
+       "no ip address A.B.C.D/A",
+       NO_STR
+       "Interface Internet Protocol config commands\n"
+       "Set the IP address of an interface\n"
+       "IP address (e.g. 10.0.0.1/8\n")
+{
+  struct interface *ifp;
+  struct isis_circuit *circuit;
+  struct prefix_ipv4 ipv4, *ip = NULL;
+  struct listnode *node;
+  int ret;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  /* UGLY - will remove l8r */
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  if (!circuit->ip_addrs || circuit->ip_addrs->count == 0) {
+    vty_out (vty, "Invalid address %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  ret = str2prefix_ipv4 (argv[0], &ipv4);
+  if (ret <= 0) {
+    vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  for (node = listhead (circuit->ip_addrs); node; nextnode (node)) {
+    ip = getdata (node);
+    if (prefix_same ((struct prefix *)ip, (struct prefix *)&ipv4))
+      break;
+  }
+  
+  if (ip) {
+    listnode_delete (circuit->ip_addrs, ip);
+  } else {
+    vty_out (vty, "Invalid address %s", VTY_NEWLINE);
+  }
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_hello,
+       no_isis_hello_cmd,
+       "no isis hello padding",
+       NO_STR
+       "IS-IS commands\n"
+       "Add padding to IS-IS hello packets\n"
+       "Pad hello packets\n"
+       "<cr>\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  circuit->u.bc.pad_hellos = 0;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (csnp_interval,
+       csnp_interval_cmd,
+       "isis csnp-interval <0-65535>",
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "CSNP interval value\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  unsigned long interval;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  interval = atol (argv[0]);
+
+  circuit->csnp_interval[0] = (u_int16_t)interval;
+  circuit->csnp_interval[1] = (u_int16_t)interval;
+    
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_csnp_interval,
+       no_csnp_interval_cmd,
+       "no isis csnp-interval",
+       NO_STR
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       )
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+    
+  circuit->csnp_interval[0] = CSNP_INTERVAL;
+  circuit->csnp_interval[1] = CSNP_INTERVAL;
+    
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_csnp_interval,
+       no_csnp_interval_arg_cmd,
+       "no isis csnp-interval <0-65535>",
+       NO_STR
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "CSNP interval value\n")
+
+
+DEFUN (csnp_interval_l1,
+       csnp_interval_l1_cmd,
+       "isis csnp-interval <0-65535> level-1",
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "CSNP interval value\n"
+       "Specify interval for level-1 CSNPs\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  unsigned long interval;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  interval = atol (argv[0]);
+  
+  circuit->csnp_interval[0] = (u_int16_t)interval;
+    
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_csnp_interval_l1,
+       no_csnp_interval_l1_cmd,
+       "no isis csnp-interval level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "Specify interval for level-1 CSNPs\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  circuit->csnp_interval[0] = CSNP_INTERVAL;
+    
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_csnp_interval_l1,
+       no_csnp_interval_l1_arg_cmd,
+       "no isis csnp-interval <0-65535> level-1",
+       NO_STR
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "CSNP interval value\n"
+       "Specify interval for level-1 CSNPs\n")
+
+
+DEFUN (csnp_interval_l2,
+       csnp_interval_l2_cmd,
+       "isis csnp-interval <0-65535> level-2",
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "CSNP interval value\n"
+       "Specify interval for level-2 CSNPs\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+  unsigned long interval;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  interval = atol (argv[0]);
+  
+  circuit->csnp_interval[1] = (u_int16_t)interval;
+    
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_csnp_interval_l2,
+       no_csnp_interval_l2_cmd,
+       "no isis csnp-interval level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "Specify interval for level-2 CSNPs\n")
+{
+  struct isis_circuit *circuit;
+  struct interface *ifp;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+  
+  circuit->csnp_interval[1] = CSNP_INTERVAL;
+    
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_csnp_interval_l2,
+       no_csnp_interval_l2_arg_cmd,
+       "no isis csnp-interval <0-65535> level-2",
+       NO_STR
+       "IS-IS commands\n"
+       "Set CSNP interval in seconds\n"
+       "CSNP interval value\n"
+       "Specify interval for level-2 CSNPs\n")
+
+
+#ifdef HAVE_IPV6
+DEFUN (ipv6_router_isis,
+       ipv6_router_isis_cmd,
+       "ipv6 router isis WORD",
+       "IPv6 interface subcommands\n"
+       "IPv6 Router interface commands\n"
+       "IS-IS Routing for IPv6\n"
+       "Routing process tag\n")
+{
+  struct isis_circuit *c;
+  struct interface *ifp;
+  struct isis_area *area;
+  
+  ifp = (struct interface *)vty->index;
+  assert (ifp);
+  
+  area = isis_area_lookup (argv[0]);
+
+  /* Prevent more than one circuit per interface */
+  if (area)
+    c = circuit_lookup_by_ifp (ifp, area->circuit_list);
+  else  c = NULL;
+  
+  if (c && (ifp->info != NULL)) {
+    if (c->ipv6_router == 1) {
+      vty_out (vty, "ISIS circuit is already defined for IPv6%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  }
+
+  /* this is here for ciscopability */
+  if (!area) {
+    vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  if (!c) {
+    c = circuit_lookup_by_ifp (ifp, isis->init_circ_list); 
+    c = isis_csm_state_change (ISIS_ENABLE, c, area);
+    c->interface = ifp;       
+    ifp->info = c;               
+  }
+
+  if(!c) 
+    return CMD_WARNING;
+
+  c->ipv6_router = 1;
+  area->ipv6_circuits++;
+  circuit_update_nlpids (c);
+
+  vty->node = INTERFACE_NODE;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_router_isis,
+       no_ipv6_router_isis_cmd,
+       "no ipv6 router isis WORD",
+       NO_STR
+       "IPv6 interface subcommands\n"
+       "IPv6 Router interface commands\n"
+       "IS-IS Routing for IPv6\n"
+       "Routing process tag\n")
+{
+  struct isis_circuit *c;
+  struct interface *ifp;
+  struct isis_area *area;
+  
+  ifp = (struct interface *)vty->index;
+  /* UGLY - will remove l8r
+     if (circuit == NULL) {
+  return CMD_WARNING;
+    } */
+  assert (ifp);
+  
+  area = isis_area_lookup (argv[0]);
+  if (!area) {
+    vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+ 
+  c = circuit_lookup_by_ifp (ifp, area->circuit_list);
+  if (!c)
+    return CMD_WARNING;
+
+  c->ipv6_router = 0;
+  area->ipv6_circuits--;
+  if (c->ip_router == 0)
+    isis_csm_state_change (ISIS_DISABLE, c, area);
+
+  return CMD_SUCCESS;
+}
+
+#if 0 /* Guess we don't really need these */
+
+DEFUN (ipv6_address,
+       ipv6_address_cmd,
+       "ipv6 address X:X::X:X/M",
+       "Interface Internet Protocol config commands\n"
+       "Set the IP address of an interface\n"
+       "IPv6 address (e.g. 3ffe:506::1/48)\n")
+{
+  struct interface *ifp;
+  struct isis_circuit *circuit;
+  struct prefix_ipv6 *ipv6, *ip6;
+  struct listnode *node;
+  int ret, found = 1;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  /* UGLY - will remove l8r */
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+#ifdef EXTREME_DEBUG
+  zlog_info ("ipv6_address_cmd circuit %d", circuit->idx);
+#endif /* EXTREME_DEBUG */
+  
+  if (circuit == NULL) {
+    zlog_warn ("ipv6_address_cmd(): no circuit");
+    return CMD_WARNING;
+  }
+  
+  
+  ipv6 = prefix_ipv6_new ();
+  
+  ret = str2prefix_ipv6 (argv[0], ipv6);
+  if (ret <= 0) {
+    vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  if (!circuit->ipv6_addrs) 
+    circuit->ipv6_addrs = list_new ();
+  else {
+    for (node = listhead (circuit->ipv6_addrs); node; nextnode (node)) {
+      ip6 = getdata (node);
+      if (prefix_same ((struct prefix *)ip6, (struct prefix *)ipv6))
+      found = 1;
+    }
+    if (found) {
+    prefix_ipv6_free (ipv6);
+    return CMD_SUCCESS;
+    }
+  }
+
+  
+  listnode_add (circuit->ipv6_addrs, ipv6);
+#ifdef EXTREME_DEBUG
+  zlog_info ("added IPv6 address %s to circuit %d", argv[0], circuit->idx);
+#endif /* EXTREME_DEBUG */
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_address,
+       no_ipv6_address_cmd,
+       "no ipv6 address X:X::X:X/M",              
+       NO_STR
+       "Interface Internet Protocol config commands\n"
+       "Set the IP address of an interface\n"
+       "IPv6 address (e.g. 3ffe:506::1/48)\n")
+{
+  struct interface *ifp;
+  struct isis_circuit *circuit;
+  struct prefix_ipv6 ipv6, *ip6 = NULL;
+  struct listnode *node;
+  int ret;
+
+  ifp  = vty->index;
+  circuit = ifp->info;
+  /* UGLY - will remove l8r */
+  if (circuit == NULL) {
+    return CMD_WARNING;
+  }
+  assert (circuit);
+
+  if (!circuit->ipv6_addrs || circuit->ipv6_addrs->count == 0) {
+    vty_out (vty, "Invalid address %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  ret = str2prefix_ipv6 (argv[0], &ipv6);
+  if (ret <= 0) {
+    vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  for (node = listhead (circuit->ipv6_addrs); node; nextnode (node)) {
+    ip6 = getdata (node);
+    if (prefix_same ((struct prefix *)ip6, (struct prefix *)&ipv6))
+      break;
+  }
+  
+  if (ip6) {
+    listnode_delete (circuit->ipv6_addrs, ip6);
+  } else {
+    vty_out (vty, "Invalid address %s", VTY_NEWLINE);
+  }
+  
+  return CMD_SUCCESS;
+}
+#endif /* 0 */
+#endif /* HAVE_IPV6 */ 
+
+
+struct cmd_node interface_node =
+{
+  INTERFACE_NODE,
+  "%s(config-if)# ",
+  1,
+};
+
+
+int
+isis_if_new_hook (struct interface *ifp)
+{
+/* FIXME: Discuss if the circuit should be created here
+  ifp->info = XMALLOC (MTYPE_ISIS_IF_INFO, sizeof (struct isis_if_info)); */
+  ifp->info = NULL;
+  return 0;
+}
+
+int
+isis_if_delete_hook (struct interface *ifp)
+{
+/* FIXME: Discuss if the circuit should be created here
+  XFREE (MTYPE_ISIS_IF_INFO, ifp->info);*/
+  ifp->info = NULL;
+  return 0;
+}
+
+
+void
+isis_circuit_init ()
+{
+  
+  /* Initialize Zebra interface data structure */
+  if_init ();
+  if_add_hook (IF_NEW_HOOK, isis_if_new_hook);
+  if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook);
+
+  /* Install interface node */
+  install_node (&interface_node, isis_interface_config_write);
+  install_element (CONFIG_NODE, &interface_cmd);
+
+  install_default (INTERFACE_NODE);
+  install_element (INTERFACE_NODE, &interface_desc_cmd);
+  install_element (INTERFACE_NODE, &no_interface_desc_cmd);
+
+  install_element (INTERFACE_NODE, &ip_router_isis_cmd);
+  install_element (INTERFACE_NODE, &no_ip_router_isis_cmd);
+
+  install_element (INTERFACE_NODE, &isis_circuit_type_cmd);
+  install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd);
+
+  install_element (INTERFACE_NODE, &isis_passwd_cmd);
+  install_element (INTERFACE_NODE, &no_isis_passwd_cmd);
+
+  install_element (INTERFACE_NODE, &isis_priority_cmd);
+  install_element (INTERFACE_NODE, &no_isis_priority_cmd);
+  install_element (INTERFACE_NODE, &no_isis_priority_arg_cmd);
+  install_element (INTERFACE_NODE, &isis_priority_l1_cmd);
+  install_element (INTERFACE_NODE, &no_isis_priority_l1_cmd);
+  install_element (INTERFACE_NODE, &no_isis_priority_l1_arg_cmd);
+  install_element (INTERFACE_NODE, &isis_priority_l2_cmd);
+  install_element (INTERFACE_NODE, &no_isis_priority_l2_cmd);
+  install_element (INTERFACE_NODE, &no_isis_priority_l2_arg_cmd);
+
+  install_element (INTERFACE_NODE, &isis_metric_cmd);
+  install_element (INTERFACE_NODE, &no_isis_metric_cmd);
+  install_element (INTERFACE_NODE, &no_isis_metric_arg_cmd);
+
+  install_element (INTERFACE_NODE, &isis_hello_interval_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_interval_arg_cmd);
+  install_element (INTERFACE_NODE, &isis_hello_interval_l1_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_arg_cmd);
+  install_element (INTERFACE_NODE, &isis_hello_interval_l2_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_arg_cmd);
+
+  install_element (INTERFACE_NODE, &isis_hello_multiplier_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_multiplier_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_multiplier_arg_cmd);
+  install_element (INTERFACE_NODE, &isis_hello_multiplier_l1_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_arg_cmd);
+  install_element (INTERFACE_NODE, &isis_hello_multiplier_l2_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_arg_cmd);
+
+  install_element (INTERFACE_NODE, &isis_hello_cmd);
+  install_element (INTERFACE_NODE, &no_isis_hello_cmd);
+
+  install_element (INTERFACE_NODE, &ip_address_cmd);
+  install_element (INTERFACE_NODE, &no_ip_address_cmd);
+
+  install_element (INTERFACE_NODE, &csnp_interval_cmd);
+  install_element (INTERFACE_NODE, &no_csnp_interval_cmd);
+  install_element (INTERFACE_NODE, &no_csnp_interval_arg_cmd);
+  install_element (INTERFACE_NODE, &csnp_interval_l1_cmd);
+  install_element (INTERFACE_NODE, &no_csnp_interval_l1_cmd);
+  install_element (INTERFACE_NODE, &no_csnp_interval_l1_arg_cmd);
+  install_element (INTERFACE_NODE, &csnp_interval_l2_cmd);
+  install_element (INTERFACE_NODE, &no_csnp_interval_l2_cmd);
+  install_element (INTERFACE_NODE, &no_csnp_interval_l2_arg_cmd);
+
+#ifdef HAVE_IPV6
+  install_element (INTERFACE_NODE, &ipv6_router_isis_cmd);
+  install_element (INTERFACE_NODE, &no_ipv6_router_isis_cmd);
+#if 0
+  install_element (INTERFACE_NODE, &ipv6_address_cmd);
+  install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
+#endif
+#endif
+
+}
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
new file mode 100644
index 0000000..7163c5b
--- /dev/null
+++ b/isisd/isis_circuit.h
@@ -0,0 +1,158 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_circuit.h
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef ISIS_CIRCUIT_H
+#define ISIS_CIRCUIT_H
+
+#define CIRCUIT_MAX 255
+
+struct password {
+  struct password *next;
+  int               len;
+  u_char          *pass;
+};
+
+struct metric {
+  u_char metric_default;
+  u_char metric_error;
+  u_char metric_expense;
+  u_char metric_delay;
+};
+
+struct isis_bcast_info {
+  u_char snpa [ETH_ALEN];                  /* SNPA of this circuit */
+  char run_dr_elect[2];                    /* Should we run dr election ? */
+  struct thread *t_run_dr[2];              /* DR election thread */
+  struct thread *t_send_lan_hello[2];      /* send LAN IIHs in this thread */
+  struct list *adjdb[2];                   /* adjacency dbs */
+  struct list *lan_neighs[2];              /* list of lx neigh snpa */
+  char is_dr[2];                           /* Are we level x DR ? */
+  u_char l1_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-1 DR */
+  u_char l2_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-2 DR */
+  struct thread *t_refresh_pseudo_lsp[2];  /* refresh pseudo-node LSPs */
+  int pad_hellos;                          /* add padding to Hello PDUs ? */
+  u_char priority[2];                      /* l1/2 IS Priority */
+};
+
+struct isis_p2p_info {
+  struct isis_adjacency    *neighbor;
+  struct thread *t_send_p2p_hello;         /* send P2P IIHs in this thread  */
+};
+
+struct isis_circuit {
+  int state;
+  u_char circuit_id;             /* l1/l2 p2p/bcast CircuitID */
+  struct isis_area *area;        /* back pointer to the area */
+  struct interface *interface;   /* interface info from z */
+  int fd;                        /* IS-IS l1/2 socket */
+  struct nlpids nlpids;    
+  /*
+   * Threads
+   */
+  struct thread *t_read;
+  struct thread *t_send_csnp[2];
+  struct thread *t_send_psnp[2];
+  struct list *lsp_queue;        /* LSPs to be txed (both levels) */
+  /* there is no real point in two streams, just for programming kicker */
+  int (* rx) (struct isis_circuit *circuit, u_char *ssnpa);
+  struct stream *rcv_stream;     /* Stream for receiving */
+  int (* tx) (struct isis_circuit *circuit, int level);
+  struct stream *snd_stream;     /* Stream for sending */
+  int idx;                       /* idx in S[RM|SN] flags */
+#define CIRCUIT_T_BROADCAST  0 
+#define CIRCUIT_T_P2P        1
+#define CIRCUIT_T_STATIC_IN  2
+#define CIRCUIT_T_STATIC_OUT 3
+#define CIRCUIT_T_DA         4
+  int        circ_type;          /* type of the physical interface */
+  union {
+    struct isis_bcast_info bc;
+    struct isis_p2p_info p2p;
+  } u;
+  char ext_domain;               /* externalDomain   (boolean) */
+  /* 
+   * Configurables 
+   */
+  struct isis_passwd passwd;      /* Circuit rx/tx password */
+  long lsp_interval;            
+  int manual_l2_only;             /* manualL2OnlyMode (boolean) */
+  int circuit_is_type;            /* circuit is type == level of circuit
+                                   * diffrenciated from circuit type (media) */
+  u_int32_t hello_interval[2];    /* l1HelloInterval in msecs */
+  u_int16_t hello_multiplier[2];  /* l1HelloMultiplier */
+  u_int16_t csnp_interval[2];     /* level-1 csnp-interval in seconds */
+  u_int16_t psnp_interval[2];     /* level-1 psnp-interval in seconds */
+  struct metric metrics[2];       /* l1XxxMetric */
+  struct password *c_rx_passwds;  /* circuitReceivePasswords */
+  struct password *c_tc_passwd;   /* circuitTransmitPassword */
+  int ip_router;                  /* Route IP ? */
+  struct list *ip_addrs;          /* our IP addresses */
+#ifdef HAVE_IPV6
+  int ipv6_router;                /* Route IPv6 ? */
+  struct list *ipv6_link;         /* our link local IPv6 addresses */
+  struct list *ipv6_non_link;     /* our non-link local IPv6 addresses */
+#endif /* HAVE_IPV6 */
+  /* 
+   * RFC 2973 IS-IS Mesh Groups 
+   */
+#define MESH_INACTIVE 0
+#define MESH_BLOCKED  1
+#define MESH_SET      2
+  int mesh_enabled;               /* meshGroupEnabled */
+  u_int16_t mesh_group;           /* meshGroup */
+  u_int16_t upadjcount[2];
+  /*
+   * Counters as in 10589--11.2.5.9
+   */
+  u_int32_t adj_state_changes;    /* changesInAdjacencyState */
+  u_int32_t init_failures;        /* intialisationFailures */
+  u_int32_t ctrl_pdus_rxed;       /* controlPDUsReceived */
+  u_int32_t ctrl_pdus_txed;       /* controlPDUsSent */
+  u_int32_t desig_changes[2];     /* lanLxDesignatedIntermediateSystemChanges*/
+  u_int32_t rej_adjacencies;      /* rejectedAdjacencies */
+};
+
+
+void                 isis_circuit_init        (void);
+struct isis_circuit *isis_circuit_new         (void);
+struct isis_circuit *circuit_lookup_by_ifp    (struct interface *ifp, 
+                                               struct list *list);
+struct isis_circuit *circuit_scan_by_ifp      (struct interface *ifp);
+void                 isis_circuit_del         (struct isis_circuit *circuit);
+void                 isis_circuit_configure   (struct isis_circuit *circuit, 
+                                               struct isis_area *area);
+void                 isis_circuit_up          (struct isis_circuit *circuit);
+void                 isis_circuit_deconfigure (struct isis_circuit *circuit, 
+                                               struct isis_area *area);
+
+int                  isis_circuit_destroy     (struct isis_circuit *circuit);
+void                 isis_circuit_if_add      (struct isis_circuit *circuit,
+                                               struct interface *ifp);
+void                 isis_circuit_if_del      (struct isis_circuit *circuit);
+void                 circuit_update_nlpids    (struct isis_circuit *circuit);
+void                 isis_circuit_update_params (struct isis_circuit *circuit,
+                                                 struct interface *ifp);
+void                 isis_circuit_add_addr (struct isis_circuit *circuit, 
+                                            struct connected *conn);
+void                 isis_circuit_del_addr (struct isis_circuit *circuit, 
+                                            struct connected *conn);
+#endif /* _ZEBRA_ISIS_CIRCUIT_H */
diff --git a/isisd/isis_common.h b/isisd/isis_common.h
new file mode 100644
index 0000000..951e637
--- /dev/null
+++ b/isisd/isis_common.h
@@ -0,0 +1,65 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_common.h  
+ *                             some common data structures
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * Area Address
+ */ 
+struct area_addr {
+  u_char             addr_len;
+  u_char             area_addr[20];
+};
+
+struct isis_passwd {
+  u_char len;
+#define ISIS_PASSWD_TYPE_UNUSED   0
+#define ISIS_PASSWD_TYPE_CLEARTXT 1
+#define ISIS_PASSWD_TYPE_PRIVATE  255
+  u_char type;
+  u_char passwd[255];
+};
+
+/*
+ * (Dynamic) Hostname
+ * one struct for cache list
+ * one struct for LSP TLV
+ */
+struct hostname {
+  u_char namelen;
+  u_char name[255];
+};
+
+/*
+ * Supported Protocol IDs
+ */
+struct nlpids {
+  u_char count;
+  u_char nlpids[4]; /* FIXME: enough ? */ 
+};
+
+/*
+ * Flags structure for SSN and SRM flags
+ */ 
+struct flags {
+  int maxindex;
+  struct list *free_idcs;
+};
diff --git a/isisd/isis_constants.h b/isisd/isis_constants.h
new file mode 100644
index 0000000..c5b59aa
--- /dev/null
+++ b/isisd/isis_constants.h
@@ -0,0 +1,151 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_constants.h   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef ISIS_CONSTANTS_H
+#define ISIS_CONSTANTS_H
+
+/*
+ * Architectural constant values from p. 35 of ISO/IEC 10589
+ */ 
+
+#define MAX_LINK_METRIC               63 
+#define MAX_PATH_METRIC               1023
+#define ISO_SAP                       0xFE
+#define INTRADOMAIN_ROUTEING_SELECTOR 0
+#define SEQUENCE_MODULUS              4294967296
+#define RECEIVE_LSP_BUFFER_SIZE       1492
+
+/*
+ * implementation specific jitter values
+ */
+
+#define IIH_JITTER                    25  /* % */
+#define MAX_AGE_JITTER                 5  /* % */
+#define MAX_LSP_GEN_JITTER             5  /* % */
+#define CSNP_JITTER                   10  /* % */
+#define PSNP_JITTER                   10  /* % */
+
+#define RANDOM_SPREAD           100000.0
+
+/*
+ * Default values
+ * ISO - 10589
+ * Section 7.3.21 - Parameters
+ */
+#define MAX_AGE                       1200
+#define ZERO_AGE_LIFETIME             60
+#define MAX_LSP_GEN_INTERVAL          900
+#define MIN_LSP_GEN_INTERVAL          30
+#define MIN_LSP_TRANS_INTERVAL        5
+#define ISIS_MIN_LSP_LIFETIME         380
+#define CSNP_INTERVAL                 10
+#define PSNP_INTERVAL                 2
+#define ISIS_MAX_PATH_SPLITS          3
+
+#define ISIS_LEVELS                   2
+#define ISIS_LEVEL1                   1
+#define ISIS_LEVEL2                   2
+
+#define HELLO_INTERVAL                1
+#define HELLO_MINIMAL HELLO_INTERVAL
+#define HELLO_MULTIPLIER              3
+#define DEFAULT_PRIORITY              64
+/* different vendors implement different values 5-10 on average */
+#define LSP_GEN_INTERVAL_DEFAULT      10 
+#define LSP_INTERVAL                  33  /* msecs */
+#define DEFAULT_CIRCUIT_METRICS 10
+#define METRICS_UNSUPPORTED 0x80
+#define PERIODIC_SPF_INTERVAL         60 /* at the top of my head */
+#define MINIMUM_SPF_INTERVAL           5 /* .. same here          */ 
+
+/*
+ * NLPID values
+ */
+#define NLPID_IP   204
+#define NLPID_IPV6 142
+
+/*
+ * Return values for functions
+ */
+#define ISIS_OK       0
+#define ISIS_WARNING  1
+#define ISIS_ERROR    2
+#define ISIS_CRITICAL 3
+
+/*
+ * IS-IS Circuit Types
+ */
+
+#define IS_LEVEL_1       1
+#define IS_LEVEL_2       2
+#define IS_LEVEL_1_AND_2 3
+
+#define SNPA_ADDRSTRLEN 18
+#define ISIS_SYS_ID_LEN  6
+#define SYSID_STRLEN    24
+
+/*
+ * LSP bit masks
+ */
+#define LSPBIT_P   0x80
+#define LSPBIT_ATT 0x78
+#define LSPBIT_OL  0x04
+#define LSPBIT_IST 0x03
+
+/*
+ * LSP bit masking macros
+ * taken from tcpdumps
+ * print-isoclns.c
+ */
+
+#define ISIS_MASK_LSP_OL_BIT(x)            ((x)&0x4)
+#define ISIS_MASK_LSP_IS_L1_BIT(x)         ((x)&0x1)
+#define ISIS_MASK_LSP_IS_L2_BIT(x)         ((x)&0x2)
+#define ISIS_MASK_LSP_PARTITION_BIT(x)     ((x)&0x80)
+#define ISIS_MASK_LSP_ATT_BITS(x)          ((x)&0x78)
+#define ISIS_MASK_LSP_ATT_ERROR_BIT(x)     ((x)&0x40)
+#define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x)   ((x)&0x20)
+#define ISIS_MASK_LSP_ATT_DELAY_BIT(x)     ((x)&0x10)
+#define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x)   ((x)&0x8)
+
+#define LLC_LEN 3
+
+/* we need to be aware of the fact we are using ISO sized
+ * packets, using isomtu = mtu - LLC_LEN
+ */
+#define ISO_MTU(C) \
+          (C->circ_type==CIRCUIT_T_BROADCAST) ? \
+          (C->interface->mtu - LLC_LEN) : (C->interface->mtu)
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+#endif  /* ISIS_CONSTANTS_H */
+
+
+
+
+
+
+
+
diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c
new file mode 100644
index 0000000..2282bbc
--- /dev/null
+++ b/isisd/isis_csm.c
@@ -0,0 +1,186 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_csm.c
+ *                             IS-IS circuit state machine
+ * Copyright (C) 2001,2002    Sampo Saaristo
+ *                            Tampere University of Technology      
+ *                            Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "log.h"
+#include "memory.h"
+#include "if.h"
+#include "linklist.h"
+#include "command.h"
+#include "thread.h"
+#include "hash.h"
+#include "prefix.h"
+#include "stream.h"
+
+#include "isisd/dict.h"
+#include "isisd/include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_network.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_dr.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_csm.h"
+#include "isisd/isis_events.h"
+
+extern struct isis *isis;
+
+static char *csm_statestr[] = 
+{
+  "C_STATE_NA",
+  "C_STATE_INIT",
+  "C_STATE_CONF",
+  "C_STATE_UP"
+};
+
+#define STATE2STR(S) csm_statestr[S]
+
+static char *csm_eventstr[] =
+{
+  "NO_STATE",
+  "ISIS_ENABLE",
+  "IF_UP_FROM_Z",
+  "ISIS_DISABLE",
+  "IF_DOWN_FROM_Z",
+};
+
+#define EVENT2STR(E) csm_eventstr[E]
+
+
+struct isis_circuit*
+isis_csm_state_change (int event, struct isis_circuit *circuit, 
+                       void *arg)
+{
+  int old_state;
+
+  old_state = circuit ? circuit->state : C_STATE_NA;
+  
+  zlog_info ("CSM_EVENT: %s", EVENT2STR(event));
+  
+  switch (old_state) {
+  case C_STATE_NA:
+    if (circuit)
+      zlog_warn ("Non-null circuit while state C_STATE_NA");
+    switch (event) {
+    case ISIS_ENABLE:
+      circuit = isis_circuit_new ();
+      isis_circuit_configure (circuit, (struct isis_area *)arg);
+      circuit->state = C_STATE_CONF;
+      break;
+    case IF_UP_FROM_Z:
+      circuit = isis_circuit_new ();
+      isis_circuit_if_add (circuit, (struct interface *)arg);
+      listnode_add (isis->init_circ_list, circuit);
+      circuit->state = C_STATE_INIT;
+      break;
+    case ISIS_DISABLE:
+      zlog_warn ("circuit already disabled");
+    case IF_DOWN_FROM_Z:
+      zlog_warn ("circuit already disconnected");
+      break;
+    }
+    break;
+  case C_STATE_INIT:
+    switch (event) {
+    case ISIS_ENABLE:
+      isis_circuit_configure (circuit, (struct isis_area *)arg);
+      isis_circuit_up (circuit);
+      circuit->state = C_STATE_UP;
+      isis_event_circuit_state_change (circuit, 1);
+      listnode_delete (isis->init_circ_list, circuit);
+      break;
+    case IF_UP_FROM_Z:
+      zlog_warn ("circuit already connected");
+      break;
+    case ISIS_DISABLE:
+      zlog_warn ("circuit already disabled");
+      break;
+    case IF_DOWN_FROM_Z:
+      isis_circuit_if_del (circuit);
+      listnode_delete (isis->init_circ_list, circuit);
+      isis_circuit_del (circuit);
+      break;
+    }
+    break;
+  case C_STATE_CONF:
+    switch (event) {
+    case ISIS_ENABLE:
+      zlog_warn ("circuit already enabled");
+      break;
+    case IF_UP_FROM_Z:
+      isis_circuit_if_add (circuit, (struct interface *)arg);
+      isis_circuit_up (circuit);
+      circuit->state = C_STATE_UP;
+      isis_event_circuit_state_change (circuit, 1);
+      break;
+    case ISIS_DISABLE:
+      isis_circuit_deconfigure (circuit, (struct isis_area *)arg);
+      isis_circuit_del (circuit);
+      break;
+    case IF_DOWN_FROM_Z:
+      zlog_warn ("circuit already disconnected");
+      break;
+    }
+    break;
+  case C_STATE_UP:
+    switch (event) {
+    case ISIS_ENABLE:
+      zlog_warn ("circuit already configured");
+      break;
+    case IF_UP_FROM_Z:
+      zlog_warn ("circuit already connected");
+      break;
+    case ISIS_DISABLE:
+      isis_circuit_deconfigure (circuit, (struct isis_area *)arg);
+      listnode_add (isis->init_circ_list, circuit);
+      circuit->state = C_STATE_INIT;
+      isis_event_circuit_state_change (circuit, 0);
+      break;
+    case IF_DOWN_FROM_Z:
+      isis_circuit_if_del (circuit);
+      circuit->state = C_STATE_CONF;
+      isis_event_circuit_state_change (circuit, 0);
+      break;
+    }
+    break;
+    
+  default:
+    zlog_warn ("Invalid circuit state %d", old_state);
+  }
+  
+  zlog_info ("CSM_STATE_CHANGE: %s -> %s ", STATE2STR (old_state), 
+             circuit ? STATE2STR (circuit->state) : STATE2STR (C_STATE_NA));
+
+  return circuit;
+}
+
+
+
diff --git a/isisd/isis_csm.h b/isisd/isis_csm.h
new file mode 100644
index 0000000..23cc215
--- /dev/null
+++ b/isisd/isis_csm.h
@@ -0,0 +1,47 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_csm.h
+ *                             IS-IS circuit state machine
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef _ZEBRA_ISIS_CSM_H
+#define _ZEBRA_ISIS_CSM_H
+
+/*
+ * Circuit states
+ */
+#define C_STATE_NA   0
+#define C_STATE_INIT 1 /* Connected to interface */
+#define C_STATE_CONF 2 /* Configured for ISIS    */
+#define C_STATE_UP   3 /* CONN | CONF            */ 
+
+/*
+ * Circuit events
+ */
+#define ISIS_ENABLE    1
+#define IF_UP_FROM_Z   2
+#define ISIS_DISABLE   3
+#define IF_DOWN_FROM_Z 4
+
+struct isis_circuit *isis_csm_state_change (int event, 
+                                            struct isis_circuit *circuit, 
+                                            void *arg);
+
+#endif /* _ZEBRA_ISIS_CSM_H */
diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c
new file mode 100644
index 0000000..5b7d23e
--- /dev/null
+++ b/isisd/isis_dr.c
@@ -0,0 +1,373 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_dr.c
+ *                             IS-IS designated router related routines   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "log.h"
+#include "hash.h"
+#include "thread.h"
+#include "linklist.h"
+#include "vty.h"
+#include "stream.h"
+#include "if.h"
+
+#include "isisd/dict.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_dr.h"
+#include "isisd/isis_events.h"
+
+extern struct isis *isis;
+extern struct thread_master *master;
+
+char *
+isis_disflag2string (int disflag) {
+
+  switch (disflag) {
+    case ISIS_IS_NOT_DIS:
+      return "is not DIS";
+    case ISIS_IS_DIS:
+      return "is DIS";
+    case ISIS_WAS_DIS:
+      return "was DIS";
+  default:
+    return "unknown DIS state";
+  }
+  return NULL; /* not reached */
+}
+
+
+
+int
+isis_run_dr_l1 (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  if (circuit->u.bc.run_dr_elect[0])
+    zlog_warn ("isis_run_dr(): run_dr_elect already set for l1");
+  
+  circuit->u.bc.run_dr_elect[0] = 1;
+    
+  return ISIS_OK;
+}
+
+int
+isis_run_dr_l2 (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  if (circuit->u.bc.run_dr_elect[1])
+    zlog_warn ("isis_run_dr(): run_dr_elect already set for l2");
+  
+  
+  circuit->u.bc.run_dr_elect[1] = 1;
+    
+  return ISIS_OK;
+}
+
+int
+isis_check_dr_change (struct isis_adjacency *adj, int level)
+{
+  int i;
+
+  if ( adj->dis_record[level-1].dis != 
+       adj->dis_record[(1*ISIS_LEVELS) + level - 1].dis) 
+    /* was there a DIS state transition ? */ 
+    {
+      adj->dischanges[level-1]++;
+      /* ok rotate the history list through */
+      for (i = DIS_RECORDS - 1; i > 0; i--) 
+	{
+	  adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis = 
+            adj->dis_record[((i-1) * ISIS_LEVELS) + level - 1].dis;
+	  adj->dis_record[(i * ISIS_LEVELS) + level - 1].last_dis_change = 
+            adj->dis_record[((i-1) * ISIS_LEVELS) + level - 1].last_dis_change;
+	}
+    }
+  return ISIS_OK;
+}
+
+int 
+isis_dr_elect (struct isis_circuit *circuit, int level)
+{
+  struct list *adjdb;
+  struct listnode *node;
+  struct isis_adjacency *adj, *adj_dr = NULL;
+  struct list *list = list_new ();
+  u_char own_prio;
+  int biggest_prio = -1;
+  int cmp_res, retval = ISIS_OK;
+  
+  own_prio = circuit->u.bc.priority[level - 1];
+  adjdb = circuit->u.bc.adjdb[level - 1];
+
+  if (!adjdb) {
+    zlog_warn ("isis_dr_elect() adjdb == NULL");
+    retval = ISIS_WARNING;
+    list_delete (list);
+    goto out;
+  }
+  isis_adj_build_up_list (adjdb, list);
+
+  /*
+   * Loop the adjacencies and find the one with the biggest priority
+   */
+  for (node = listhead (list); node; nextnode (node)) {
+    adj = getdata (node);
+    /* clear flag for show output */
+    adj->dis_record[level-1].dis = ISIS_IS_NOT_DIS;  
+    adj->dis_record[level-1].last_dis_change = time (NULL);
+
+    if (adj->prio[level-1] > biggest_prio) {
+      biggest_prio = adj->prio[level-1];
+      adj_dr = adj;
+    } else if (adj->prio[level-1] == biggest_prio) {
+      /*
+       * Comparison of MACs breaks a tie
+       */
+      if (adj_dr) {
+        cmp_res = memcmp (adj_dr->snpa, adj->snpa, ETH_ALEN);
+        if (cmp_res < 0) {
+          adj_dr = adj;
+	}
+        if (cmp_res == 0)
+          zlog_warn ("isis_dr_elect(): multiple adjacencies with same SNPA"); 
+      } else {
+        adj_dr = adj;
+      }
+    }
+  }
+  
+  if (!adj_dr) {
+    /*
+     * Could not find the DR - means we are alone and thus the DR
+     */
+    if ( !circuit->u.bc.is_dr[level - 1]) {
+      list_delete (list);
+      list = NULL;
+      return isis_dr_commence (circuit, level);
+    }
+    goto out;
+  }
+
+  /*
+   * Now we have the DR adjacency, compare it to self
+   */
+  if (adj_dr->prio[level-1] < own_prio || (adj_dr->prio[level-1] == own_prio &&
+                                  memcmp (adj_dr->snpa, circuit->u.bc.snpa, 
+                                          ETH_ALEN) < 0)) {
+    if (!circuit->u.bc.is_dr[level - 1]) {
+      /*
+       * We are the DR -> commence
+       */
+      list_delete (list);
+      return isis_dr_commence (circuit, level);
+    }
+  } else {
+
+    /* ok we have found the DIS - lets mark the adjacency */
+    /* set flag for show output */
+    adj_dr->dis_record[level - 1].dis = ISIS_IS_DIS; 
+    adj_dr->dis_record[level - 1].last_dis_change = time(NULL);
+
+    /* now loop through a second time to check if there has been a DIS change
+     * if yes rotate the history log
+     */
+
+    for (node = listhead (list); node; nextnode (node)) {
+      adj = getdata (node);
+      isis_check_dr_change(adj, level);
+    }
+
+    /*
+     * We are not DR - if we were -> resign
+     */
+
+    if (circuit->u.bc.is_dr[level - 1]) {
+      list_delete (list);
+      return isis_dr_resign (circuit, level);
+    }
+  }
+ out:
+  if (list)
+    list_delete (list);
+  return retval;
+}
+
+int 
+isis_dr_resign (struct isis_circuit *circuit, int level)
+{
+  u_char id[ISIS_SYS_ID_LEN + 2];
+      
+  zlog_info ("isis_dr_resign l%d", level);
+
+  circuit->u.bc.is_dr[level - 1] = 0;
+  circuit->u.bc.run_dr_elect[level - 1] = 0; 
+  if (circuit->u.bc.t_run_dr[level - 1]) {
+    thread_cancel (circuit->u.bc.t_run_dr[level - 1]);
+    circuit->u.bc.t_run_dr[level - 1] = NULL;
+  }
+  if (circuit->u.bc.t_refresh_pseudo_lsp[level - 1]) {
+    thread_cancel (circuit->u.bc.t_refresh_pseudo_lsp[level - 1]);
+    circuit->u.bc.t_refresh_pseudo_lsp[level - 1] = NULL;
+  }
+  
+  memcpy (id, isis->sysid, ISIS_SYS_ID_LEN);
+  LSP_PSEUDO_ID(id) = circuit->circuit_id;
+  LSP_FRAGMENT(id) = 0;
+  lsp_purge_dr (id, circuit, level);
+
+  if (level == 1) {
+    memset (circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1);
+    
+    if (circuit->t_send_csnp[0])
+      thread_cancel (circuit->t_send_csnp[0]);    
+    
+    circuit->u.bc.t_run_dr[0] =
+      thread_add_timer (master, isis_run_dr_l1, circuit,
+                        2 * circuit->hello_interval[1]);    
+
+    circuit->t_send_psnp[0] = 
+      thread_add_timer (master,
+                        send_l1_psnp,
+                        circuit,
+                        isis_jitter (circuit->psnp_interval[level - 1],
+                                     PSNP_JITTER));
+  } else {
+    memset (circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1);
+
+    if (circuit->t_send_csnp[0])
+      thread_cancel (circuit->t_send_csnp[0]);
+
+    circuit->u.bc.t_run_dr[1] =
+      thread_add_timer (master, isis_run_dr_l2, circuit,
+                        2 * circuit->hello_interval[1]);    
+    circuit->t_send_psnp[1] = 
+      thread_add_timer (master,
+                        send_l2_psnp,
+                        circuit,
+                        isis_jitter (circuit->psnp_interval[level - 1],
+                                     PSNP_JITTER));
+  }
+  
+  thread_add_event (master, isis_event_dis_status_change, circuit, 0);
+
+  return ISIS_OK;
+}
+
+int 
+isis_dr_commence (struct isis_circuit *circuit, int level)
+{
+  u_char old_dr[ISIS_SYS_ID_LEN + 2];
+  
+  zlog_info ("isis_dr_commence l%d", level);
+
+  /* Lets keep a pause in DR election */
+  circuit->u.bc.run_dr_elect[level - 1] = 0;
+  if (level == 1) 
+    circuit->u.bc.t_run_dr[0] = 
+      thread_add_timer (master, isis_run_dr_l1, circuit,
+			2 * circuit->hello_multiplier[0] * 
+			circuit->hello_interval[0]); 
+  else 
+    circuit->u.bc.t_run_dr[1] = 
+      thread_add_timer (master, isis_run_dr_l2, circuit,
+			2 * circuit->hello_multiplier[1] * 
+			circuit->hello_interval[1]);	      	
+  circuit->u.bc.is_dr[level - 1] = 1;
+
+  if (level == 1) {
+    memcpy (old_dr, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
+    LSP_FRAGMENT (old_dr) = 0;
+    if (LSP_PSEUDO_ID(old_dr)) {
+      /* there was a dr elected, purge its LSPs from the db */
+      lsp_purge_dr (old_dr, circuit, level);
+    }
+    memcpy (circuit->u.bc.l1_desig_is, isis->sysid, ISIS_SYS_ID_LEN);
+    *(circuit->u.bc.l1_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id;
+    
+    assert (circuit->circuit_id); /* must be non-zero */
+    /*    if (circuit->t_send_l1_psnp)
+          thread_cancel (circuit->t_send_l1_psnp); */
+    lsp_l1_pseudo_generate (circuit);
+
+    circuit->u.bc.t_run_dr[0] =
+      thread_add_timer (master, isis_run_dr_l1, circuit,
+                        2 * circuit->hello_interval[0]);
+
+    circuit->t_send_csnp[0] = thread_add_timer (master,
+                                                send_l1_csnp,
+                                                circuit, 
+                                                isis_jitter 
+                                              (circuit->csnp_interval[level-1],
+                                               CSNP_JITTER));
+  } else {
+    memcpy (old_dr, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
+    LSP_FRAGMENT (old_dr) = 0;
+    if (LSP_PSEUDO_ID(old_dr)) {
+      /* there was a dr elected, purge its LSPs from the db */
+      lsp_purge_dr (old_dr, circuit, level);
+    }
+    memcpy (circuit->u.bc.l2_desig_is, isis->sysid, ISIS_SYS_ID_LEN);
+    *(circuit->u.bc.l2_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id;
+    
+    assert (circuit->circuit_id); /* must be non-zero */
+    /*    if (circuit->t_send_l1_psnp)
+          thread_cancel (circuit->t_send_l1_psnp); */
+    lsp_l2_pseudo_generate (circuit);
+
+    circuit->u.bc.t_run_dr[1] =
+      thread_add_timer (master, isis_run_dr_l2, circuit,
+                        2 * circuit->hello_interval[1]);    
+
+    circuit->t_send_csnp[1] = 
+      thread_add_timer (master,
+                        send_l2_csnp,
+                        circuit, 
+                        isis_jitter (circuit->csnp_interval[level-1],
+                                     CSNP_JITTER));
+        
+  } 
+
+  thread_add_event (master, isis_event_dis_status_change, circuit, 0);
+  
+  return ISIS_OK;
+}
+
diff --git a/isisd/isis_dr.h b/isisd/isis_dr.h
new file mode 100644
index 0000000..73d9cd3
--- /dev/null
+++ b/isisd/isis_dr.h
@@ -0,0 +1,42 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_dr.h
+ *                             IS-IS designated router related routines   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_DR_H
+#define _ZEBRA_ISIS_DR_H
+
+int isis_run_dr_l1 (struct thread *thread);
+int isis_run_dr_l2 (struct thread *thread);
+int isis_dr_elect (struct isis_circuit *circuit, int level);
+int isis_dr_resign (struct isis_circuit *circuit, int level);
+int isis_dr_commence (struct isis_circuit *circuit, int level);
+char *isis_disflag2string (int disflag);
+
+enum isis_dis_state {     
+  ISIS_IS_NOT_DIS,
+  ISIS_IS_DIS,
+  ISIS_WAS_DIS,
+  ISIS_UNKNOWN_DIS
+};
+
+#endif /* _ZEBRA_ISIS_DR_H */
+
diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c
new file mode 100644
index 0000000..9e151d0
--- /dev/null
+++ b/isisd/isis_dynhn.c
@@ -0,0 +1,124 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_dynhn.c
+ *                             Dynamic hostname cache
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <time.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "vty.h"
+#include "linklist.h"
+#include "memory.h"
+#include "log.h"
+#include "stream.h"
+#include "command.h"
+#include "if.h"
+
+#include "isisd/dict.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_dynhn.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_constants.h"
+
+extern struct isis *isis;
+extern struct host host;
+
+struct list *dyn_cache = NULL;
+
+void
+dyn_cache_init (void)
+{
+  dyn_cache = list_new ();
+  
+  return;
+}
+
+struct isis_dynhn *dynhn_find_by_id (u_char * id)
+{
+  struct listnode *node = NULL;
+  struct isis_dynhn *dyn = NULL;
+
+  for (node = listhead (dyn_cache); node; nextnode (node)) {
+    dyn = getdata (node);
+    if (memcmp (dyn->id, id, ISIS_SYS_ID_LEN) == 0)
+      return dyn;
+  }
+  
+  return NULL;
+}
+
+void
+isis_dynhn_insert (u_char *id, struct hostname *hostname, int level)
+{
+  struct isis_dynhn *dyn;
+
+  dyn = dynhn_find_by_id (id);
+  if (dyn) {
+    memcpy (&dyn->name, hostname, hostname->namelen + 1);
+    memcpy (dyn->id, id, ISIS_SYS_ID_LEN);
+    dyn->refresh = time (NULL);
+    return;
+  }
+  dyn = XMALLOC (MTYPE_ISIS_DYNHN, sizeof (struct isis_dynhn));
+  if (!dyn) {
+    zlog_warn ("isis_dynhn_insert(): out of memory!");
+    return;
+  }
+  memset (dyn,0,sizeof(struct isis_dynhn));
+  /* we also copy the length */
+  memcpy (&dyn->name, hostname, hostname->namelen + 1); 
+  memcpy (dyn->id, id, ISIS_SYS_ID_LEN);
+  dyn->refresh = time (NULL);
+  dyn->level = level;
+  
+  listnode_add (dyn_cache, dyn);
+
+  return;
+}
+
+/*
+ * Level  System ID      Dynamic Hostname  (notag)
+ *  2     0000.0000.0001 foo-gw
+ *  2     0000.0000.0002 bar-gw
+ *      * 0000.0000.0004 this-gw
+ */
+void  dynhn_print_all (struct vty *vty) 
+{
+  struct listnode *node;
+  struct isis_dynhn *dyn;
+
+  vty_out (vty, "Level  System ID      Dynamic Hostname%s", VTY_NEWLINE);
+  for (node = listhead (dyn_cache); node; nextnode (node)) {
+    dyn = getdata (node);
+    vty_out (vty, "%-7d", dyn->level);
+    vty_out (vty, "%-15s%-15s%s", sysid_print (dyn->id), dyn->name.name, 
+	     VTY_NEWLINE);
+  }
+  
+  vty_out (vty,  "     * %s %s%s", sysid_print (isis->sysid), host.name, 
+	   VTY_NEWLINE);
+  return;
+}
+
diff --git a/isisd/isis_dynhn.h b/isisd/isis_dynhn.h
new file mode 100644
index 0000000..2a7f3ec
--- /dev/null
+++ b/isisd/isis_dynhn.h
@@ -0,0 +1,42 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_dynhn.h
+ *                             Dynamic hostname cache
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef _ZEBRA_ISIS_DYNHN_H
+#define _ZEBRA_ISIS_DYNHN_H
+
+struct isis_dynhn {
+  u_char id[ISIS_SYS_ID_LEN];
+  struct hostname name;
+  time_t refresh;
+  int level;
+};
+
+void dyn_cache_init (void);
+void isis_dynhn_insert (u_char *id, struct hostname *hostname, int level);
+struct isis_dynhn *dynhn_find_by_id (u_char * id);
+void  dynhn_print_all (struct vty *vty);
+
+#endif /* _ZEBRA_ISIS_DYNHN_H */
+
+
+
+
diff --git a/isisd/isis_events.c b/isisd/isis_events.c
new file mode 100644
index 0000000..aada395
--- /dev/null
+++ b/isisd/isis_events.c
@@ -0,0 +1,336 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_events.h   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "log.h"
+#include "memory.h"
+#include "if.h"
+#include "linklist.h"
+#include "command.h"
+#include "thread.h"
+#include "hash.h"
+#include "prefix.h"
+#include "stream.h"
+
+#include "isisd/dict.h"
+#include "isisd/include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_network.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_dr.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_csm.h"
+#include "isisd/isis_events.h"
+#include "isisd/isis_spf.h"
+
+extern struct thread_master *master;
+extern struct isis *isis;
+
+/* debug isis-spf spf-events 
+ 4w4d: ISIS-Spf (tlt): L2 SPF needed, new adjacency, from 0x609229F4
+ 4w4d: ISIS-Spf (tlt): L2, 0000.0000.0042.01-00 TLV contents changed, code 0x2
+ 4w4d: ISIS-Spf (tlt): L2, new LSP 0 DEAD.BEEF.0043.00-00
+ 4w5d: ISIS-Spf (tlt): L1 SPF needed, periodic SPF, from 0x6091C844
+ 4w5d: ISIS-Spf (tlt): L2 SPF needed, periodic SPF, from 0x6091C844
+*/
+
+void 
+isis_event_circuit_state_change (struct isis_circuit *circuit, int up)
+{
+  struct isis_area *area;
+  
+  area = circuit->area;
+  assert (area);
+  area->circuit_state_changes++;
+  
+  if (isis->debugs & DEBUG_EVENTS) 
+    zlog_info ("ISIS-Evt (%s) circuit %s", circuit->area->area_tag, 
+	       up ? "up" : "down");
+  
+  /*
+   * Regenerate LSPs this affects
+   */
+  lsp_regenerate_schedule (area);
+
+  return;
+}
+
+void 
+isis_event_system_type_change (struct isis_area *area, int newtype)
+{
+  struct listnode *node;
+  struct isis_circuit *circuit;
+
+  if (isis->debugs & DEBUG_EVENTS) 
+    zlog_info ("ISIS-Evt (%s) system type change %s -> %s", area->area_tag, 
+	       circuit_t2string (area->is_type), circuit_t2string (newtype));
+  
+  if (area->is_type == newtype)
+    return; /* No change */
+  
+  switch (area->is_type) {
+  case IS_LEVEL_1:
+    if (area->lspdb[1] == NULL)
+      area->lspdb[1] = lsp_db_init (); 
+    lsp_l2_generate (area);
+    break;
+  case IS_LEVEL_1_AND_2:
+    if (newtype == IS_LEVEL_1) {
+      lsp_db_destroy (area->lspdb[1]);
+    } 
+    else {
+      lsp_db_destroy (area->lspdb[0]);
+    } 
+    break;
+  case IS_LEVEL_2:
+    if (area->lspdb[0] == NULL)
+      area->lspdb[0] = lsp_db_init (); 
+    lsp_l1_generate (area);
+    break;
+  default:
+    break;
+  }
+  
+  area->is_type = newtype;
+  for (node = listhead (area->circuit_list); node; nextnode (node)) {
+    circuit = getdata (node);
+    isis_event_circuit_type_change (circuit, newtype);
+  }
+
+  spftree_area_init (area);
+  lsp_regenerate_schedule (area);
+
+  return;
+}
+
+
+
+void 
+isis_event_area_addr_change (struct isis_area *area)
+{
+
+}
+
+void
+circuit_commence_level (struct isis_circuit *circuit, int level)
+{
+  uint32_t interval;
+
+  if (level == 1) {
+    circuit->t_send_psnp[0] = thread_add_timer (master, send_l1_psnp,
+						circuit,
+						isis_jitter
+						(circuit->psnp_interval[0], 
+						 PSNP_JITTER));
+    if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+      interval = circuit->hello_multiplier[0] * (circuit->hello_interval[0]); 
+      circuit->u.bc.t_run_dr[0] =  thread_add_timer (master, isis_run_dr_l1, 
+						     circuit, interval);
+      
+      circuit->u.bc.t_send_lan_hello[0] = 
+	thread_add_timer (master, 
+                          send_lan_l1_hello,
+                          circuit, 
+                          isis_jitter 
+                          (circuit->hello_interval[0], IIH_JITTER));
+      circuit->u.bc.lan_neighs[0] = list_new ();
+    }
+  } else {
+    circuit->t_send_psnp[1] = thread_add_timer (master, send_l2_psnp,
+						circuit,
+						isis_jitter
+						(circuit->psnp_interval[1], 
+						 PSNP_JITTER));
+    if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+      interval = circuit->hello_multiplier[1] * (circuit->hello_interval[1]); 
+      circuit->u.bc.t_run_dr[1] =  thread_add_timer (master, isis_run_dr_l2, 
+						     circuit, interval);
+      
+      circuit->u.bc.t_send_lan_hello[1] = 
+	thread_add_timer (master, 
+                          send_lan_l2_hello,
+                          circuit, 
+                          isis_jitter 
+                          (circuit->hello_interval[1], IIH_JITTER));
+      circuit->u.bc.lan_neighs[1] = list_new ();
+    }
+  }
+  
+  return;
+}
+
+void
+circuit_resign_level (struct isis_circuit *circuit, int level)
+{
+  int idx = level - 1;
+ 
+  if (circuit->t_send_csnp[idx])
+      thread_cancel (circuit->t_send_csnp[idx]);
+  circuit->t_send_csnp[idx] = NULL;
+
+  if (circuit->t_send_psnp[idx])
+    thread_cancel (circuit->t_send_psnp[idx]);
+  circuit->t_send_psnp[level - 1] = NULL;
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    if (circuit->u.bc.t_send_lan_hello[idx])
+      thread_cancel (circuit->u.bc.t_send_lan_hello[idx]);
+    circuit->u.bc.t_send_lan_hello[idx] = NULL;
+    if (circuit->u.bc.t_run_dr[idx])
+	thread_cancel (circuit->u.bc.t_run_dr[idx]);
+    circuit->u.bc.t_run_dr[idx] = NULL;
+    circuit->u.bc.run_dr_elect[idx] = 0;
+  }
+  
+  return;
+}
+
+void 
+isis_event_circuit_type_change (struct isis_circuit *circuit, int newtype) 
+{
+  
+  if (isis->debugs & DEBUG_EVENTS) 
+    zlog_info ("ISIS-Evt (%s) circuit type change %s -> %s", 
+	       circuit->area->area_tag, 
+	       circuit_t2string (circuit->circuit_is_type), 
+	       circuit_t2string (newtype));
+
+  if (circuit->circuit_is_type == newtype)
+    return; /* No change */
+
+  if (!(newtype & circuit->area->is_type)) {
+    zlog_err ("ISIS-Evt (%s) circuit type change - invalid level %s because"
+	      " area is %s", circuit->area->area_tag, 
+	      circuit_t2string (newtype), 
+	      circuit_t2string (circuit->area->is_type));
+    return;
+  }
+    
+  switch (circuit->circuit_is_type) {
+  case IS_LEVEL_1:
+    if (newtype == IS_LEVEL_2)
+      circuit_resign_level (circuit, 1);
+    circuit_commence_level (circuit, 2);
+    break;
+  case IS_LEVEL_1_AND_2:
+    if (newtype == IS_LEVEL_1)
+      circuit_resign_level (circuit, 2);
+    else 
+      circuit_resign_level (circuit, 1);
+    break;
+  case IS_LEVEL_2:
+    if (newtype == IS_LEVEL_1)
+      circuit_resign_level (circuit, 2);
+    circuit_commence_level (circuit, 1);
+    break;
+  default:
+    break;
+  }
+  
+  circuit->circuit_is_type = newtype;
+  lsp_regenerate_schedule (circuit->area);
+
+  return;
+}
+
+ /* 04/18/2002 by Gwak. */
+ /**************************************************************************
+  *
+  * EVENTS for LSP generation
+  *
+  * 1) an Adajacency or Circuit Up/Down event
+  * 2) a chnage in Circuit metric
+  * 3) a change in Reachable Address metric
+  * 4) a change in manualAreaAddresses
+  * 5) a change in systemID
+  * 6) a change in DIS status
+  * 7) a chnage in the waiting status
+  *
+  * ***********************************************************************
+  *
+  * current support event
+  *
+  * 1) Adjacency Up/Down event
+  * 6) a change in DIS status
+  *
+  * ***********************************************************************/
+
+void 
+isis_event_adjacency_state_change (struct isis_adjacency *adj, int newstate)
+{
+  /* adjacency state change event. 
+   * - the only proto-type was supported */
+  
+  /* invalid arguments */ 
+  if ( !adj || !adj->circuit || !adj->circuit->area ) return;     
+  
+  zlog_info ("ISIS-Evt (%s) Adjacency State change", 
+	     adj->circuit->area->area_tag );
+  
+  /* LSP generation again */
+  lsp_regenerate_schedule (adj->circuit->area);
+
+  return;
+}
+
+/* events supporting code */
+
+int
+isis_event_dis_status_change (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  
+  circuit = THREAD_ARG (thread);
+  
+  /* invalid arguments */
+  if (!circuit || !circuit->area) return 0;
+  
+  zlog_info ("ISIS-Evt (%s) DIS status change", circuit->area->area_tag);
+
+  /* LSP generation again */
+  lsp_regenerate_schedule (circuit->area);
+  
+  return 0;
+}
+
+
+void 
+isis_event_auth_failure (char *area_tag, char *error_string, char *sysid) 
+{
+  zlog_info ("ISIS-Evt (%s) Authentication failure %s from %s",
+	     area_tag, error_string, sysid_print (sysid));
+  
+  return;
+}
+
diff --git a/isisd/isis_events.h b/isisd/isis_events.h
new file mode 100644
index 0000000..75dd92e
--- /dev/null
+++ b/isisd/isis_events.h
@@ -0,0 +1,54 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_events.h   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef _ZEBRA_ISIS_EVENTS_H
+#define _ZEBRA_ISIS_EVENTS_H
+
+/*
+ * Events related to area
+ */
+void isis_event_system_type_change (struct isis_area *area, int newtype);
+void isis_event_area_addr_change (struct isis_area *area);
+
+/*
+ * Events related to circuit
+ */
+void isis_event_circuit_state_change (struct isis_circuit *circuit, int state);
+void isis_event_circuit_type_change (struct isis_circuit *circuit, 
+                                     int newtype);
+/*
+ * Events related to adjacencies
+ */
+void isis_event_adjacency_state_change(struct isis_adjacency *adj, 
+                                       int newstate);
+
+int isis_event_dis_status_change (struct thread *thread);
+
+/*
+ * Error events
+ */
+#define AUTH_ERROR_TYPE_LSP   3
+#define AUTH_ERROR_TYPE_SNP   2
+#define AUTH_ERROR_TYPE_HELLO 1
+void isis_event_auth_failure (char *area_tag, char *error_string, char *sysid);
+
+#endif /* _ZEBRA_ISIS_EVENTS_H */
+
diff --git a/isisd/isis_flags.c b/isisd/isis_flags.c
new file mode 100644
index 0000000..716bee0
--- /dev/null
+++ b/isisd/isis_flags.c
@@ -0,0 +1,71 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_flags.c
+ *                             Routines for manipulation of SSN and SRM flags
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+#include <zebra.h>
+#include "log.h"
+#include "linklist.h"
+
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_flags.h"
+
+int
+flags_get_index (struct flags *flags) 
+{
+  struct listnode *node;
+  int index;
+
+  if (flags->free_idcs == NULL || flags->free_idcs->count == 0) {
+    flags->maxindex++;
+    index = flags->maxindex;
+  } else {
+    node = listhead (flags->free_idcs);
+    index = (int) getdata (node);
+    listnode_delete (flags->free_idcs, (void *)index);
+  }
+  
+  return index;
+}
+
+void 
+flags_free_index (struct flags *flags, int index) 
+{
+  if (flags->free_idcs == NULL) {
+    flags->free_idcs = list_new ();
+  }
+  
+  listnode_add (flags->free_idcs, (void *)index);
+  
+  return;
+}
+
+int  
+flags_any_set (u_int32_t *flags)
+{
+
+  u_int32_t zero[ISIS_MAX_CIRCUITS]; 
+  memset (zero, 0x00, ISIS_MAX_CIRCUITS*4); 
+
+  return bcmp(flags, zero, ISIS_MAX_CIRCUITS*4);
+}
diff --git a/isisd/isis_flags.h b/isisd/isis_flags.h
new file mode 100644
index 0000000..66b9484
--- /dev/null
+++ b/isisd/isis_flags.h
@@ -0,0 +1,58 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_flags.h
+ *                             Routines for manipulation of SSN and SRM flags
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_FLAGS_H
+#define _ZEBRA_ISIS_FLAGS_H
+
+/* The grand plan is to support 1024 circuits so we have 32*32 bit flags
+ * the support will be achived using the newest drafts */
+#define ISIS_MAX_CIRCUITS 32 /* = 1024 */ /*FIXME:defined in lsp.h as well*/
+
+struct flags *new_flags        (int size);
+int           flags_get_index  (struct flags *flags);
+void          flags_free_index (struct flags *flags, int index);
+
+int  flags_any_set (u_int32_t *flags);
+
+#define ISIS_SET_FLAG(F,C) \
+        F[C->idx>>5] |= (1<<(C->idx & 0x1F));
+
+#define ISIS_CLEAR_FLAG(F,C) \
+        F[C->idx>>5] &= ~(1<<(C->idx & 0x1F));
+
+#define ISIS_CHECK_FLAG(F, C)  F[(C)->idx>>5] & (1<<(C->idx & 0x1F))
+
+/* sets all u_32int_t flags to 1 */
+#define ISIS_FLAGS_SET_ALL(FLAGS) \
+        memset(FLAGS,0xFF,ISIS_MAX_CIRCUITS*4);
+
+#define ISIS_FLAGS_CLEAR_ALL(FLAGS) \
+        memset(FLAGS,0x00,ISIS_MAX_CIRCUITS*4);
+
+#endif /* _ZEBRA_ISIS_FLAGS_H */
+
+
+
+
+
+
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
new file mode 100644
index 0000000..6bfb0fd
--- /dev/null
+++ b/isisd/isis_lsp.c
@@ -0,0 +1,2419 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_lsp.c
+ *                             LSP processing
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "linklist.h"
+#include "thread.h"
+#include "vty.h"
+#include "stream.h"
+#include "memory.h"
+#include "log.h"
+#include "prefix.h"
+#include "command.h"
+#include "hash.h"
+#include "if.h"
+
+#include "isisd/dict.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_dynhn.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_flags.h"
+#include "isisd/iso_checksum.h"
+#include "isisd/isis_csm.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_spf.h"
+
+#ifdef TOPOLOGY_GENERATE
+#include "spgrid.h"
+#endif
+
+#define LSP_MEMORY_PREASSIGN 
+
+extern struct isis *isis;
+extern struct thread_master *master;
+extern struct host host;
+
+int 
+lsp_id_cmp (u_char *id1, u_char *id2)
+{  
+  return memcmp (id1, id2, ISIS_SYS_ID_LEN + 2);
+}
+
+dict_t *
+lsp_db_init (void) 
+{
+  dict_t *dict;
+  
+  dict = dict_create (DICTCOUNT_T_MAX, (dict_comp_t)lsp_id_cmp);
+  
+  return dict;
+}
+
+struct isis_lsp *
+lsp_search (u_char *id, dict_t *lspdb)
+{
+  dnode_t *node;
+
+#ifdef EXTREME_DEBUG 
+  dnode_t *dn;
+
+  zlog_warn("searching db");
+  for (dn = dict_first(lspdb); dn; dn = dict_next(lspdb, dn)) {
+    zlog_warn("%s\t%pX", rawlspid_print((char *) dnode_getkey(dn)), 
+              dnode_get(dn));
+  }
+#endif /* EXTREME DEBUG */
+
+  node = dict_lookup (lspdb, id);
+  
+  if (node)
+    return (struct isis_lsp *)dnode_get (node);
+
+  return NULL;
+}
+
+void
+lsp_clear_data (struct isis_lsp *lsp)
+{
+  if (!lsp)
+    return;
+ 
+  if (lsp->own_lsp) {
+    if (lsp->tlv_data.nlpids)
+      XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.nlpids);
+    if (lsp->tlv_data.hostname)
+      XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.hostname);
+  }
+  if (lsp->tlv_data.is_neighs)
+    list_delete (lsp->tlv_data.is_neighs);
+  if (lsp->tlv_data.area_addrs)
+    list_delete (lsp->tlv_data.area_addrs);
+  if (lsp->tlv_data.es_neighs)
+    list_delete (lsp->tlv_data.es_neighs);
+  if (lsp->tlv_data.ipv4_addrs)
+    list_delete (lsp->tlv_data.ipv4_addrs);
+  if (lsp->tlv_data.ipv4_int_reachs)
+    list_delete (lsp->tlv_data.ipv4_int_reachs);
+  if (lsp->tlv_data.ipv4_ext_reachs)
+    list_delete (lsp->tlv_data.ipv4_ext_reachs);
+#ifdef HAVE_IPV6
+  if (lsp->tlv_data.ipv6_addrs)
+    list_delete (lsp->tlv_data.ipv6_addrs);
+  if (lsp->tlv_data.ipv6_reachs)
+    list_delete (lsp->tlv_data.ipv6_reachs);
+#endif /* HAVE_IPV6 */
+
+  memset (&lsp->tlv_data, 0, sizeof (struct tlvs));
+
+  return;
+}
+
+void
+lsp_destroy (struct isis_lsp *lsp)
+{
+  if (!lsp)
+    return;
+  
+  lsp_clear_data (lsp);
+  
+  if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags) {
+      list_delete (lsp->lspu.frags);
+  }
+  
+  if (lsp->pdu)
+    stream_free (lsp->pdu);
+  XFREE (MTYPE_ISIS_LSP, lsp);
+}
+
+void 
+lsp_db_destroy (dict_t *lspdb)
+{
+  dnode_t *dnode, *next;
+  struct isis_lsp *lsp;
+  
+  dnode = dict_first (lspdb);
+  while (dnode) {
+    next = dict_next (lspdb, dnode);
+    lsp = dnode_get (dnode);
+    lsp_destroy (lsp);
+    dict_delete_free (lspdb, dnode);
+    dnode = next;
+  }
+  
+  dict_free (lspdb);
+  
+  return;
+}
+
+/*
+ * Remove all the frags belonging to the given lsp
+ */
+void
+lsp_remove_frags (struct list *frags, dict_t *lspdb)
+{
+  dnode_t *dnode;
+  struct listnode *lnode;
+  struct isis_lsp *lsp;
+
+  for (lnode = listhead (frags); lnode; nextnode (lnode)) {
+    lsp = getdata (lnode);
+    dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id);
+    lsp_destroy (lsp);
+    dnode_destroy (dict_delete(lspdb, dnode));
+  }
+  
+  list_delete_all_node (frags);
+  
+  return;
+}
+
+void
+lsp_search_and_destroy (u_char *id, dict_t *lspdb)
+{
+  dnode_t *node;
+  struct isis_lsp *lsp;
+
+  node = dict_lookup (lspdb, id);
+  if (node) {
+    node = dict_delete (lspdb, node);
+    lsp = dnode_get (node);
+    /*
+     * If this is a zero lsp, remove all the frags now 
+     */
+    if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0) {
+      if (lsp->lspu.frags)
+        lsp_remove_frags (lsp->lspu.frags, lspdb);
+    } else {
+    /* 
+     * else just remove this frag, from the zero lsps' frag list
+     */
+      if (lsp->lspu.zero_lsp && lsp->lspu.zero_lsp->lspu.frags)
+        listnode_delete (lsp->lspu.zero_lsp->lspu.frags, lsp);
+    }
+    lsp_destroy (lsp);
+    dnode_destroy (node);
+  }
+}
+
+/*
+ * Compares a LSP to given values
+ * Params are given in net order
+ */
+int 
+lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, 
+	     u_int16_t checksum, u_int16_t rem_lifetime)
+{
+      /* no point in double ntohl on seqnum */
+  if (lsp->lsp_header->seq_num == seq_num && 
+      lsp->lsp_header->checksum == checksum &&
+      /*comparing with 0, no need to do ntohl */
+      ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) ||
+       (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0))) { 
+    if (isis->debugs & DEBUG_SNP_PACKETS) {
+      zlog_info ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
+                 " lifetime %us",
+                 areatag,
+                 rawlspid_print (lsp->lsp_header->lsp_id),
+                 ntohl(lsp->lsp_header->seq_num),
+                 ntohs(lsp->lsp_header->checksum),
+                 ntohs(lsp->lsp_header->rem_lifetime) );
+      zlog_info ("ISIS-Snp (%s):         is equal to ours seq 0x%08x,"
+                 " cksum 0x%04x, lifetime %us",
+                 areatag,
+                 ntohl(seq_num),
+                 ntohs(checksum),
+                 ntohs(rem_lifetime));
+    }
+    return LSP_EQUAL;
+  }
+
+  if (ntohl(seq_num) >= ntohl(lsp->lsp_header->seq_num)) {
+    if (isis->debugs & DEBUG_SNP_PACKETS) {
+      zlog_info ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x,"
+                 " lifetime %us",
+                 areatag,
+                 rawlspid_print (lsp->lsp_header->lsp_id),
+                 ntohl(seq_num),
+                 ntohs(checksum),
+                 ntohs(rem_lifetime ));
+      zlog_info ("ISIS-Snp (%s):       is newer than ours seq 0x%08x, "
+                 "cksum 0x%04x, lifetime %us",
+                 areatag,
+                 ntohl(lsp->lsp_header->seq_num),
+                 ntohs(lsp->lsp_header->checksum),
+                 ntohs(lsp->lsp_header->rem_lifetime) );
+    }
+    return LSP_NEWER;
+  }
+  if (isis->debugs & DEBUG_SNP_PACKETS) {
+    zlog_info ("ISIS-Snp (%s): LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us",
+	       areatag,
+	       rawlspid_print (lsp->lsp_header->lsp_id),
+	       ntohl(seq_num),
+	       ntohs(checksum),
+	       ntohs(rem_lifetime ));
+    zlog_info ("ISIS-Snp (%s):       is older than ours seq 0x%08x,"
+               " cksum 0x%04x, lifetime %us",
+	       areatag,
+	       ntohl(lsp->lsp_header->seq_num),
+	       ntohs(lsp->lsp_header->checksum),
+	       ntohs(lsp->lsp_header->rem_lifetime) );
+  }
+
+  return LSP_OLDER;
+}
+
+void 
+lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num)
+{
+  u_int32_t newseq;
+  
+  if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num)
+    newseq = ntohl (lsp->lsp_header->seq_num) + 1;
+  else
+    newseq = seq_num ++;
+  
+  lsp->lsp_header->seq_num = htonl (newseq);
+  iso_csum_create (STREAM_DATA (lsp->pdu) + 12, 
+                   ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+
+  return;
+}
+
+/*
+ * Genetates checksum for LSP and its frags
+ */
+void
+lsp_seqnum_update (struct isis_lsp *lsp0)
+{
+  struct isis_lsp *lsp;
+  struct listnode *node;
+  
+  lsp_inc_seqnum (lsp0, 0);
+
+  if (!lsp0->lspu.frags)
+    return;
+
+  for (node = listhead (lsp0->lspu.frags); node; nextnode (node)) {
+    lsp = getdata (node);
+    lsp_inc_seqnum(lsp, 0);
+  }
+  
+  return;
+}
+
+int 
+isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
+			 int  pdulen, struct isis_passwd *passwd)
+{
+  uint32_t expected = 0, found;
+  struct tlvs tlvs;
+  int retval = 0;
+
+  expected |= TLVFLAG_AUTH_INFO;
+  retval = parse_tlvs (area->area_tag, stream->data +
+                       ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
+                       pdulen - ISIS_FIXED_HDR_LEN 
+                       - ISIS_LSP_HDR_LEN, 
+		       &expected, &found, &tlvs);
+  if (retval || !(found & TLVFLAG_AUTH_INFO))
+    return 1; /* Auth fail (parsing failed or no auth-tlv)*/
+
+  return authentication_check (passwd, &tlvs.auth_info);
+}
+
+void
+lsp_update_data (struct isis_lsp *lsp, struct stream *stream, 
+                 struct isis_area *area)
+{
+  uint32_t expected = 0,found;
+  int retval;
+  
+  /* copying only the relevant part of our stream */
+  lsp->pdu = stream_new (stream->endp);
+  lsp->pdu->putp = stream->putp;
+  lsp->pdu->getp = stream->getp;
+  lsp->pdu->endp = stream->endp;
+  memcpy (lsp->pdu->data, stream->data, stream->endp);
+
+  /* setting pointers to the correct place */
+  lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu));
+  lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu) + 
+						   ISIS_FIXED_HDR_LEN);
+  lsp->age_out = ZERO_AGE_LIFETIME;
+  lsp->installed = time(NULL);
+  /*
+   * Get LSP data i.e. TLVs
+   */
+  expected |= TLVFLAG_AUTH_INFO;
+  expected |= TLVFLAG_AREA_ADDRS;
+  expected |= TLVFLAG_IS_NEIGHS;
+  if ((lsp->lsp_header->lsp_bits & 3) == 3) /* a level 2 LSP */
+    expected |= TLVFLAG_PARTITION_DESIG_LEVEL2_IS;
+  expected |= TLVFLAG_NLPID;
+  if (area->dynhostname)
+    expected |= TLVFLAG_DYN_HOSTNAME;
+  if (area->newmetric) {
+    expected |= TLVFLAG_TE_IS_NEIGHS;
+    expected |= TLVFLAG_TE_IPV4_REACHABILITY;
+    expected |= TLVFLAG_TE_ROUTER_ID;
+  }
+  expected |= TLVFLAG_IPV4_ADDR;
+  expected |= TLVFLAG_IPV4_INT_REACHABILITY;
+  expected |= TLVFLAG_IPV4_EXT_REACHABILITY;
+#ifdef HAVE_IPV6
+  expected |= TLVFLAG_IPV6_ADDR;
+  expected |= TLVFLAG_IPV6_REACHABILITY;
+#endif /* HAVE_IPV6 */
+
+  retval = parse_tlvs (area->area_tag, lsp->pdu->data +
+                       ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN,
+                       ntohs(lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN 
+                       - ISIS_LSP_HDR_LEN, &expected, &found, &lsp->tlv_data);
+
+  if (found & TLVFLAG_DYN_HOSTNAME) {
+    if (area->dynhostname)
+      isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname,
+                         (lsp->lsp_header->lsp_bits & LSPBIT_IST) == 
+                         IS_LEVEL_1_AND_2 ? IS_LEVEL_2 : 
+                         (lsp->lsp_header->lsp_bits & LSPBIT_IST));
+  }
+
+}
+
+void
+lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
+            struct stream *stream, struct isis_area *area)
+{
+
+  /* free the old lsp data*/
+  XFREE (MTYPE_STREAM_DATA, lsp->pdu);
+  lsp_clear_data (lsp);
+
+  /* rebuild the lsp data */
+  lsp_update_data (lsp, stream, area);
+
+  /* set the new values for lsp header */ 
+  memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
+
+}
+
+
+/* creation of LSP directly from what we received */
+struct isis_lsp *
+lsp_new_from_stream_ptr (struct stream *stream, 
+                         u_int16_t pdu_len, struct isis_lsp *lsp0,
+                         struct isis_area *area)
+{
+  struct isis_lsp *lsp;
+
+  lsp = XMALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
+  memset (lsp, 0, sizeof (struct isis_lsp));
+  
+  lsp_update_data (lsp, stream, area);
+  
+  if (lsp0 == NULL) {
+    /*
+     * zero lsp -> create the list for fragments
+     */
+    lsp->lspu.frags = list_new ();
+  } else {
+    /*
+     * a fragment -> set the backpointer and add this to zero lsps frag list
+     */
+    lsp->lspu.zero_lsp = lsp0;
+    listnode_add (lsp0->lspu.frags, lsp);
+  }
+  
+  return lsp;
+}
+
+struct isis_lsp *
+lsp_new (u_char *lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num, 
+         u_int8_t lsp_bits, u_int16_t checksum, int level)
+{
+  struct isis_lsp *lsp;
+
+  lsp = XMALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
+  if (!lsp) {
+    /* FIXME: set lspdbol bit */
+    zlog_warn ("lsp_new(): out of memory");
+    return NULL;
+  }
+  memset (lsp, 0, sizeof (struct isis_lsp));
+#ifdef LSP_MEMORY_PREASSIGN
+  lsp->pdu = stream_new (1514); /*Should be minimal mtu? yup...*/
+#else
+  /* We need to do realloc on TLVs additions*/
+  lsp->pdu = malloc (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); 
+#endif /* LSP_MEMORY_PREASSIGN */
+  if (LSP_FRAGMENT (lsp_id) == 0)
+    lsp->lspu.frags = list_new ();
+  lsp->isis_header = (struct isis_fixed_hdr*)(STREAM_DATA(lsp->pdu));
+  lsp->lsp_header = (struct isis_link_state_hdr*)
+                    (STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN);
+  
+  /* at first we fill the FIXED HEADER */
+  (level == 1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE):
+                 fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE);
+  
+  /* now for the LSP HEADER */
+  /* Minimal LSP PDU size */
+  lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); 
+  memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
+  lsp->lsp_header->checksum = checksum; /* Provided in network order */
+  lsp->lsp_header->seq_num = htonl (seq_num);
+  lsp->lsp_header->rem_lifetime = htons (rem_lifetime);
+  lsp->lsp_header->lsp_bits = lsp_bits;
+  lsp->level = level;
+  lsp->age_out = ZERO_AGE_LIFETIME;
+
+  stream_set_putp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+
+  /* #ifdef EXTREME_DEBUG */
+  /* logging */
+  zlog_info ("New LSP with ID %s-%02x-%02x seqnum %08x", sysid_print (lsp_id),
+             LSP_PSEUDO_ID (lsp->lsp_header->lsp_id),
+             LSP_FRAGMENT (lsp->lsp_header->lsp_id),
+             ntohl (lsp->lsp_header->seq_num));
+  /* #endif  EXTREME DEBUG */
+
+  return lsp;
+}
+
+void
+lsp_insert (struct isis_lsp *lsp, dict_t *lspdb)
+{
+  dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp);
+}
+
+/*
+ * Build a list of LSPs with non-zero ht bounded by start and stop ids
+ */
+void 
+lsp_build_list_nonzero_ht (u_char *start_id, u_char *stop_id, 
+                           struct list *list, dict_t *lspdb)
+{
+  dnode_t *first, *last, *curr;
+
+  first = dict_lower_bound (lspdb, start_id);
+  if (!first)
+    return;
+  
+  last = dict_upper_bound (lspdb, stop_id);
+  
+  curr = first;
+  
+  if (((struct isis_lsp *)(curr->dict_data))->lsp_header->rem_lifetime)
+    listnode_add (list, first->dict_data);
+
+  while (curr) {
+    curr = dict_next (lspdb, curr);
+    if (curr && 
+        ((struct isis_lsp *)(curr->dict_data))->lsp_header->rem_lifetime)
+      listnode_add (list, curr->dict_data);
+    if (curr == last)
+      break;
+  }
+  
+  return;
+}
+
+/*
+ * Build a list of all LSPs bounded by start and stop ids
+ */
+void 
+lsp_build_list (u_char *start_id, u_char *stop_id, 
+                struct list *list, dict_t *lspdb)
+{
+  dnode_t *first, *last, *curr;
+
+  first = dict_lower_bound (lspdb, start_id);
+  if (!first)
+    return;
+  
+  last = dict_upper_bound (lspdb, stop_id);
+  
+  curr = first;
+  
+  listnode_add (list, first->dict_data);
+
+  while (curr) {
+    curr = dict_next (lspdb, curr);
+    if (curr)
+      listnode_add (list, curr->dict_data);
+    if (curr == last)
+      break;
+  }
+  
+  return;
+}
+
+/*
+ * Build a list of LSPs with SSN flag set for the given circuit
+ */
+void
+lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list, 
+                    dict_t *lspdb)
+{
+  dnode_t *dnode, *next;
+  struct isis_lsp *lsp;
+  
+  dnode = dict_first (lspdb);
+  while (dnode != NULL) {
+    next = dict_next (lspdb, dnode);
+    lsp = dnode_get (dnode);
+    if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit))
+      listnode_add (list, lsp);
+    dnode = next;
+  }
+  
+  return;
+}
+
+void
+lsp_set_time (struct isis_lsp *lsp)
+{
+  assert (lsp);
+  
+  if (lsp->lsp_header->rem_lifetime == 0) {
+    if (lsp->age_out != 0) lsp->age_out--;
+    return;
+  }
+
+  /* If we are turning 0 */
+  /* ISO 10589 - 7.3.16.4 first paragraph */
+
+  if (ntohs (lsp->lsp_header->rem_lifetime) == 1) {
+    /* 7.3.16.4 a) set SRM flags on all */
+    ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+    /* 7.3.16.4 b) retain only the header FIXME  */
+    /* 7.3.16.4 c) record the time to purge FIXME (other way to do it)*/
+  }
+
+  lsp->lsp_header->rem_lifetime = 
+    htons (ntohs (lsp->lsp_header->rem_lifetime) - 1);
+}
+
+void
+lspid_print (u_char *lsp_id, u_char *trg, char dynhost, char frag)
+{
+  struct isis_dynhn *dyn = NULL;
+  u_char id [SYSID_STRLEN];
+
+  if (dynhost)
+    dyn = dynhn_find_by_id (lsp_id);
+  else
+    dyn = NULL;
+
+  if (dyn)
+    sprintf (id, "%.14s", dyn->name.name);
+  else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) & dynhost)
+    sprintf (id, "%.14s", host.name);
+   else {
+    memcpy(id, sysid_print (lsp_id), 15);
+  }
+  if (frag)
+    sprintf (trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id), 
+             LSP_FRAGMENT(lsp_id));
+  else
+    sprintf (trg, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
+}
+
+/* Convert the lsp attribute bits to attribute string */ 
+char * 
+lsp_bits2string (u_char *lsp_bits) {
+
+  char *pos = lsp_bits_string; 
+
+  if(!*lsp_bits)
+    return " none";
+
+  /* we only focus on the default metric */
+  pos += sprintf (pos, "%d/",
+           ISIS_MASK_LSP_ATT_DEFAULT_BIT(*lsp_bits) ?
+           1 : 0);
+
+  pos += sprintf (pos, "%d/",
+           ISIS_MASK_LSP_PARTITION_BIT(*lsp_bits) ?
+           1 : 0);
+
+  pos += sprintf (pos, "%d",
+           ISIS_MASK_LSP_OL_BIT(*lsp_bits) ?
+           1 : 0);
+  
+  *(pos) = '\0';
+  
+  return lsp_bits_string;
+
+}
+
+/* this function prints the lsp on show isis database */
+void
+lsp_print (dnode_t *node, struct vty *vty, char dynhost)
+{
+  struct isis_lsp *lsp = dnode_get(node);
+  u_char LSPid[255];
+
+  lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
+  vty_out (vty, "%-21s%c   ", LSPid,lsp->own_lsp?'*':' ');
+  vty_out (vty, "0x%08x   ", ntohl(lsp->lsp_header->seq_num));
+  vty_out (vty, "0x%04x      ", ntohs(lsp->lsp_header->checksum));
+
+  if (ntohs(lsp->lsp_header->rem_lifetime) == 0)
+    vty_out (vty, " (%2u)",lsp->age_out);
+  else
+    vty_out (vty, "%5u", ntohs(lsp->lsp_header->rem_lifetime));
+
+  vty_out (vty, "         %s%s",
+    lsp_bits2string(&lsp->lsp_header->lsp_bits),	   
+    VTY_NEWLINE);
+}
+
+void
+lsp_print_detail (dnode_t *node, struct vty *vty, char dynhost)
+{
+  struct isis_lsp *lsp = dnode_get (node);
+  struct area_addr *area_addr;
+  char   nlpidstr[2];
+  int    i;
+  struct listnode *lnode;
+  struct is_neigh *is_neigh;
+  struct te_is_neigh *te_is_neigh;
+  struct ipv4_reachability *ipv4_reach;
+  struct in_addr *ipv4_addr;
+  struct te_ipv4_reachability *te_ipv4_reach;
+#ifdef HAVE_IPV6
+  struct ipv6_reachability *ipv6_reach;
+  struct in6_addr in6;
+#endif
+  u_char LSPid[255];
+  u_char hostname[255];
+  u_char buff[BUFSIZ];
+  u_int32_t now,helper;
+  u_char ipv4_reach_prefix[20];
+  u_char ipv4_reach_mask[20];
+  u_char ipv4_address[20];
+
+  lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1);
+  lsp_print(node, vty, dynhost);
+
+  /* for all area address */
+  if (lsp->tlv_data.area_addrs) {
+    LIST_LOOP (lsp->tlv_data.area_addrs, area_addr, lnode) {
+    vty_out (vty, "  Area Address:  %s%s", 
+		   isonet_print (area_addr->area_addr, area_addr->addr_len), 
+		   VTY_NEWLINE);
+    }
+  }
+
+  /* for the nlpid tlv */
+  if (lsp->tlv_data.nlpids) {
+    for (i = 0; i < lsp->tlv_data.nlpids->count; i++) {
+      switch (lsp->tlv_data.nlpids->nlpids[i]) {
+      case NLPID_IP:
+      case NLPID_IPV6:
+        vty_out (vty, "  NLPID:         0x%X%s",
+               lsp->tlv_data.nlpids->nlpids[i],
+               VTY_NEWLINE);
+        break;
+      default:
+        vty_out (vty, "  NLPID:         %s%s",
+               "unknown",
+               VTY_NEWLINE);
+        break;
+      }
+    } 
+  }
+
+  /* for the hostname tlv */
+  if (lsp->tlv_data.hostname) {
+    bzero (hostname, sizeof (hostname));
+    memcpy (hostname, lsp->tlv_data.hostname->name,
+            lsp->tlv_data.hostname->namelen);
+    vty_out (vty, "  Hostname: %s%s", hostname, VTY_NEWLINE);
+  }
+
+  if (lsp->tlv_data.ipv4_addrs) {
+    LIST_LOOP(lsp->tlv_data.ipv4_addrs, ipv4_addr, lnode) {
+      memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_addr));
+      vty_out (vty, "  IP:        %s%s",
+               ipv4_address,
+               VTY_NEWLINE);
+    }
+  }
+  
+  /* for the internal reachable tlv */
+  if (lsp->tlv_data.ipv4_int_reachs)
+    LIST_LOOP(lsp->tlv_data.ipv4_int_reachs, ipv4_reach, lnode) {
+      memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix), sizeof (ipv4_reach_prefix));
+      memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask), sizeof (ipv4_reach_mask));
+      vty_out (vty, "  Matric: %d IP %s %s%s",
+             ipv4_reach->metrics.metric_default,
+             ipv4_reach_prefix,
+             ipv4_reach_mask,
+             VTY_NEWLINE);
+  }
+
+  /* for the IS neighbor tlv */
+  if (lsp->tlv_data.is_neighs) {
+    LIST_LOOP(lsp->tlv_data.is_neighs,is_neigh,lnode) {
+      lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
+      vty_out (vty, "  Metric: %d IS %s%s",
+              is_neigh->metrics.metric_default,
+              LSPid,
+              VTY_NEWLINE);
+    }
+  }
+
+/* FIXME: Other tlvs such as te or external tlv will be added later */
+#if 0  
+  vty_out (vty, "%s  %s %c%s",
+	   VTY_NEWLINE,
+	   LSPid,
+	   lsp->own_lsp ? '*' : ' ',
+	   VTY_NEWLINE);
+
+  vty_out (vty, "    Sequence: 0x%08x Checksum: 0x%04x Lifetime: ",
+	   ntohl (lsp->lsp_header->seq_num),
+	   ntohs (lsp->lsp_header->checksum));
+
+  if (ntohs (lsp->lsp_header->rem_lifetime) == 0)
+    vty_out (vty, " (%2u) ", lsp->age_out);
+  else
+    vty_out (vty, "%5u ", ntohs (lsp->lsp_header->rem_lifetime));
+
+  vty_out (vty, "%s    Attributes:%s",
+	   VTY_NEWLINE,
+	   lsp_bits2string (&lsp->lsp_header->lsp_bits));
+
+  /* if this is a self originated LSP then print
+   * the generation time plus when we sent it last
+   * if it is a non self-originated LSP then print the
+   * time when the LSP has been installed
+   */
+
+  if (lsp->own_lsp) {
+
+    now = time (NULL);
+    helper = now - lsp->last_generated;
+    if (!lsp->last_generated)
+      helper = 0;
+
+    vty_out (vty, ", Generated: %s ago",
+	     time2string (helper));
+
+    now = time (NULL);
+    helper = now - lsp->last_sent;
+    if (!lsp->last_sent)
+      helper = 0;
+
+    vty_out (vty, ", Last sent: %s ago",
+	     time2string (helper));
+  } else {
+    now = time (NULL);
+    helper = now - lsp->installed;
+    if (!lsp->installed)
+      helper = 0;
+
+    vty_out (vty, ", Installed: %s ago",
+	     time2string (helper));
+
+  }
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  if (lsp->tlv_data.nlpids)  {
+    vty_out (vty, "    Speaks: %s%s", nlpid2string (lsp->tlv_data.nlpids), 
+             VTY_NEWLINE);
+  }
+
+  if (lsp->tlv_data.router_id)  {
+    vty_out (vty, "     Router ID: %s%s", 
+             inet_ntoa (lsp->tlv_data.router_id->id), VTY_NEWLINE);
+  }
+
+  if (lsp->tlv_data.is_neighs)
+  LIST_LOOP(lsp->tlv_data.is_neighs,is_neigh,lnode) {
+    lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0);
+    vty_out (vty, "     IS      %s, Metric: %d%s",
+             LSPid,
+	     is_neigh->metrics.metric_default,
+	     VTY_NEWLINE);
+  }
+
+  if (lsp->tlv_data.te_is_neighs)
+    LIST_LOOP(lsp->tlv_data.te_is_neighs,te_is_neigh,lnode) {
+    /* FIXME: metric display is wrong */
+    lspid_print (te_is_neigh->neigh_id, LSPid, dynhost, 0);
+    vty_out (vty, "     extd-IS %s, Metric: %d%s",
+             LSPid,	     
+	     te_is_neigh->te_metric[0],
+	     VTY_NEWLINE);
+  }
+
+  if (lsp->tlv_data.ipv4_int_reachs)
+    LIST_LOOP(lsp->tlv_data.ipv4_int_reachs, ipv4_reach, lnode) {
+    vty_out (vty, "     int-IP  %s/%d, Metric: %d%s",
+             inet_ntoa (ipv4_reach->prefix),
+	     ip_masklen (ipv4_reach->mask),
+	     ipv4_reach->metrics.metric_default,
+	     VTY_NEWLINE);
+  }
+
+  if (lsp->tlv_data.ipv4_ext_reachs)
+    LIST_LOOP(lsp->tlv_data.ipv4_ext_reachs,ipv4_reach,lnode) {
+    vty_out (vty, "     ext-IP  %s/%d, Metric: %d%s",
+             inet_ntoa(ipv4_reach->prefix),
+	     ip_masklen(ipv4_reach->mask),
+	     ipv4_reach->metrics.metric_default,
+	     VTY_NEWLINE);
+  }
+
+  if (lsp->tlv_data.te_ipv4_reachs)
+    LIST_LOOP(lsp->tlv_data.te_ipv4_reachs,te_ipv4_reach,lnode) {
+    vty_out (vty, "     extd-IP %s/%d, Metric: %d%s",
+             inet_ntoa ( newprefix2inaddr (&te_ipv4_reach->prefix_start, 
+                                           te_ipv4_reach->control)),
+             te_ipv4_reach->control & 0x3F,
+	     ntohl (te_ipv4_reach->te_metric),
+	     VTY_NEWLINE);
+  }
+
+#ifdef HAVE_IPV6
+  if (lsp->tlv_data.ipv6_reachs)
+    LIST_LOOP(lsp->tlv_data.ipv6_reachs, ipv6_reach, lnode) {
+    memcpy (in6.s6_addr, ipv6_reach->prefix, 16);
+    inet_ntop (AF_INET6, &in6, buff, BUFSIZ);
+    if ((ipv6_reach->control_info &&  
+        CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL)
+      vty_out (vty, "     int-IPv6 %s/%d, Metric: %d%s",
+               buff,
+               ipv6_reach->prefix_len,
+               ntohl (ipv6_reach->metric),
+               VTY_NEWLINE);
+    else
+      vty_out (vty, "     ext-IPv6 %s/%d, Metric: %d%s",
+               buff,
+               ipv6_reach->prefix_len,
+               ntohl (ipv6_reach->metric),
+               VTY_NEWLINE);
+    
+  }
+#endif
+  if (lsp->tlv_data.hostname) {
+    memset (hostname, 0, sizeof (hostname));
+    memcpy (hostname, lsp->tlv_data.hostname->name,
+            lsp->tlv_data.hostname->namelen);
+    vty_out (vty, "    Hostname: %s%s", hostname, VTY_NEWLINE);
+  }
+#endif
+ return;
+}
+
+/* print all the lsps info in the local lspdb */
+int 
+lsp_print_all (struct vty *vty, dict_t *lspdb, char detail, char dynhost)
+{
+
+  dnode_t *node = dict_first(lspdb), *next;
+  int lsp_count = 0;
+
+  /* print the title, for both modes */
+  vty_out (vty, "LSP ID                   LSP Seq Num  LSP Checksum "
+             "LSP Holdtime ATT/P/OL%s", VTY_NEWLINE);
+             
+  if (detail == ISIS_UI_LEVEL_BRIEF) {
+    while (node != NULL) {
+      /* dict_contains (lspdb, node); */ /* I think it is unnecessary, so I comment it out */
+      next = dict_next (lspdb, node);
+      lsp_print (node, vty, dynhost);
+      node = next;
+      lsp_count++;
+    }
+  } else if (detail == ISIS_UI_LEVEL_DETAIL) {
+    while (node != NULL) {
+      next = dict_next (lspdb, node);
+      lsp_print_detail (node, vty, dynhost);
+      node = next;
+      lsp_count++;
+    }
+  }
+
+  return lsp_count;
+}
+
+/* this function reallocate memory to an lsp pdu, with an additional
+ * size of memory, it scans the lsp and moves all pointers the
+ * way they should */
+u_char *
+lsppdu_realloc (struct isis_lsp *lsp, int memorytype, int size)
+{
+  u_char *retval;
+  
+  retval = STREAM_DATA(lsp->pdu) + ntohs(lsp->lsp_header->pdu_len);
+#ifdef   LSP_MEMORY_PREASSIGN
+  lsp->lsp_header->pdu_len = htons(ntohs(lsp->lsp_header->pdu_len) + size);
+  return retval;
+#else    /* otherwise we have to move all pointers */
+  u_char *newpdu;
+  newpdu = stream_new (ntohs (lsp->lsp_header->pdu_len) + size);
+  memcpy (STREAM_DATA (newpdu), STREAM_DATA(lsp->pdu), 
+          ntohs (lsp->lsp_header->pdu_len));
+  XFREE (memorytype, lsp->pdu);
+  lsp->pdu = newpdu;
+  lsp->isis_header = (struct isis_fixed_hdr*)STREAM_DATA(lsp->pdu);
+  lsp->lsp_header = (struct isis_link_state_hdr*)
+                    (STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN);
+  htons (ntohs (lsp->lsp_header->pdu_len) += size);
+  return STREAM_DATA(lsp->pdu) + (lsp->lsp_header->pdu_len - size);
+#endif /* LSP_MEMORY_PREASSIGN */
+}
+
+
+#if 0 /* Saving the old one just in case :) */
+/*
+ * Builds the lsp->tlv_data
+ * and writes the tlvs into lsp->pdu 
+ */
+void
+lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
+{
+  struct is_neigh *is_neigh;
+  struct listnode *node, *ipnode;
+  int level = lsp->level;
+  struct isis_circuit *circuit;
+  struct prefix_ipv4 *ipv4;
+  struct ipv4_reachability *ipreach;
+  struct isis_adjacency *nei;
+#ifdef HAVE_IPV6
+  struct prefix_ipv6 *ipv6;
+  struct ipv6_reachability *ip6reach;
+#endif /* HAVE_IPV6 */
+  
+  /*
+   * First add the tlvs related to area
+   */
+  
+  /* Area addresses */
+  if (lsp->tlv_data.area_addrs == NULL)
+    lsp->tlv_data.area_addrs = list_new ();
+  list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
+  /* Protocols Supported */
+  if (area->ip_circuits > 0 
+#ifdef HAVE_IPV6
+      || area->ipv6_circuits > 0
+#endif /* HAVE_IPV6 */
+      )
+    {
+      lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
+      lsp->tlv_data.nlpids->count = 0;
+      if (area->ip_circuits > 0) { 
+        lsp->tlv_data.nlpids->count++;
+        lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
+      }  
+#ifdef HAVE_IPV6
+      if (area->ipv6_circuits > 0) {  
+        lsp->tlv_data.nlpids->count++;
+        lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] = 
+        NLPID_IPV6;
+      } 
+#endif /* HAVE_IPV6 */
+    }
+  /* Dynamic Hostname */
+  if (area->dynhostname) {
+    lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV, 
+                                      sizeof (struct hostname));
+    memcpy (&lsp->tlv_data.hostname->name, host.name, strlen(host.name));
+    lsp->tlv_data.hostname->namelen = strlen (host.name);
+  }
+#ifdef TOPOLOGY_GENERATE
+  /*
+   * If we have a topology in this area, we need to connect this lsp to
+   * the first topology lsp
+   */
+  if ((area->topology) && (level == 1)) {
+    if (lsp->tlv_data.is_neighs == NULL)
+      lsp->tlv_data.is_neighs = list_new ();
+    is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+    memset (is_neigh, 0, sizeof (struct is_neigh));
+    memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
+    /* connected to the first */
+    is_neigh->neigh_id[ISIS_SYS_ID_LEN-1] = (0x01); 
+    /* this is actually the same system, why mess the SPT */
+    is_neigh->metrics.metric_default = 0; 
+    is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
+    is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
+    is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
+    listnode_add (lsp->tlv_data.is_neighs, is_neigh);
+
+  }
+#endif
+
+  /*
+   * Then add tlvs related to circuits
+   */
+  for (node = listhead (area->circuit_list); node; nextnode (node)) {
+    circuit = getdata (node);
+    if (circuit->state != C_STATE_UP)
+      continue;
+    
+    /*
+     * Add IPv4 internal reachability of this circuit
+     */
+    if (circuit->ip_router && circuit->ip_addrs && 
+        circuit->ip_addrs->count > 0) {
+      if (lsp->tlv_data.ipv4_int_reachs == NULL) { 
+        lsp->tlv_data.ipv4_int_reachs = list_new ();
+        lsp->tlv_data.ipv4_int_reachs->del = free_tlv;
+      }
+      for (ipnode = listhead (circuit->ip_addrs); ipnode; nextnode (ipnode)) {
+        ipv4 = getdata (ipnode);
+        ipreach = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
+        ipreach->metrics = circuit->metrics[level - 1];
+        ipreach->prefix = ipv4->prefix;
+        masklen2ip (ipv4->prefixlen, &ipreach->mask); 
+        listnode_add (lsp->tlv_data.ipv4_int_reachs, ipreach);
+      }
+    }
+#ifdef HAVE_IPV6
+    /*
+     * Add IPv6 reachability of this circuit
+     */
+    if (circuit->ipv6_router && circuit->ipv6_non_link && 
+        circuit->ipv6_non_link->count > 0) {
+        if (lsp->tlv_data.ipv6_reachs == NULL) {
+            lsp->tlv_data.ipv6_reachs = list_new ();
+            lsp->tlv_data.ipv6_reachs->del = free_tlv;
+        }
+      for (ipnode = listhead (circuit->ipv6_non_link); ipnode; 
+           nextnode (ipnode)) {
+        ipv6 = getdata (ipnode);
+        ip6reach = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
+        memset (ip6reach, 0, sizeof (struct ipv6_reachability));
+        ip6reach->metric = htonl(circuit->metrics[level - 1].metric_default);
+        ip6reach->control_info = 0;
+        ip6reach->prefix_len = ipv6->prefixlen;
+        memcpy (&ip6reach->prefix, ipv6->prefix.s6_addr, 
+                (ipv6->prefixlen + 7) / 8);
+        listnode_add (lsp->tlv_data.ipv6_reachs, ip6reach);
+      }
+    }
+#endif /* HAVE_IPV6 */
+    
+    switch (circuit->circ_type) {
+    case CIRCUIT_T_BROADCAST:
+      if (level & circuit->circuit_is_type) {
+        if (lsp->tlv_data.is_neighs == NULL) {
+          lsp->tlv_data.is_neighs = list_new ();
+          lsp->tlv_data.is_neighs->del = free_tlv;
+        }
+        is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+        memset (is_neigh, 0, sizeof (struct is_neigh));
+        if (level == 1)
+          memcpy (&is_neigh->neigh_id, 
+                  circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
+        else
+          memcpy (&is_neigh->neigh_id, 
+                  circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
+            is_neigh->metrics = circuit->metrics[level - 1];
+        listnode_add (lsp->tlv_data.is_neighs, is_neigh);
+      }
+      break;
+    case CIRCUIT_T_P2P:
+      nei = circuit->u.p2p.neighbor; 
+        if (nei && (level & nei->circuit_t)) {
+          if (lsp->tlv_data.is_neighs == NULL) {
+            lsp->tlv_data.is_neighs = list_new ();
+            lsp->tlv_data.is_neighs->del = free_tlv;
+          }
+          is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+          memset (is_neigh, 0, sizeof (struct is_neigh));
+          memcpy (&is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
+          is_neigh->metrics = circuit->metrics[level - 1];
+          listnode_add (lsp->tlv_data.is_neighs, is_neigh);
+      }
+      break;
+    case  CIRCUIT_T_STATIC_IN:
+      zlog_warn ("lsp_area_create: unsupported circuit type");
+      break;
+    case  CIRCUIT_T_STATIC_OUT:
+      zlog_warn ("lsp_area_create: unsupported circuit type");
+      break;
+    case CIRCUIT_T_DA:
+      zlog_warn ("lsp_area_create: unsupported circuit type");
+      break;
+    default:
+      zlog_warn ("lsp_area_create: unknown circuit type");
+    }
+  }
+  
+  stream_set_putp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+  
+  if (lsp->tlv_data.nlpids)
+    tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
+  if (lsp->tlv_data.hostname)
+    tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
+  if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0 )
+    tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
+  if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
+    tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
+  if (lsp->tlv_data.ipv4_int_reachs  && 
+      listcount (lsp->tlv_data.ipv4_int_reachs) > 0)
+    tlv_add_ipv4_reachs (lsp->tlv_data.ipv4_int_reachs, lsp->pdu);
+#ifdef  HAVE_IPV6 
+  if (lsp->tlv_data.ipv6_reachs && 
+      listcount (lsp->tlv_data.ipv6_reachs) > 0)
+    tlv_add_ipv6_reachs (lsp->tlv_data.ipv6_reachs, lsp->pdu);
+#endif /* HAVE_IPV6 */
+
+  lsp->lsp_header->pdu_len = htons (stream_get_putp (lsp->pdu));
+
+  return;
+}
+#endif
+
+#define FRAG_THOLD(S,T) \
+((STREAM_SIZE(S)*T)/100)
+
+/* stream*, area->lsp_frag_threshold, increment */
+#define FRAG_NEEDED(S,T,I) \
+  (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T))
+
+void
+lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to,
+             int tlvsize, int frag_thold, 
+             int tlv_build_func(struct list *, struct stream *))
+{
+  int count, i;
+  
+  /* can we fit all ? */
+  if (!FRAG_NEEDED(lsp->pdu, frag_thold,
+                   listcount(*from) * tlvsize + 2)) {
+    tlv_build_func (*from, lsp->pdu);
+    *to = *from;
+    *from = NULL;
+  } else if (!FRAG_NEEDED(lsp->pdu, frag_thold, tlvsize + 2)) {
+    /* fit all we can */
+    count = FRAG_THOLD(lsp->pdu,frag_thold) - 2 - 
+      (STREAM_SIZE(lsp->pdu) - STREAM_REMAIN(lsp->pdu));
+    if (count)
+      count = count / tlvsize;
+    for (i = 0; i < count; i++) {
+      listnode_add (*to, getdata(listhead(*from)));
+      listnode_delete(*from, getdata(listhead(*from)));
+    }
+    tlv_build_func (*to, lsp->pdu);
+  }
+  lsp->lsp_header->pdu_len = htons (stream_get_putp (lsp->pdu));  
+  return;
+}
+
+struct isis_lsp  *
+lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area, 
+               int level )
+{
+  struct isis_lsp *lsp;
+  u_char frag_id[ISIS_SYS_ID_LEN + 2]; 
+  
+  memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1);
+  LSP_FRAGMENT (frag_id) = frag_num;
+  lsp = lsp_search (frag_id, area->lspdb[level - 1]);
+  if (lsp) {
+    /*
+     * Clear the TLVs, but inherit the authinfo
+     */
+    lsp_clear_data (lsp);
+    if (lsp0->tlv_data.auth_info.type) {
+      memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info, 
+	      sizeof (struct isis_passwd));
+      tlv_add_authinfo (lsp->tlv_data.auth_info.type, 
+			lsp->tlv_data.auth_info.len, 
+		      lsp->tlv_data.auth_info.passwd, lsp->pdu);
+    }
+    return lsp;
+  } 
+  lsp = lsp_new (frag_id, area->max_lsp_lifetime[level - 1], 0, area->is_type,
+                 0, level);
+  lsp->own_lsp = 1;
+  lsp_insert (lsp, area->lspdb[level-1]);
+  listnode_add (lsp0->lspu.frags, lsp);
+  lsp->lspu.zero_lsp = lsp0;
+  /*
+   * Copy the authinfo from zero LSP
+   */
+  if (lsp0->tlv_data.auth_info.type) {
+    memcpy (&lsp->tlv_data.auth_info, &lsp->tlv_data.auth_info, 
+	    sizeof (struct isis_passwd));
+    tlv_add_authinfo (lsp->tlv_data.auth_info.type, 
+		      lsp->tlv_data.auth_info.len, 
+		      lsp->tlv_data.auth_info.passwd, lsp->pdu);
+  }
+  return lsp;
+}
+
+/*
+ * Builds the LSP data part. This func creates a new frag whenever 
+ * area->lsp_frag_threshold is exceeded.
+ */
+#if 1
+void
+lsp_build_nonpseudo (struct isis_lsp *lsp, struct isis_area *area)
+{
+  struct is_neigh *is_neigh;
+  struct listnode *node, *ipnode;
+  int level = lsp->level;
+  struct isis_circuit *circuit;
+  struct prefix_ipv4 *ipv4;
+  struct ipv4_reachability *ipreach;
+  struct isis_adjacency *nei;
+#ifdef HAVE_IPV6
+  struct prefix_ipv6 *ipv6;
+  struct ipv6_reachability *ip6reach;
+#endif /* HAVE_IPV6 */
+  struct tlvs tlv_data;
+  struct isis_lsp *lsp0 = lsp;
+  struct isis_passwd *passwd;
+
+  /*
+   * First add the tlvs related to area
+   */
+  
+  /* Area addresses */
+  if (lsp->tlv_data.area_addrs == NULL)
+    lsp->tlv_data.area_addrs = list_new ();
+  list_add_list (lsp->tlv_data.area_addrs, area->area_addrs);
+  /* Protocols Supported */
+  if (area->ip_circuits > 0 
+#ifdef HAVE_IPV6
+      || area->ipv6_circuits > 0
+#endif /* HAVE_IPV6 */
+      )
+    {
+      lsp->tlv_data.nlpids = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids));
+      lsp->tlv_data.nlpids->count = 0;
+      if (area->ip_circuits > 0) { 
+        lsp->tlv_data.nlpids->count++;
+        lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP;
+      }  
+#ifdef HAVE_IPV6
+      if (area->ipv6_circuits > 0) {  
+        lsp->tlv_data.nlpids->count++;
+        lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] = 
+        NLPID_IPV6;
+      } 
+#endif /* HAVE_IPV6 */
+    }
+  /* Dynamic Hostname */
+  if (area->dynhostname) {
+    lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV, 
+                                      sizeof (struct hostname));
+    memcpy (lsp->tlv_data.hostname->name, host.name, strlen (host.name));
+    lsp->tlv_data.hostname->namelen = strlen (host.name);
+  }
+
+  /*
+   * Building the zero lsp
+   */
+  stream_set_putp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);  
+  /*
+   * Add the authentication info if its present
+   */
+  (level == 1) ? (passwd = &area->area_passwd) : 
+                 (passwd = &area->domain_passwd);
+  if (passwd->type) {
+    memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
+    tlv_add_authinfo (passwd->type, passwd->len,
+		      passwd->passwd, lsp->pdu);
+  }
+  if (lsp->tlv_data.nlpids)
+    tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu);
+  if (lsp->tlv_data.hostname)
+    tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu);
+  if (lsp->tlv_data.area_addrs && listcount (lsp->tlv_data.area_addrs) > 0 )
+    tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu);
+ 
+  memset (&tlv_data, 0, sizeof (struct tlvs));
+  /*
+   * Then build lists of tlvs related to circuits
+   */
+  for (node = listhead (area->circuit_list); node; nextnode (node)) {
+    circuit = getdata (node);
+    if (circuit->state != C_STATE_UP)
+      continue;
+    
+    /*
+     * Add IPv4 internal reachability of this circuit
+     */
+    if (circuit->ip_router && circuit->ip_addrs && 
+        circuit->ip_addrs->count > 0) {
+      if (tlv_data.ipv4_int_reachs == NULL) { 
+        tlv_data.ipv4_int_reachs = list_new ();
+      }
+      for (ipnode = listhead (circuit->ip_addrs); ipnode; nextnode (ipnode)) {
+        ipv4 = getdata (ipnode);
+        ipreach = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability));
+        ipreach->metrics = circuit->metrics[level - 1];
+        ipreach->prefix = ipv4->prefix;
+        masklen2ip (ipv4->prefixlen, &ipreach->mask); 
+        listnode_add (tlv_data.ipv4_int_reachs, ipreach);
+      }
+
+    }
+#ifdef HAVE_IPV6
+    /*
+     * Add IPv6 reachability of this circuit
+     */
+    if (circuit->ipv6_router && circuit->ipv6_non_link && 
+        circuit->ipv6_non_link->count > 0) {
+      
+      if (tlv_data.ipv6_reachs == NULL) {
+        tlv_data.ipv6_reachs = list_new ();
+      }
+      for (ipnode = listhead (circuit->ipv6_non_link); ipnode; 
+           nextnode (ipnode)) {
+        ipv6 = getdata (ipnode);
+        ip6reach = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability));
+        memset (ip6reach, 0, sizeof (struct ipv6_reachability));
+        ip6reach->metric = htonl(circuit->metrics[level - 1].metric_default);
+        ip6reach->control_info = 0;
+        ip6reach->prefix_len = ipv6->prefixlen;
+        memcpy (ip6reach->prefix, ipv6->prefix.s6_addr, 
+                (ipv6->prefixlen + 7) / 8);
+        listnode_add (tlv_data.ipv6_reachs, ip6reach);
+      }
+    }
+#endif /* HAVE_IPV6 */
+    
+    switch (circuit->circ_type) {
+    case CIRCUIT_T_BROADCAST:
+      if (level & circuit->circuit_is_type) {
+        if (tlv_data.is_neighs == NULL) {
+          tlv_data.is_neighs = list_new ();
+        }
+        is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+        memset (is_neigh, 0, sizeof (struct is_neigh));
+        if (level == 1)
+          memcpy (is_neigh->neigh_id, 
+                  circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
+        else
+          memcpy (is_neigh->neigh_id, 
+                  circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
+            is_neigh->metrics = circuit->metrics[level - 1];
+        listnode_add (tlv_data.is_neighs, is_neigh);
+      }
+      break;
+    case CIRCUIT_T_P2P:
+      nei = circuit->u.p2p.neighbor; 
+        if (nei && (level & nei->circuit_t)) {
+          if (tlv_data.is_neighs == NULL) {
+            tlv_data.is_neighs = list_new ();
+            tlv_data.is_neighs->del = free_tlv;
+          }
+          is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+          memset (is_neigh, 0, sizeof (struct is_neigh));
+          memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN);
+          is_neigh->metrics = circuit->metrics[level - 1];
+          listnode_add (tlv_data.is_neighs, is_neigh);
+      }
+      break;
+    case  CIRCUIT_T_STATIC_IN:
+      zlog_warn ("lsp_area_create: unsupported circuit type");
+      break;
+    case  CIRCUIT_T_STATIC_OUT:
+      zlog_warn ("lsp_area_create: unsupported circuit type");
+      break;
+    case CIRCUIT_T_DA:
+      zlog_warn ("lsp_area_create: unsupported circuit type");
+      break;
+    default:
+      zlog_warn ("lsp_area_create: unknown circuit type");
+    }
+  }
+  
+  while (tlv_data.ipv4_int_reachs && listcount(tlv_data.ipv4_int_reachs)) {
+    if (lsp->tlv_data.ipv4_int_reachs == NULL)
+      lsp->tlv_data.ipv4_int_reachs = list_new ();
+    lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs, 
+                 &lsp->tlv_data.ipv4_int_reachs,
+                 IPV4_REACH_LEN, area->lsp_frag_threshold, 
+                 tlv_add_ipv4_reachs);
+    if (tlv_data.ipv4_int_reachs && listcount(tlv_data.ipv4_int_reachs))
+      lsp = lsp_next_frag (LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, 
+                           lsp0, area, level);
+  }
+
+#ifdef  HAVE_IPV6   
+  while (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs)) {
+    if (lsp->tlv_data.ipv6_reachs == NULL)
+      lsp->tlv_data.ipv6_reachs = list_new ();
+    lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs, 
+                 &lsp->tlv_data.ipv6_reachs,
+                 IPV6_REACH_LEN, area->lsp_frag_threshold, 
+                 tlv_add_ipv6_reachs);
+    if (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs))
+      lsp = lsp_next_frag (LSP_FRAGMENT(lsp->lsp_header->lsp_id) +  1, 
+                           lsp0, area, level);
+  }
+#endif /* HAVE_IPV6 */   
+
+  while (tlv_data.is_neighs && listcount(tlv_data.is_neighs)) {
+    if (lsp->tlv_data.is_neighs == NULL)
+      lsp->tlv_data.is_neighs = list_new ();
+    lsp_tlv_fit (lsp, &tlv_data.is_neighs, 
+                 &lsp->tlv_data.is_neighs,
+                 IS_NEIGHBOURS_LEN, area->lsp_frag_threshold, 
+                 tlv_add_is_neighs);
+    if (tlv_data.is_neighs && listcount(tlv_data.is_neighs))
+      lsp = lsp_next_frag (LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, 
+                           lsp0, area, level);
+  }
+  
+  
+  return;
+}
+#endif
+
+void
+build_lsp_data (struct isis_lsp *lsp, struct isis_area *area)
+{
+  struct list *circuit_list = area->circuit_list;
+  struct isis_circuit *circuit;
+  u_char *tlv_ptr;
+  struct is_neigh *is_neigh;
+
+   
+  /* add our nlpids */
+  /* the 2 is for the TL plus 1 for the nlpid*/
+  tlv_ptr = lsppdu_realloc (lsp,MTYPE_ISIS_TLV, 3);
+  *tlv_ptr = PROTOCOLS_SUPPORTED; /* Type */
+  *(tlv_ptr+1) = 1; /* one protocol */
+#ifdef HAVE_IPV6 /*dunno if its right*/
+  *(tlv_ptr+2) =  NLPID_IPV6;
+#else
+  *(tlv_ptr+2) =  NLPID_IP;
+#endif /* HAVE_IPV6 */
+
+  /* we should add our areas here
+   * FIXME: we need to figure out which should be added? Adj? All? First? */
+
+  /* first, lets add ourselves to the IS neighbours info */
+  /* the 2 is for the TL plus 1 for the virtual field*/
+  tlv_ptr = lsppdu_realloc(lsp,MTYPE_ISIS_TLV, 3);
+  *tlv_ptr = IS_NEIGHBOURS; /* Type */
+  *(tlv_ptr+2) = 0; /* virtual is zero */
+  lsp->tlv_data.is_neighs = list_new (); /* new list of is_neighbours */
+  /* assign space for the is_neigh at the pdu end */
+  is_neigh = (struct is_neigh*) lsppdu_realloc(lsp,MTYPE_ISIS_TLV, 
+					       sizeof(struct is_neigh)); 
+  /* add this node to our list */
+  listnode_add (lsp->tlv_data.is_neighs, is_neigh); 
+  /* FIXME: Do we need our designated address here? */
+  memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN + 1); 
+  /* FIXME: Where should we really get our own LSPs metrics from? */
+  circuit = (struct isis_circuit*)listhead(circuit_list);
+  /* is_neigh->metrics = circuit->metrics[lsp->level -1];*/
+  /* Length */
+  *(tlv_ptr+1)=(lsp->tlv_data.is_neighs->count * sizeof(struct is_neigh) +1); 
+
+  /* FIXME: scan for adjencecies and add them */
+
+  /* FIXME: add reachability info */
+
+  /* adding dynamic hostname if needed*/
+  if (area->dynhostname) {
+    tlv_ptr = lsppdu_realloc (lsp,MTYPE_ISIS_TLV, 2); /* the 2 is for the TL */
+    *tlv_ptr = DYNAMIC_HOSTNAME; /* Type */
+    *(tlv_ptr+1) = strlen (host.name); /* Length */
+    lsp->tlv_data.hostname = (struct hostname *)
+      (lsppdu_realloc(lsp,
+		      MTYPE_ISIS_TLV,
+		      /* the -1 is to fit the length in the struct */
+		      strlen (host.name)) - 1); 
+    memcpy (lsp->tlv_data.hostname->name, host.name, strlen(host.name));
+  }
+
+}
+
+/*
+ * 7.3.7 Generation on non-pseudonode LSPs
+ */
+int
+lsp_generate_non_pseudo (struct isis_area *area, int level) {
+
+  struct isis_lsp *oldlsp, *newlsp;
+  u_int32_t seq_num = 0;
+  u_char lspid[ISIS_SYS_ID_LEN + 2];
+
+  memset (&lspid, 0, ISIS_SYS_ID_LEN + 2);
+  memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN);
+
+  /* only builds the lsp if the area shares the level */
+  if ((area->is_type & level) == level) { 
+    oldlsp = lsp_search (lspid, area->lspdb[level-1]);
+    if (oldlsp) {
+      seq_num = ntohl (oldlsp->lsp_header->seq_num);
+      lsp_search_and_destroy (oldlsp->lsp_header->lsp_id, 
+                              area->lspdb[level-1]);
+      /* FIXME: we should actually initiate a purge */
+    }
+    newlsp = lsp_new (lspid, area->max_lsp_lifetime[level-1], seq_num, 
+                      area->is_type, 0, level);
+    newlsp->own_lsp = 1;
+    
+    lsp_insert (newlsp, area->lspdb[level-1]);
+    /* build_lsp_data (newlsp, area); */
+    lsp_build_nonpseudo (newlsp, area);
+    /* time to calculate our checksum */
+    lsp_seqnum_update (newlsp);
+  }
+
+
+  /* DEBUG_ADJ_PACKETS */
+  if (isis->debugs & DEBUG_ADJ_PACKETS) {
+    /* FIXME: is this place right? fix missing info */
+    zlog_info ("ISIS-Upd (%s): Building L%d LSP",
+               area->area_tag, level);
+  }
+
+  return ISIS_OK;
+}
+
+/*
+ * 7.3.9 Generation of level 1 LSPs (non-pseudonode)
+ */
+int
+lsp_l1_generate (struct isis_area *area)
+{
+  
+  area->t_lsp_refresh[0] = thread_add_timer (master, lsp_refresh_l1, area, 
+                                             MAX_LSP_GEN_INTERVAL);
+
+  return lsp_generate_non_pseudo (area, 1);
+}
+
+
+/*
+ * 7.3.9 Generation of level 2 LSPs (non-pseudonode)
+ */
+int
+lsp_l2_generate (struct isis_area *area)
+{
+  
+  area->t_lsp_refresh[1] = thread_add_timer (master, lsp_refresh_l2, area, 
+                                             MAX_LSP_GEN_INTERVAL);
+
+  return lsp_generate_non_pseudo (area, 2);
+}
+
+int
+lsp_non_pseudo_regenerate (struct isis_area *area, int level)
+{
+  dict_t *lspdb = area->lspdb[level - 1];
+  struct isis_lsp *lsp, *frag;
+  struct listnode *node;
+  u_char lspid[ISIS_SYS_ID_LEN + 2];
+
+  memset (lspid, 0, ISIS_SYS_ID_LEN + 2);
+  memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
+  
+  lsp = lsp_search (lspid, lspdb);
+  
+  if (!lsp) {
+    zlog_err ("ISIS-Upd (%s): lsp_non_pseudo_regenerate(): no L%d LSP found!",
+              area->area_tag,	      
+	      level);
+
+    return ISIS_ERROR;
+  }
+
+  lsp_clear_data (lsp);  
+  lsp_build_nonpseudo (lsp, area);
+  lsp->lsp_header->rem_lifetime = htons (isis_jitter 
+                                         (area->max_lsp_lifetime[level-1],
+                                          MAX_AGE_JITTER));
+  lsp_seqnum_update (lsp);
+    
+  if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+    zlog_info ("ISIS-Upd (%s): refreshing our L%d LSP %s, "
+	       "seq 0x%08x, cksum 0x%04x lifetime %us",
+	       area->area_tag,
+	       level,
+               rawlspid_print (lsp->lsp_header->lsp_id),
+	       ntohl(lsp->lsp_header->seq_num),
+	       ntohs(lsp->lsp_header->checksum),
+	       ntohs(lsp->lsp_header->rem_lifetime)); 
+  }
+
+  lsp->last_generated = time (NULL);
+  area->lsp_regenerate_pending[level - 1] = 0;
+  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+  for (node = listhead (lsp->lspu.frags); node; nextnode(node)) {
+    frag = getdata (node);
+    frag->lsp_header->rem_lifetime = htons (isis_jitter 
+                                         (area->max_lsp_lifetime[level-1],
+                                          MAX_AGE_JITTER));
+    ISIS_FLAGS_SET_ALL (frag->SRMflags);
+  }
+
+  if (area->ip_circuits)
+    isis_spf_schedule (area, level);
+#ifdef HAVE_IPV6
+  if (area->ipv6_circuits)
+    isis_spf_schedule6 (area, level);
+#endif
+  return ISIS_OK;
+}
+
+
+/*
+ * Done at least every MAX_LSP_GEN_INTERVAL. Search own LSPs, update holding
+ * time and set SRM
+ */
+int 
+lsp_refresh_l1 (struct thread *thread)
+{
+  struct isis_area *area;
+  unsigned long ref_time;
+
+  area = THREAD_ARG (thread);
+  assert (area);
+  
+  area->t_lsp_refresh[0] = NULL;
+  if (area->is_type & IS_LEVEL_1) 
+    lsp_non_pseudo_regenerate (area, 1);
+  
+  ref_time =  area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ? 
+    MAX_LSP_GEN_INTERVAL : area->lsp_refresh[0];
+
+  area->t_lsp_refresh[0] = thread_add_timer (master, lsp_refresh_l1, area,
+                                          isis_jitter (ref_time, 
+                                                       MAX_AGE_JITTER));
+  return ISIS_OK;
+}
+
+int 
+lsp_refresh_l2 (struct thread *thread)
+{
+  struct isis_area *area;
+  unsigned long ref_time;
+
+  area = THREAD_ARG (thread);
+  assert (area);
+  
+  area->t_lsp_refresh[1] = NULL;
+  if (area->is_type & IS_LEVEL_2) 
+    lsp_non_pseudo_regenerate (area, 2);
+
+  ref_time =  area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ? 
+    MAX_LSP_GEN_INTERVAL : area->lsp_refresh[1];
+
+
+  area->t_lsp_refresh[1] = thread_add_timer (master, lsp_refresh_l2, area,
+                                          isis_jitter (ref_time, 
+                                                       MAX_AGE_JITTER));
+  return ISIS_OK;
+}
+
+
+/*
+ * Something has changed -> regenerate LSP
+ */
+
+int
+lsp_l1_regenerate (struct thread *thread)
+{
+  struct isis_area *area;
+
+  area = THREAD_ARG (thread);
+  area->lsp_regenerate_pending[0] = 0;
+
+  return lsp_non_pseudo_regenerate (area, 1);
+}
+
+int
+lsp_l2_regenerate (struct thread *thread)
+{
+  struct isis_area *area;
+
+  area = THREAD_ARG (thread);
+  area->lsp_regenerate_pending[1] = 0;
+  
+  return lsp_non_pseudo_regenerate (area, 2);
+}
+
+int 
+lsp_regenerate_schedule (struct isis_area *area)
+{
+  struct isis_lsp *lsp;
+  u_char id[ISIS_SYS_ID_LEN + 2];
+  time_t now, diff;
+  memcpy(id, isis->sysid, ISIS_SYS_ID_LEN);
+  LSP_PSEUDO_ID(id) = LSP_FRAGMENT(id) = 0;
+  now = time (NULL);
+  /*
+   * First level 1
+   */
+  if (area->is_type & IS_LEVEL_1) {
+    lsp = lsp_search (id, area->lspdb[0]);
+    if (!lsp || area->lsp_regenerate_pending[0])
+      goto L2;
+    /*
+     * Throttle avoidance
+     */
+    diff = now - lsp->last_generated;
+    if (diff < MIN_LSP_GEN_INTERVAL) {
+      area->lsp_regenerate_pending[0] = 1;
+      thread_add_timer (master, lsp_l1_regenerate, area, 
+                        MIN_LSP_GEN_INTERVAL - diff);
+      return ISIS_OK;
+    } else
+      lsp_non_pseudo_regenerate (area, 1);
+  }
+  /*
+   * then 2
+   */
+ L2:
+  if (area->is_type & IS_LEVEL_2) {
+    lsp = lsp_search (id, area->lspdb[1]);
+    if (!lsp || area->lsp_regenerate_pending[1])
+      return ISIS_OK;
+    /*
+     * Throttle avoidance
+     */
+    diff = now - lsp->last_generated;
+    if (diff < MIN_LSP_GEN_INTERVAL) {
+      area->lsp_regenerate_pending[1] = 1;
+      thread_add_timer (master, lsp_l2_regenerate, area, 
+                        MIN_LSP_GEN_INTERVAL - diff);
+      return ISIS_OK;
+    } else
+      lsp_non_pseudo_regenerate (area, 2); 
+  }
+    
+  return ISIS_OK; 
+}
+
+/*
+ * Funcs for pseudonode LSPs
+ */
+
+/*
+ * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs 
+ */
+void
+lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit, 
+                  int level)
+{
+  struct isis_adjacency *adj;
+  struct is_neigh *is_neigh;
+  struct es_neigh *es_neigh;
+  struct list *adj_list;
+  struct listnode *node;
+  struct isis_passwd *passwd;
+
+  assert (circuit);
+  assert (circuit->circ_type == CIRCUIT_T_BROADCAST);
+  
+  if (!circuit->u.bc.is_dr[level - 1])
+    return; /* we are not DIS on this circuit */
+  
+  lsp->level = level;
+  if (level == 1)
+    lsp->lsp_header->lsp_bits |= IS_LEVEL_1;
+  else
+    lsp->lsp_header->lsp_bits |= IS_LEVEL_2;
+
+  /*
+   * add self to IS neighbours 
+   */
+  if (lsp->tlv_data.is_neighs == NULL) {
+    lsp->tlv_data.is_neighs = list_new ();
+    lsp->tlv_data.is_neighs->del = free_tlv;
+  }
+  is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+  memset (is_neigh, 0, sizeof (struct is_neigh));
+  memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
+  listnode_add (lsp->tlv_data.is_neighs, is_neigh);
+  
+  adj_list = list_new();
+  isis_adj_build_up_list (circuit->u.bc.adjdb[level-1], adj_list);
+  
+  for (node = listhead (adj_list); node; nextnode (node)){
+    adj = getdata (node);
+    if (adj->circuit_t & level) {
+      if ((level == 1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) ||
+          (level == 1 && adj->sys_type == ISIS_SYSTYPE_L2_IS &&
+           adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
+          (level == 2 && adj->sys_type == ISIS_SYSTYPE_L2_IS)) {
+        /* an IS neighbour -> add it */
+        is_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh));
+        memset (is_neigh, 0, sizeof (struct is_neigh));
+        memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN);
+        listnode_add (lsp->tlv_data.is_neighs, is_neigh);
+      } else if (level == 1 && adj->sys_type == ISIS_SYSTYPE_ES) {
+        /* an ES neigbour add it, if we are building level 1 LSP */
+        /* FIXME: the tlv-format is hard to use here */
+        if (lsp->tlv_data.es_neighs == NULL) {
+          lsp->tlv_data.es_neighs = list_new ();
+          lsp->tlv_data.es_neighs->del = free_tlv;
+        }
+        es_neigh = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh));
+        memset (es_neigh, 0, sizeof (struct es_neigh));
+        memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN);
+        listnode_add (lsp->tlv_data.es_neighs, is_neigh);
+      }
+    }
+  }
+  
+  stream_set_putp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+  /*
+   * Add the authentication info if it's present
+   */
+  (level == 1) ? (passwd = &circuit->area->area_passwd) : 
+                 (passwd = &circuit->area->domain_passwd);
+  if (passwd->type) {
+    memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd));
+    tlv_add_authinfo (passwd->type, passwd->len,
+		      passwd->passwd, lsp->pdu);
+  }
+
+  if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0)
+    tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu);
+
+  if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0)
+    tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu);
+
+  lsp->lsp_header->pdu_len = htons (stream_get_putp (lsp->pdu));
+  iso_csum_create (STREAM_DATA (lsp->pdu) + 12, 
+                   ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+  
+  list_delete (adj_list);
+
+  return;
+}
+
+int
+lsp_pseudo_regenerate (struct isis_circuit *circuit, int level)
+{
+  dict_t *lspdb = circuit->area->lspdb[level - 1];
+  struct isis_lsp *lsp;
+  u_char lsp_id[ISIS_SYS_ID_LEN + 2];
+  
+  memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
+  LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id;
+  LSP_FRAGMENT(lsp_id) = 0;
+  
+  lsp = lsp_search (lsp_id, lspdb);
+  
+  if (!lsp) {
+    zlog_err ("lsp_pseudo_regenerate(): no l%d LSP %s found!", level,
+              rawlspid_print(lsp_id));
+    return ISIS_ERROR;
+  }
+  lsp_clear_data (lsp);  
+
+  lsp_build_pseudo (lsp, circuit, level);
+
+  lsp->lsp_header->rem_lifetime = 
+    htons (isis_jitter (circuit->area->max_lsp_lifetime[level - 1],
+                        MAX_AGE_JITTER));
+
+  lsp_inc_seqnum (lsp, 0);
+    
+  if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+    zlog_info ("ISIS-Upd (%s): refreshing pseudo LSP L%d %s", 
+               circuit->area->area_tag, level,
+               rawlspid_print (lsp->lsp_header->lsp_id)); 
+  }
+
+  lsp->last_generated = time (NULL);
+  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+    
+  return ISIS_OK;
+}
+
+
+int
+lsp_l1_refresh_pseudo (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  int retval;
+  unsigned long ref_time;
+
+  circuit = THREAD_ARG(thread);
+  
+  if (!circuit->u.bc.is_dr[0])
+    return ISIS_ERROR; /* FIXME: purge and such */
+  
+  retval = lsp_pseudo_regenerate (circuit, 1);
+  
+  ref_time =  circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ? 
+    MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
+
+  circuit->u.bc.t_refresh_pseudo_lsp[0] = 
+    thread_add_timer (master, lsp_l1_refresh_pseudo, circuit, 
+                      isis_jitter (ref_time,
+                                   MAX_AGE_JITTER));
+  return retval;
+}
+
+int 
+lsp_l1_pseudo_generate (struct isis_circuit *circuit)
+{
+  struct isis_lsp *lsp;
+  u_char id[ISIS_SYS_ID_LEN + 2];
+  unsigned long ref_time;
+
+  memcpy(id, isis->sysid, ISIS_SYS_ID_LEN);
+  LSP_FRAGMENT(id) = 0;
+  LSP_PSEUDO_ID(id) = circuit->circuit_id;
+
+  /*
+   * If for some reason have a pseudo LSP in the db already -> regenerate
+   */
+  if (lsp_search (id, circuit->area->lspdb[0]))
+    return lsp_pseudo_regenerate (circuit, 1);
+  lsp = lsp_new (id, circuit->area->max_lsp_lifetime[0],
+                 1, circuit->area->is_type, 0, 1);
+  
+  lsp_build_pseudo (lsp, circuit, 1);
+  
+  lsp->own_lsp = 1;
+  lsp_insert (lsp, circuit->area->lspdb[0]);
+  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+
+  ref_time =  circuit->area->lsp_refresh[0] > MAX_LSP_GEN_INTERVAL ? 
+    MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[0];
+
+  
+  circuit->u.bc.t_refresh_pseudo_lsp[0] = 
+    thread_add_timer (master, lsp_l1_refresh_pseudo, circuit, 
+                      isis_jitter (ref_time,
+                                   MAX_AGE_JITTER));
+
+  return lsp_regenerate_schedule (circuit->area);
+}
+
+int
+lsp_l2_refresh_pseudo (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  int retval;
+  unsigned long ref_time;
+  circuit = THREAD_ARG(thread);
+  
+  if (!circuit->u.bc.is_dr[1])
+    return ISIS_ERROR; /* FIXME: purge and such */
+  
+  retval = lsp_pseudo_regenerate (circuit, 2);
+
+  ref_time =  circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ? 
+    MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
+
+
+  circuit->u.bc.t_refresh_pseudo_lsp[1] = 
+    thread_add_timer (master, lsp_l2_refresh_pseudo, circuit, 
+                      isis_jitter (ref_time,
+                                   MAX_AGE_JITTER));
+  return retval;
+}
+
+
+int 
+lsp_l2_pseudo_generate (struct isis_circuit *circuit)
+{
+  struct isis_lsp *lsp;
+  u_char id[ISIS_SYS_ID_LEN + 2];
+  unsigned long ref_time;
+
+  memcpy(id, isis->sysid, ISIS_SYS_ID_LEN);
+  LSP_FRAGMENT(id) = 0;
+  LSP_PSEUDO_ID(id) = circuit->circuit_id;
+
+  if (lsp_search (id, circuit->area->lspdb[1]))
+    return lsp_pseudo_regenerate (circuit, 2);
+
+  lsp = lsp_new (id, circuit->area->max_lsp_lifetime[1],
+                 1, circuit->area->is_type, 0, 2);
+
+  lsp_build_pseudo (lsp, circuit, 2);
+  
+  ref_time =  circuit->area->lsp_refresh[1] > MAX_LSP_GEN_INTERVAL ? 
+    MAX_LSP_GEN_INTERVAL : circuit->area->lsp_refresh[1];
+
+
+  lsp->own_lsp = 1;
+  lsp_insert (lsp, circuit->area->lspdb[1]);
+  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+      
+  circuit->u.bc.t_refresh_pseudo_lsp[1] = 
+    thread_add_timer (master, lsp_l2_refresh_pseudo, circuit, 
+                      isis_jitter (ref_time,
+                                   MAX_AGE_JITTER));
+  
+  return lsp_regenerate_schedule (circuit->area);
+}
+
+
+
+/*
+ * Walk through LSPs for an area
+ *  - set remaining lifetime
+ *  - set LSPs with SRMflag set for sending
+ */
+int 
+lsp_tick (struct thread *thread)
+{
+  struct isis_area *area;
+  struct isis_circuit *circuit;
+  struct isis_lsp *lsp;
+  struct list *lsp_list;
+  struct listnode *lspnode, *cnode;
+  dnode_t *dnode, *dnode_next;
+  int level;
+
+  lsp_list = list_new ();
+  
+  area = THREAD_ARG (thread);
+  assert (area);
+  area->t_tick = thread_add_timer (master, lsp_tick, area, 1);
+
+  /*
+   * Build a list of LSPs with (any) SRMflag set
+   * and removed the ones that have aged out
+   */
+  for (level = 0; level < ISIS_LEVELS; level++) {
+    if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0) {
+      dnode = dict_first (area->lspdb[level]);
+      while (dnode != NULL) {
+        dnode_next = dict_next (area->lspdb[level], dnode);
+        lsp = dnode_get (dnode);
+        lsp_set_time (lsp);
+        if (lsp->age_out == 0) {
+
+          zlog_info ("ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
+		     area->area_tag,
+		     lsp->level,
+		     rawlspid_print (lsp->lsp_header->lsp_id),
+		     ntohl(lsp->lsp_header->seq_num));
+
+          lsp_destroy (lsp);
+          dict_delete (area->lspdb[level], dnode);
+        } else if (flags_any_set (lsp->SRMflags))
+          listnode_add (lsp_list, lsp);
+        dnode = dnode_next;
+      }
+
+      /*
+       * Send LSPs on circuits indicated by the SRMflags
+       */
+      if (listcount (lsp_list) > 0) {
+        for (cnode = listhead (area->circuit_list); cnode; nextnode (cnode)) {
+          circuit = getdata (cnode);
+          for (lspnode = listhead (lsp_list); lspnode; nextnode (lspnode)) {
+            lsp = getdata (lspnode);
+            if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit)) {
+							/* FIXME: if same or elder lsp is already in lsp queue */
+							listnode_add (circuit->lsp_queue, lsp);			
+              thread_add_event (master, send_lsp, circuit, 0);
+            }
+          }
+        }
+      }
+      list_delete_all_node (lsp_list);
+    }
+  }
+
+  list_delete (lsp_list);
+
+  return ISIS_OK;
+}
+
+
+void
+lsp_purge_dr (u_char *id, struct isis_circuit *circuit, int level)
+{
+  struct isis_lsp *lsp;
+  
+  lsp = lsp_search (id, circuit->area->lspdb[level - 1]);
+  
+  if (lsp && lsp->purged == 0) {
+    lsp->lsp_header->rem_lifetime = htons (0);
+    lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+    lsp->purged = 0;
+    iso_csum_create (STREAM_DATA (lsp->pdu) + 12, 
+                     ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+    ISIS_FLAGS_SET_ALL(lsp->SRMflags);
+  } 
+    
+    
+  return;
+}
+
+/*
+ * Purge own LSP that is received and we don't have. 
+ * -> Do as in 7.3.16.4
+ */
+void
+lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr, 
+                     struct isis_area *area)
+{
+  struct isis_lsp *lsp;
+
+  /*
+   * We need to create the LSP to be purged 
+   */
+  zlog_info ("LSP PURGE NON EXIST");
+  lsp = XMALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
+  memset (lsp, 0, sizeof (struct isis_lsp));
+  /*FIXME: BUG BUG BUG! the lsp doesn't exist here!*/
+  /*did smt here, maybe good probably not*/
+  lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? 1 : 2;
+  lsp->pdu = stream_new (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+  lsp->isis_header = (struct isis_fixed_hdr*)STREAM_DATA(lsp->pdu);
+  fill_fixed_hdr (lsp->isis_header, (lsp->level == 1) ? L1_LINK_STATE
+                  : L2_LINK_STATE);
+  lsp->lsp_header = (struct isis_link_state_hdr*)(STREAM_DATA(lsp->pdu) +
+                                                  ISIS_FIXED_HDR_LEN);  
+  memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
+  
+  /*
+   * Retain only LSP header
+   */
+  lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
+  /*
+   * Set the remaining lifetime to 0
+   */
+  lsp->lsp_header->rem_lifetime = 0;
+  /*
+   * Put the lsp into LSPdb
+   */
+  lsp_insert (lsp, area->lspdb[lsp->level-1]);
+
+  /*
+   * Send in to whole area
+   */
+  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+  
+  return;
+}
+
+#ifdef TOPOLOGY_GENERATE
+int
+top_lsp_refresh (struct thread *thread)
+{
+  struct isis_lsp  *lsp;
+
+  lsp = THREAD_ARG (thread);
+  assert (lsp);
+
+  lsp->t_lsp_top_ref = NULL;
+
+  lsp->lsp_header->rem_lifetime = htons (isis_jitter(MAX_AGE,MAX_AGE_JITTER));
+  lsp->lsp_header->seq_num = htonl(ntohl(lsp->lsp_header->seq_num) +1);
+
+  ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+  if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+    zlog_info ("ISIS-Upd (): refreshing Topology L1 %s", 
+               rawlspid_print (lsp->lsp_header->lsp_id));
+  }
+
+  /* time to calculate our checksum */
+  iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
+                   ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+
+  lsp->t_lsp_top_ref = thread_add_timer (master, top_lsp_refresh, lsp,
+                                         isis_jitter (MAX_LSP_GEN_INTERVAL,
+                                                      MAX_LSP_GEN_JITTER));
+
+  return ISIS_OK;
+}
+
+void
+generate_topology_lsps (struct isis_area *area)
+{
+  struct listnode *node;
+  int i, max = 0;
+  struct arc *arc;
+  u_char lspid[ISIS_SYS_ID_LEN + 2];
+  struct isis_lsp *lsp;
+
+  /* first we find the maximal node */
+  LIST_LOOP (area->topology, arc, node) {
+    if (arc->from_node > max) max = arc->from_node;
+    if (arc->to_node > max) max = arc->to_node;
+  }
+
+
+  for (i = 1; i < (max+1); i++) {
+    memcpy (lspid,area->topology_baseis,ISIS_SYS_ID_LEN);
+    LSP_PSEUDO_ID (lspid) = 0x00;
+    LSP_FRAGMENT (lspid) = 0x00;
+    lspid[ISIS_SYS_ID_LEN-1] = (i & 0xFF);
+    lspid[ISIS_SYS_ID_LEN-2] = ((i >> 8) & 0xFF);
+
+    lsp = lsp_new (lspid, isis_jitter (area->max_lsp_lifetime[0],
+				       MAX_AGE_JITTER), 1, IS_LEVEL_1, 0, 1);
+    lsp->from_topology = 1;
+    /* creating data based on topology */
+    build_topology_lsp_data (lsp,area,i);
+    /* time to calculate our checksum */
+    iso_csum_create (STREAM_DATA (lsp->pdu) + 12,
+		     ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+    lsp->t_lsp_top_ref = thread_add_timer (master, top_lsp_refresh, lsp,
+					   isis_jitter(MAX_LSP_GEN_INTERVAL,
+						       MAX_LSP_GEN_JITTER));
+
+    ISIS_FLAGS_SET_ALL(lsp->SRMflags);
+    lsp_insert (lsp,area->lspdb[0]);
+
+  }
+}
+
+void
+remove_topology_lsps (struct isis_area *area)
+{
+  struct isis_lsp *lsp;
+  dnode_t *dnode, *dnode_next;
+
+  dnode = dict_first (area->lspdb[0]);
+  while (dnode != NULL) {
+    dnode_next = dict_next (area->lspdb[0], dnode);
+    lsp = dnode_get (dnode);
+    if (lsp->from_topology) {
+      thread_cancel(lsp->t_lsp_top_ref);
+      lsp_destroy (lsp);
+      dict_delete (area->lspdb[0], dnode);
+    }
+    dnode = dnode_next;
+  }
+}
+
+void
+build_topology_lsp_data (struct isis_lsp *lsp, struct isis_area *area, 
+			 int lsp_top_num)
+{
+  struct listnode *node;
+  struct arc *arc;
+  u_char *tlv_ptr;
+  struct is_neigh *is_neigh;
+  int to_lsp = 0;
+  char buff[200];
+
+  /* add our nlpids */
+  /* the 2 is for the TL plus 1 for the nlpid*/
+  tlv_ptr = lsppdu_realloc (lsp,MTYPE_ISIS_TLV, 3); 
+  *tlv_ptr = PROTOCOLS_SUPPORTED; /* Type */
+  *(tlv_ptr+1) = 1; /* one protocol */
+  *(tlv_ptr+2) =  NLPID_IP;
+  lsp->tlv_data.nlpids = (struct nlpids*)(tlv_ptr+1); 
+
+  /* first, lets add the tops */
+  /* the 2 is for the TL plus 1 for the virtual field*/
+  tlv_ptr = lsppdu_realloc (lsp ,MTYPE_ISIS_TLV, 3);
+  *tlv_ptr = IS_NEIGHBOURS; /* Type */
+  *(tlv_ptr+1) = 1; /* this is the virtual char len*/
+  *(tlv_ptr+2) = 0; /* virtual is zero */
+  lsp->tlv_data.is_neighs = list_new (); /* new list of is_neighbours */
+
+  /* add reachability for this IS for simulated 1 */
+  if (lsp_top_num == 1) {
+    /* assign space for the is_neigh at the pdu end */
+    is_neigh = (struct is_neigh*) lsppdu_realloc(lsp, MTYPE_ISIS_TLV, 
+						 sizeof(struct is_neigh)); 
+    /* add this node to our list */
+    listnode_add (lsp->tlv_data.is_neighs, is_neigh); 
+    memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN);
+    LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
+    is_neigh->metrics.metric_default = 0x00; /* no special reason */
+    is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
+    is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
+    is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
+    /* don't forget the length */
+    *(tlv_ptr+1) += IS_NEIGHBOURS_LEN; /* the -1 is the virtual */
+    /* no need to check for fragging here, it is a lonely is_reach */
+  }
+
+  /* addding is reachabilities */
+  LIST_LOOP (area->topology, arc, node) {
+    if ((arc->from_node == lsp_top_num) ||
+        (arc->to_node   == lsp_top_num)) {
+      if (arc->to_node   == lsp_top_num) to_lsp = arc->from_node;
+      if (arc->from_node == lsp_top_num) to_lsp = arc->to_node;
+
+      /* if the length here is about to cross the FF limit, we reTLV */
+      if (*(tlv_ptr+1) >= (0xFF - IS_NEIGHBOURS_LEN)) {
+        /* retlv */
+	/* the 2 is for the TL plus 1 for the virtual field*/
+        tlv_ptr = lsppdu_realloc(lsp,MTYPE_ISIS_TLV, 3); 
+        *tlv_ptr = IS_NEIGHBOURS; /* Type */
+        *(tlv_ptr+1) = 1; /* this is the virtual char len*/
+        *(tlv_ptr+2) = 0; /* virtual is zero */
+      }
+      /* doing this here assures us that we won't add an "empty" tlv */
+      /* assign space for the is_neigh at the pdu end */
+      is_neigh = (struct is_neigh*) lsppdu_realloc (lsp, MTYPE_ISIS_TLV, 
+						    sizeof(struct is_neigh));
+      /* add this node to our list */
+      listnode_add (lsp->tlv_data.is_neighs, is_neigh); 
+      memcpy (&is_neigh->neigh_id, area->topology_baseis, ISIS_SYS_ID_LEN);
+      LSP_PSEUDO_ID (is_neigh->neigh_id) = 0x00;
+      is_neigh->neigh_id[ISIS_SYS_ID_LEN-1] = (to_lsp & 0xFF);
+      is_neigh->neigh_id[ISIS_SYS_ID_LEN-2] = ((to_lsp >> 8) & 0xFF);
+      is_neigh->metrics.metric_default = arc->distance;
+      is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED;
+      is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED;
+      is_neigh->metrics.metric_error = METRICS_UNSUPPORTED;
+      /* don't forget the length */
+      *(tlv_ptr+1) += IS_NEIGHBOURS_LEN; /* the -1 is the virtual */
+    }
+  }
+
+  /* adding dynamic hostname if needed*/
+  if (area->dynhostname) {
+    memset (buff,0x00,200);
+    sprintf (buff,"feedme%d",lsp_top_num);
+    tlv_ptr = lsppdu_realloc (lsp,MTYPE_ISIS_TLV, 2); /* the 2 is for the TL */
+    *tlv_ptr = DYNAMIC_HOSTNAME; /* Type */
+    *(tlv_ptr+1) = strlen (buff); /* Length */
+    /* the -1 is to fit the length in the struct */
+    lsp->tlv_data.hostname = (struct hostname *)
+      (lsppdu_realloc (lsp, MTYPE_ISIS_TLV, strlen(buff)) - 1);
+    memcpy (lsp->tlv_data.hostname->name, buff, strlen(buff));
+  }
+
+  /* thanks to hannes, another bug bites the dust */
+  lsp->pdu->putp = ntohs(lsp->lsp_header->pdu_len);
+  lsp->pdu->endp = ntohs(lsp->lsp_header->pdu_len);
+}
+#endif /* TOPOLOGY_GENERATE */
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
new file mode 100644
index 0000000..71a7508
--- /dev/null
+++ b/isisd/isis_lsp.h
@@ -0,0 +1,132 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_lsp.h   
+ *                             LSP processing
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_LSP_H
+#define _ZEBRA_ISIS_LSP_H
+
+/* The grand plan is to support 1024 circuits so we have 32*32 bit flags
+ * the support will be achived using the newest drafts */
+#define ISIS_MAX_CIRCUITS 32 /* = 1024 */ /*FIXME:defined in flags.h as well*/
+
+/* Structure for isis_lsp, this structure will only support the fixed
+ * System ID (Currently 6) (atleast for now). In order to support more
+ * We will have to split the header into two parts, and for readability
+ * sake it should better be avoided */
+struct isis_lsp
+{
+  struct isis_fixed_hdr *isis_header;       /* normally equals pdu */
+  struct isis_link_state_hdr *lsp_header;   /* pdu + isis_header_len */
+  struct stream *pdu;                       /* full pdu lsp */
+  union {
+    struct list *frags;
+    struct isis_lsp *zero_lsp;
+  } lspu;
+  u_int32_t SRMflags[ISIS_MAX_CIRCUITS];
+  u_int32_t SSNflags[ISIS_MAX_CIRCUITS];
+  u_int32_t rexmit_queue[ISIS_MAX_CIRCUITS];
+  int level;                                /* L1 or L2? */
+  int purged;                               /* have purged this one */
+  int scheduled;                            /* scheduled for sending */
+  time_t installed;
+  time_t last_generated;
+  time_t last_sent;
+  int own_lsp;
+#ifdef TOPOLOGY_GENERATE
+  int from_topology;
+  struct thread *t_lsp_top_ref;
+#endif
+  /* used for 60 second counting when rem_lifetime is zero */
+  int age_out; 
+  struct isis_adjacency *adj;
+  struct tlvs tlv_data;                     /* Simplifies TLV access */
+};
+
+dict_t *lsp_db_init (void);
+void lsp_db_destroy (dict_t *lspdb);
+int lsp_tick (struct thread *thread);
+
+int lsp_l1_generate (struct isis_area *area);
+int lsp_l2_generate (struct isis_area *area);
+int lsp_refresh_l1 (struct thread *thread);
+int lsp_refresh_l2 (struct thread *thread);
+int lsp_regenerate_schedule (struct isis_area *area);
+
+int lsp_l1_pseudo_generate (struct isis_circuit *circuit);
+int lsp_l2_pseudo_generate (struct isis_circuit *circuit);
+int lsp_l1_refresh_pseudo  (struct thread *thread);
+int lsp_l2_refresh_pseudo  (struct thread *thread);
+int isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area,
+			     int  pdulen, struct isis_passwd *passwd);
+struct isis_lsp *lsp_new (u_char *lsp_id, u_int16_t rem_lifetime, 
+                          u_int32_t seq_num, u_int8_t lsp_bits, 
+                          u_int16_t checksum, int level);
+struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream, 
+					  u_int16_t pdu_len,  
+                                          struct isis_lsp *lsp0, 
+                                          struct isis_area *area);
+void lsp_insert (struct isis_lsp *lsp, dict_t *lspdb);
+struct isis_lsp *lsp_search (u_char *id, dict_t *lspdb);
+
+void lsp_build_list (u_char *start_id, u_char *stop_id, 
+                     struct list *list, dict_t *lspdb);
+void lsp_build_list_nonzero_ht (u_char *start_id, u_char *stop_id, 
+                                struct list *list, dict_t *lspdb);
+void lsp_build_list_ssn (struct isis_circuit *circuit, struct list *list, 
+                         dict_t *lspdb);
+
+void lsp_search_and_destroy (u_char *id, dict_t *lspdb);
+void lsp_purge_dr (u_char *id, struct isis_circuit *circuit, int level);
+void lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr, 
+                          struct isis_area *area);
+
+#define LSP_EQUAL 1
+#define LSP_NEWER 2
+#define LSP_OLDER 3
+
+#define LSP_PSEUDO_ID(I) ((u_char)(I)[ISIS_SYS_ID_LEN])
+#define LSP_FRAGMENT(I) ((u_char)(I)[ISIS_SYS_ID_LEN + 1])
+#define OWNLSPID(I) \
+        memcpy ((I), isis->sysid, ISIS_SYS_ID_LEN);\
+        (I)[ISIS_SYS_ID_LEN] = 0;\
+        (I)[ISIS_SYS_ID_LEN + 1] = 0
+int lsp_id_cmp (u_char *id1, u_char *id2);
+int lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, 
+                 u_int16_t checksum, u_int16_t rem_lifetime);
+void lsp_update (struct isis_lsp *lsp, struct isis_link_state_hdr *lsp_hdr,
+                 struct stream *stream, struct isis_area *area);
+void lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num);
+int lsp_print_all (struct vty *vty, dict_t *lspdb, char detail, char dynhost);
+char *lsp_bits2string (u_char *);
+
+/* staticly assigned vars for printing purposes */
+char lsp_bits_string[200]; /* FIXME: enough ? */
+
+#ifdef TOPOLOGY_GENERATE
+void generate_topology_lsps (struct isis_area *area);
+void remove_topology_lsps (struct isis_area *area);
+void build_topology_lsp_data (struct isis_lsp *lsp,
+            struct isis_area *area, int lsp_top_num);
+#endif /* TOPOLOGY_GENERATE */
+
+#endif /* ISIS_LSP */
+
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
new file mode 100644
index 0000000..baf5f38
--- /dev/null
+++ b/isisd/isis_main.c
@@ -0,0 +1,330 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_main.c
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "getopt.h"
+#include "thread.h"
+#include "log.h"
+#include "version.h"
+#include "command.h"
+#include "vty.h"
+#include "memory.h"
+#include "stream.h"
+#include "if.h"
+
+#include "isisd/dict.h"
+#include "include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_dynhn.h"
+
+/* Default configuration file name */
+#define ISISD_DEFAULT_CONFIG "isisd.conf"
+/* Default vty port */
+#define ISISD_VTY_PORT       2607
+
+/* isisd options */
+struct option longopts[] = 
+{
+  { "daemon",      no_argument,       NULL, 'd'},
+  { "config_file", required_argument, NULL, 'f'},
+  { "vty_port",    required_argument, NULL, 'P'},
+  { "version",     no_argument,       NULL, 'v'},
+  { "help",        no_argument,       NULL, 'h'},
+  { 0 }
+};
+
+/* Configuration file and directory. */
+char config_current[] = ISISD_DEFAULT_CONFIG;
+char config_default[] = SYSCONFDIR ISISD_DEFAULT_CONFIG;
+char *config_file = NULL;
+
+/* isisd program name. */
+char *progname;
+
+int daemon_mode = 0;
+
+/* Master of threads. */
+struct thread_master *master;
+
+
+/* for reload */
+char _cwd[64];
+char _progpath[64];
+int _argc;
+char **_argv;
+char **_envp;
+
+
+/* Help information display. */
+static void
+usage (int status)
+{
+  if (status != 0)
+    fprintf (stderr, "Try `%s --help' for more information.\n", progname);
+  else
+    {    
+      printf ("Usage : %s [OPTION...]\n\n\
+Daemon which manages IS-IS routing\n\n\
+-d, --daemon       Runs in daemon mode\n\
+-f, --config_file  Set configuration file name\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 sambo@cs.tut.fi\n", progname);
+    }
+
+  exit (status);
+}
+
+
+void
+reload ()
+{
+  zlog_info ("Reload");
+  /* FIXME: Clean up func call here */
+  vty_finish ();
+  execve (_progpath, _argv, _envp);
+}
+
+void
+terminate (int i)
+{
+  exit (i);
+}
+
+/*
+ * Signal handlers
+ */
+void 
+sighup (int sig)
+{
+  zlog_info ("SIGHUP received");
+  reload ();
+
+  return;
+}
+
+void
+sigint (int sig)
+{
+  zlog_info ("SIGINT received");
+  terminate (0);
+  
+  return;
+}
+
+void
+sigterm (int sig)
+{
+  zlog_info ("SIGTERM received");
+  terminate (0);
+}
+
+void
+sigusr1 (int sig)
+{
+  zlog_info ("SIGUSR1 received");
+  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);
+}
+
+void
+signal_init ()
+{
+  signal_set (SIGHUP, sighup);
+  signal_set (SIGINT, sigint);
+  signal_set (SIGTERM, sigterm);
+  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);
+}
+
+/*
+ * Main routine of isisd. Parse arguments and handle IS-IS state machine.
+ */
+int 
+main (int argc, char **argv, char **envp)
+{
+  char *p;
+  int opt, vty_port = ISISD_VTY_PORT;
+  struct thread thread;
+  char *config_file = NULL;
+  char *vty_addr = NULL;
+
+  /* Get the programname without the preceding path. */
+  progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
+
+  zlog_default = openzlog (progname, ZLOG_NOLOG, ZLOG_ISIS,
+                           LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+
+  
+  /* for reload */
+  _argc = argc;
+  _argv = argv;
+  _envp = envp;
+  getcwd (_cwd, sizeof (_cwd));
+  if (*argv[0] == '.')
+    snprintf (_progpath, sizeof (_progpath), "%s/%s", _cwd, _argv[0]);
+  else
+    snprintf (_progpath, sizeof (_progpath), "%s", argv[0]);
+  
+  /* Command line argument treatment. */
+  while (1) 
+    {
+      opt = getopt_long (argc, argv, "df:hAp: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 'P':
+          vty_port = atoi (optarg);
+          break;
+        case 'v':
+	  printf("ISISd version %s\n", ISISD_VERSION);
+	  printf("Copyright (c) 2001-2002 Sampo Saaristo,"
+		 " Ofer Wald and Hannes Gredler\n");
+          print_version ("Zebra");
+          exit (0);
+          break;
+        case 'h':
+          usage (0);
+          break;
+        default:
+          usage (1);
+          break;
+        }
+    }
+  
+  /* thread master */
+  master = thread_master_create ();
+
+  /* random seed from time */
+  srand(time(NULL));
+
+  /*
+   *  initializations
+   */
+  signal_init ();
+  cmd_init (1);
+  vty_init ();
+  memory_init ();
+  isis_init ();
+  dyn_cache_init ();
+  sort_node ();
+
+  /* parse config file */ 
+  /* this is needed three times! because we have interfaces before the areas */
+  vty_read_config (config_file, config_current, config_default);
+#if 0
+  vty_read_config (config_file, config_current, config_default);
+  vty_read_config (config_file, config_current, config_default);
+#endif
+  /* demonize */
+  if (daemon_mode)
+    daemon (0, 0);
+
+  /* Problems with the build env ?*/
+#ifndef PATH_ISISD_PID
+#define PATH_ISISD_PID "/var/run/isisd.pid"
+#endif
+  /* Process ID file creation. */
+  pid_output (PATH_ISISD_PID);
+
+  /* Make isis vty socket. */
+  vty_serv_sock (vty_addr, vty_port ? vty_port : ISISD_VTY_PORT, 
+                 ISIS_VTYSH_PATH);
+  
+  /* Print banner. */
+  zlog_info ("ISISd %s starting: vty@%d", ZEBRA_VERSION, vty_port);
+#ifdef HAVE_IPV6
+  zlog_info ("IPv6 enabled");
+#endif
+  /* Start finite state machine. */
+  while (thread_fetch (master, &thread))
+    thread_call (&thread);
+
+  /* Not reached. */
+  exit (0);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
new file mode 100644
index 0000000..763ae24
--- /dev/null
+++ b/isisd/isis_misc.c
@@ -0,0 +1,438 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_misc.h
+ *                             Miscellanous routines
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <ctype.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+
+#include "stream.h"
+#include "vty.h"
+#include "hash.h"
+#include "if.h"
+
+#include "isisd/dict.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_misc.h"
+
+#include "isisd/isis_tlv.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_adjacency.h"
+
+/*
+ * This converts the isonet to its printable format
+ */
+char * isonet_print (u_char *from, int len) {
+  int i = 0;
+  char *pos = isonet;
+
+  if(!from)
+    return "unknown";
+
+  while (i < len) {
+    if (i & 1) {
+      sprintf ( pos, "%02x", *(from + i));
+      pos += 2;
+    } else {
+      if (i == 0) { /* if the area addr is just one byte, eg. 47. */
+        sprintf ( pos, "%02x", *(from + i));
+        pos += 2;
+      } else {
+        sprintf ( pos, "%02x.", *(from + i));
+        pos += 3;
+      }
+    }
+    i++;
+  }
+  *(pos) = '\0';
+  return isonet;
+}
+
+/*
+ * Returns 0 on error, length of buff on ok
+ * extract dot from the dotted str, and insert all the number in a buff 
+ */
+int
+dotformat2buff (u_char *buff, u_char *dotted)
+{
+  int dotlen, len = 0;
+  u_char *pos = dotted;
+  u_char number[3];
+  int nextdotpos = 2;
+
+  number[2] = '\0';
+  dotlen = strlen(dotted);
+  if (dotlen > 50) {
+    /* this can't be an iso net, its too long */
+    return 0;
+  }
+
+  while ( (pos - dotted) < dotlen && len < 20 ) {
+    if (*pos == '.') {
+      /* we expect the . at 2, and than every 5 */
+      if ((pos - dotted) != nextdotpos) {
+        len = 0;
+        break;
+      }
+      nextdotpos += 5;
+      pos++;
+      continue;
+    }
+    /* we must have at least two chars left here */
+    if (dotlen - (pos - dotted) < 2) {
+      len = 0;
+      break;
+    }
+
+    if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos+1)))){
+      memcpy (number, pos ,2);
+      pos+=2;
+    } else {
+      len = 0;
+      break;
+    }
+
+    *(buff + len) = (char)strtol(number, NULL, 16);
+    len++;
+  }
+  
+  return len;
+}
+/*
+ * conversion of XXXX.XXXX.XXXX to memory
+ */
+int
+sysid2buff (u_char *buff, u_char *dotted)
+ {
+  int len = 0;
+  u_char *pos = dotted;
+  u_char number[3];
+
+  number[2] = '\0';
+  // surely not a sysid_string if not 14 length
+  if (strlen(dotted) != 14) {
+    return 0;
+  }
+
+  while ( len < ISIS_SYS_ID_LEN ) {
+    if (*pos == '.') {
+      /* the . is not positioned correctly */
+      if (((pos - dotted) !=4) && ((pos - dotted) != 9)) { 
+        len = 0;
+        break;
+      }
+      pos++;
+      continue;
+    }
+    if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos+1)))){
+      memcpy (number, pos ,2);
+      pos+=2;
+    } else {
+      len = 0;
+      break;
+    }
+
+    *(buff + len) = (char)strtol(number, NULL, 16);
+    len++;
+  }
+
+  return len;
+
+}
+
+/*
+ * converts the nlpids struct (filled by TLV #129)
+ * into a string
+ */
+
+char *
+nlpid2string (struct nlpids *nlpids) {
+  char *pos = nlpidstring;
+  int i;
+
+  for (i=0;i<nlpids->count;i++) {
+    switch (nlpids->nlpids[i]) {
+    case NLPID_IP:
+      pos += sprintf (pos, "IPv4");
+      break;
+    case NLPID_IPV6:
+      pos += sprintf (pos, "IPv6");
+      break;
+    default:
+      pos += sprintf (pos, "unknown");
+      break;
+    }
+    if (nlpids->count-i>1)
+      pos += sprintf (pos, ", ");
+    
+  }
+
+  *(pos) = '\0';
+  
+  return nlpidstring;
+}
+
+/*
+ *  supports the given af ?
+ */
+int 
+speaks (struct nlpids *nlpids, int family)
+{
+  int i, speaks = 0;
+  
+  if (nlpids == (struct nlpids*)NULL)
+    return speaks;
+  for (i = 0;i < nlpids->count; i++) {
+    if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
+      speaks = 1;
+    if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
+      speaks = 1;
+  }
+
+  return speaks;
+}
+
+
+/*
+ * Returns 0 on error, IS-IS Circuit Type on ok
+ */
+int 
+string2circuit_t (u_char *str)
+{
+  
+  if (!str)
+    return 0;
+  
+  if (!strcmp(str,"level-1"))
+    return IS_LEVEL_1;
+
+  if (!strcmp(str,"level-2-only") || !strcmp(str,"level-2"))
+    return IS_LEVEL_2;
+  
+  if (!strcmp(str,"level-1-2"))
+    return IS_LEVEL_1_AND_2;
+
+  return 0;
+}
+
+const char *
+circuit_t2string (int circuit_t)
+{
+  switch (circuit_t) {
+  case IS_LEVEL_1:
+    return "L1";
+  case IS_LEVEL_2:
+    return "L2";
+  case IS_LEVEL_1_AND_2:
+    return "L1L2";
+  default:
+    return "??";
+  }
+
+  return NULL; /* not reached */
+}
+
+const char *
+syst2string (int type)
+{
+  switch (type) {
+  case ISIS_SYSTYPE_ES:
+    return "ES";
+  case ISIS_SYSTYPE_IS:
+    return "IS";
+  case ISIS_SYSTYPE_L1_IS:
+    return "1";
+  case ISIS_SYSTYPE_L2_IS:
+    return "2";
+  default:
+    return "??";
+  }
+
+  return NULL; /* not reached */
+}
+
+/*
+ * Print functions - we print to static vars
+ */
+char *
+snpa_print (u_char *from)
+{
+  int i = 0;
+  u_char *pos = snpa;
+
+  if(!from)
+    return "unknown";
+  
+  while (i < ETH_ALEN - 1) {
+    if (i & 1) {
+      sprintf ( pos, "%02x.", *(from + i));
+      pos += 3;
+    } else {
+      sprintf ( pos, "%02x", *(from + i));
+      pos += 2;
+
+    }
+    i++;
+  }
+
+  sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
+  pos += 2;
+  *(pos) = '\0';
+
+  return snpa;
+}
+
+char *
+sysid_print (u_char *from)
+{
+  int i = 0;
+  char *pos = sysid;
+
+  if(!from)
+    return "unknown";
+
+  while (i < ISIS_SYS_ID_LEN - 1) {
+    if (i & 1) {
+      sprintf ( pos, "%02x.", *(from + i));
+      pos += 3;
+    } else {
+      sprintf ( pos, "%02x", *(from + i));
+      pos += 2;
+    
+    } 
+    i++;
+  }
+
+  sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
+  pos += 2;
+  *(pos) = '\0';
+  
+  return sysid;
+}
+
+char *
+rawlspid_print (u_char *from)
+{
+  char *pos = lspid;
+  if(!from)
+    return "unknown";
+  memcpy(pos, sysid_print(from), 15);
+  pos += 14;
+  sprintf (pos, ".%02x", LSP_PSEUDO_ID(from));
+  pos += 3;
+  sprintf (pos, "-%02x", LSP_FRAGMENT(from));
+  pos += 3;
+
+  *(pos) = '\0';
+
+  return lspid;
+}
+
+char *
+time2string (u_int32_t time) {
+  char *pos = datestring; 
+  u_int32_t rest;
+
+  if (time==0)
+    return "-";
+
+  if(time/SECS_PER_YEAR)
+    pos += sprintf (pos, "%uY",time/SECS_PER_YEAR);
+  rest=time%SECS_PER_YEAR;    
+  if(rest/SECS_PER_MONTH)
+    pos += sprintf (pos, "%uM",rest/SECS_PER_MONTH);
+  rest=rest%SECS_PER_MONTH;  
+  if(rest/SECS_PER_WEEK)
+    pos += sprintf (pos, "%uw",rest/SECS_PER_WEEK);
+  rest=rest%SECS_PER_WEEK;    
+  if(rest/SECS_PER_DAY)
+    pos += sprintf (pos, "%ud",rest/SECS_PER_DAY);
+  rest=rest%SECS_PER_DAY;    
+  if(rest/SECS_PER_HOUR)
+    pos += sprintf (pos, "%uh",rest/SECS_PER_HOUR);
+  rest=rest%SECS_PER_HOUR;    
+  if(rest/SECS_PER_MINUTE)
+    pos += sprintf (pos, "%um",rest/SECS_PER_MINUTE);
+  rest=rest%SECS_PER_MINUTE;    
+  if(rest)
+    pos += sprintf (pos, "%us",rest);   
+ 
+  *(pos) = 0;
+
+  return datestring;
+}
+
+/*
+ * routine to decrement a timer by a random
+ * number
+ *
+ * first argument is the timer and the second is
+ * the jitter
+ */
+unsigned long 
+isis_jitter (unsigned long timer, unsigned long jitter)
+{
+  int j,k;
+
+  if (jitter>=100)
+    return timer;
+
+  if (timer == 1)
+    return timer;
+  /* 
+   * randomizing just the percent value provides
+   * no good random numbers - hence the spread
+   * to RANDOM_SPREAD (100000), which is ok as
+   * most IS-IS timers are no longer than 16 bit
+   */
+
+  j = 1 + (int) ((RANDOM_SPREAD * rand()) / (RAND_MAX + 1.0 )); 
+
+  k = timer - (timer * (100 - jitter))/100;
+
+  timer = timer - (k * j / RANDOM_SPREAD);
+
+  return timer;
+}
+
+struct in_addr
+newprefix2inaddr (u_char *prefix_start, u_char prefix_masklen) 
+{
+  memset(&new_prefix, 0, sizeof (new_prefix));
+  memcpy(&new_prefix, prefix_start, (prefix_masklen & 0x3F) ? 
+	 ((((prefix_masklen & 0x3F)-1)>>3)+1) : 0);
+  return new_prefix;
+}
+
+
+
+
+
diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h
new file mode 100644
index 0000000..0e219c6
--- /dev/null
+++ b/isisd/isis_misc.h
@@ -0,0 +1,94 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_misc.h
+ *                             Miscellanous routines
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_MISC_H
+#define _ZEBRA_ISIS_MISC_H
+
+int dotformat2buff (u_char *, u_char *);
+int string2circuit_t (u_char *);
+const char *circuit_t2string (int);
+const char *syst2string (int);
+struct in_addr newprefix2inaddr (u_char *prefix_start, u_char prefix_masklen);
+/*
+ * Converting input to memory stored format
+ * return value of 0 indicates wrong input
+ */
+int dotformat2buff (u_char *, u_char *);
+int sysid2buff (u_char *, u_char *);
+
+/*
+ * Printing functions
+ */
+char *isonet_print (u_char *, int len);
+char *sysid_print (u_char *);
+char *snpa_print  (u_char *);
+char *rawlspid_print (u_char *);
+char *time2string (u_int32_t);
+/* typedef struct nlpids nlpids; */
+char *nlpid2string (struct nlpids *);
+
+
+/*
+ * misc functions
+ */
+int  speaks (struct nlpids *nlpids, int family);
+unsigned long isis_jitter (unsigned long timer, unsigned long jitter);
+
+/*
+ * macros
+ */
+#define GETSYSID(A,L) (A->area_addr + (A->addr_len - (L + 1)))
+
+
+/* staticly assigned vars for printing purposes */
+struct in_addr              new_prefix; 
+/* len of xxxx.xxxx.xxxx + place for #0 termination */
+char                         sysid[15]; 
+/* len of xxxx.xxxx.xxxx + place for #0 termination */
+char                          snpa[15]; 
+/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
+char                        isonet[51]; 
+/* + place for #0 termination */
+/* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
+char                         lspid[21]; 
+/* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
+char                    datestring[20]; 
+char                   nlpidstring[30];
+
+/* used for calculating nice string representation instead of plain seconds */
+
+#define SECS_PER_MINUTE 60
+#define SECS_PER_HOUR   3600
+#define SECS_PER_DAY    86400
+#define SECS_PER_WEEK   604800
+#define SECS_PER_MONTH  2628000
+#define SECS_PER_YEAR   31536000
+
+enum {     
+  ISIS_UI_LEVEL_BRIEF,
+  ISIS_UI_LEVEL_DETAIL,
+  ISIS_UI_LEVEL_EXTENSIVE,
+};
+
+
+#endif 
diff --git a/isisd/isis_network.c b/isisd/isis_network.c
new file mode 100644
index 0000000..d22f3dd
--- /dev/null
+++ b/isisd/isis_network.c
@@ -0,0 +1,622 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_network.c   
+ *
+ * Copyright (C) 2001,2002    Sampo Saaristo
+ *                            Tampere University of Technology      
+ *                            Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <zebra.h>
+#include <net/ethernet.h>     /* the L2 protocols */
+
+#include "log.h"
+#include "stream.h"
+#include "if.h"
+
+
+#include "isisd/dict.h"
+#include "isisd/include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_network.h"
+
+/*
+ * On linux we can use the packet(7) sockets, in other OSs we have to do with
+ * Berkley Packet Filter (BPF). Please tell me if you can think of a better 
+ * way...
+ */
+#ifdef GNU_LINUX
+#include <netpacket/packet.h>
+#else 
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <net/bpf.h>
+struct bpf_insn llcfilter[] = {
+  BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ETHER_HDR_LEN),   /* check first byte */
+  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ISO_SAP, 0, 5), 
+  BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ETHER_HDR_LEN+1),
+  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ISO_SAP, 0, 3),    /* check second byte */
+  BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ETHER_HDR_LEN+2),
+  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x03, 0, 1),       /* check third byte */
+  BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+  BPF_STMT(BPF_RET+BPF_K, 0)
+};
+int readblen = 0;
+u_char *readbuff = NULL;
+#endif /* GNU_LINUX */
+
+/*
+ * Table 9 - Architectural constans for use with ISO 8802 subnetworks
+ * ISO 10589 - 8.4.8
+ */
+
+u_char ALL_L1_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x14};
+u_char ALL_L2_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x15};
+u_char ALL_ISS[6]    = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05};
+u_char ALL_ESS[6]    = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04};
+
+#ifdef GNU_LINUX
+static char discard_buff[8192];
+#endif
+static char sock_buff[8192];
+
+/*
+ * if level is 0 we are joining p2p multicast
+ * FIXME: and the p2p multicast being ???
+ */
+#ifdef GNU_LINUX
+int
+isis_multicast_join (int fd, int registerto, int if_num)
+{
+  struct packet_mreq mreq;
+
+  memset(&mreq, 0, sizeof(mreq));
+  mreq.mr_ifindex = if_num;
+  if (registerto) {
+    mreq.mr_type = PACKET_MR_MULTICAST;
+    mreq.mr_alen = ETH_ALEN;
+    if (registerto == 1)
+      memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN);
+    else if (registerto == 2)
+      memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN);
+    else if (registerto == 3)
+      memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN);
+    else
+      memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN);
+
+  } else {
+    mreq.mr_type = PACKET_MR_ALLMULTI;
+  }
+#ifdef EXTREME_DEBUG
+  zlog_info ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, "
+             "address = %02x:%02x:%02x:%02x:%02x:%02x",
+             fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1],
+             mreq.mr_address[2], mreq.mr_address[3],mreq.mr_address[4],
+             mreq.mr_address[5]);
+#endif /* EXTREME_DEBUG */
+  if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, 
+                  sizeof (struct packet_mreq))) {
+    zlog_warn ("isis_multicast_join(): setsockopt(): %s", strerror (errno));
+    return ISIS_WARNING;
+  }
+  
+  return ISIS_OK;
+}
+
+int 
+open_packet_socket (struct isis_circuit *circuit)
+{
+  struct sockaddr_ll s_addr;
+  int fd, retval = ISIS_OK;
+  
+  fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL));
+  if (fd < 0) {
+    zlog_warn ("open_packet_socket(): socket() failed %s", strerror (errno));
+    return ISIS_WARNING;
+  }
+
+  /*
+   * Bind to the physical interface
+   */
+  memset(&s_addr, 0, sizeof (struct sockaddr_ll));
+  s_addr.sll_family = AF_PACKET;
+  s_addr.sll_protocol = htons (ETH_P_ALL);
+  s_addr.sll_ifindex = circuit->interface->ifindex;
+  
+  if (bind (fd, (struct sockaddr*) (&s_addr), 
+            sizeof(struct sockaddr_ll)) < 0) {
+    zlog_warn ("open_packet_socket(): bind() failed: %s", strerror(errno));
+    return ISIS_WARNING;
+  }
+  
+  circuit->fd = fd;
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    /*
+     * Join to multicast groups
+     * according to
+     * 8.4.2 - Broadcast subnetwork IIH PDUs
+     * FIXME: is there a case only one will fail??
+     */
+    if (circuit->circuit_is_type & IS_LEVEL_1) {
+      /* joining ALL_L1_ISS */
+      retval = isis_multicast_join (circuit->fd, 1,
+                                    circuit->interface->ifindex);
+      /* joining ALL_ISS */
+      retval = isis_multicast_join (circuit->fd, 3,
+                                    circuit->interface->ifindex);
+    }
+    if (circuit->circuit_is_type & IS_LEVEL_2)
+      /* joining ALL_L2_ISS */
+      retval = isis_multicast_join (circuit->fd, 2,
+                                    circuit->interface->ifindex);
+  } else {
+    retval = isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
+  }
+
+  return retval;
+}
+
+#else
+
+int
+open_bpf_dev (struct isis_circuit *circuit)
+{
+  int i = 0, fd;
+  char bpfdev[128];
+  struct ifreq ifr;
+  u_int16_t blen;
+  int true = 1, false = 0;
+  struct timeval timeout;
+  struct bpf_program bpf_prog;
+  
+  do {
+    (void)snprintf(bpfdev, sizeof(bpfdev), "/dev/bpf%d", i++);
+      fd = open(bpfdev, O_RDWR);
+  } while (fd < 0 && errno == EBUSY);
+  
+  if (fd < 0) {
+    zlog_warn ("open_bpf_dev(): failed to create bpf socket: %s",
+               strerror (errno));
+    return ISIS_WARNING;
+  }
+  
+  zlog_info ("Opened BPF device %s", bpfdev);
+
+  memcpy (ifr.ifr_name, circuit->interface->name, sizeof(ifr.ifr_name));
+  if (ioctl (fd, BIOCSETIF, (caddr_t)&ifr) < 0 ) {
+    zlog_warn ("open_bpf_dev(): failed to bind to interface: %s", 
+               strerror (errno));
+    return ISIS_WARNING;
+  }
+
+
+  if (ioctl (fd, BIOCGBLEN, (caddr_t)&blen) < 0) {
+    zlog_warn ("failed to get BPF buffer len");
+    blen = circuit->interface->mtu;
+  }
+  
+  readblen = blen;
+
+  if (readbuff == NULL)
+    readbuff = malloc (blen);
+  
+  zlog_info ("BPF buffer len = %u", blen);
+
+  /*  BPF(4): reads return immediately upon packet reception.
+   *  Otherwise, a read will block until either the kernel
+   *  buffer becomes full or a timeout occurs. 
+   */
+  if (ioctl (fd, BIOCIMMEDIATE, (caddr_t)&true) < 0) {
+    zlog_warn ("failed to set BPF dev to immediate mode");
+  }
+
+  /*
+   * We want to see only incoming packets
+   */
+  if (ioctl (fd, BIOCSSEESENT, (caddr_t)&false) < 0) {
+    zlog_warn ("failed to set BPF dev to incoming only mode");
+  }
+
+  /*
+   * ...but all of them
+   */
+  if (ioctl (fd, BIOCPROMISC, (caddr_t)&true) < 0) {
+    zlog_warn ("failed to set BPF dev to promiscuous mode");
+  }
+
+
+  /*
+   * If the buffer length is smaller than our mtu, lets try to increase it
+   */
+  if (blen < circuit->interface->mtu) {
+    if (ioctl (fd, BIOCSBLEN, &circuit->interface->mtu) < 0) {
+      zlog_warn ("failed to set BPF buffer len (%u to %u)", blen,
+                 circuit->interface->mtu);
+    }
+  }
+
+  /*
+   * Set a timeout parameter - hope this helps select()
+   */
+  timeout.tv_sec = 600;
+  timeout.tv_usec = 0;
+  if (ioctl (fd, BIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
+    zlog_warn ("failed to set BPF device timeout");
+  }
+  
+  /*
+   * And set the filter
+   */
+  memset (&bpf_prog, 0, sizeof (struct bpf_program));
+  bpf_prog.bf_len = 8;
+  bpf_prog.bf_insns = &(llcfilter[0]);
+  if (ioctl (fd, BIOCSETF, (caddr_t)&bpf_prog) < 0) {
+    zlog_warn ("open_bpf_dev(): failed to install filter: %s", 
+               strerror (errno));
+    return ISIS_WARNING;
+  }
+
+
+  assert (fd > 0);
+
+  circuit->fd = fd;
+  
+  return ISIS_OK;
+}
+
+#endif /* GNU_LINUX */
+
+/*
+ * Create the socket and set the tx/rx funcs
+ */
+int
+isis_sock_init (struct isis_circuit *circuit)
+{
+  int retval = ISIS_OK;
+
+
+#ifdef GNU_LINUX
+  retval = open_packet_socket (circuit);
+#else
+  retval = open_bpf_dev (circuit);
+#endif
+  
+  if (retval == ISIS_OK) {
+    if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+      circuit->tx = isis_send_pdu_bcast;
+      circuit->rx = isis_recv_pdu_bcast;
+    }
+    else if (circuit->circ_type == CIRCUIT_T_P2P) {
+      circuit->tx = isis_send_pdu_p2p;
+      circuit->rx = isis_recv_pdu_p2p;
+    }
+    else {
+      zlog_warn ("isis_sock_init(): unknown circuit type");
+      retval = ISIS_WARNING;
+    }
+  }
+  
+  return retval;
+}
+
+
+static inline int 
+llc_check (u_char *llc)
+{
+
+  if(*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc +2) != 3)
+    return 0;
+  
+  return 1;
+}
+
+#ifdef GNU_LINUX
+int
+isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char *ssnpa)
+{
+  int bytesread, addr_len;
+  struct sockaddr_ll s_addr;
+  u_char llc[LLC_LEN];
+
+  addr_len = sizeof (s_addr);
+
+  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
+
+  bytesread = recvfrom (circuit->fd, (void *)&llc,
+                        LLC_LEN, MSG_PEEK,
+                        (struct sockaddr *)&s_addr, &addr_len);
+
+  if (bytesread < 0) {
+    zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", 
+               circuit->fd,  strerror (errno));
+    zlog_warn ("circuit is %s", circuit->interface->name);
+    zlog_warn ("circuit fd %d", circuit->fd);
+    zlog_warn ("bytesread %d", bytesread);
+    /* get rid of the packet */
+    bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
+    return ISIS_WARNING;
+  }
+  /*
+   * Filtering by llc field, discard packets sent by this host (other circuit)
+   */
+  if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING) {
+    /*  Read the packet into discard buff */
+    bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
+    if (bytesread < 0)
+      zlog_warn ("isis_recv_pdu_bcast(): read() failed");
+    return ISIS_WARNING;
+  }
+  
+  /* on lan we have to read to the static buff first */
+  bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
+                        (struct sockaddr *)&s_addr, &addr_len);
+  
+  /* then we lose the LLC */
+  memcpy (STREAM_DATA (circuit->rcv_stream), 
+          sock_buff + LLC_LEN, bytesread - LLC_LEN);
+  circuit->rcv_stream->putp = bytesread - LLC_LEN;
+  circuit->rcv_stream->endp = bytesread - LLC_LEN;
+  
+  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); 
+    
+  return ISIS_OK;
+}
+
+int
+isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char *ssnpa)
+{
+
+  int bytesread, addr_len;
+  struct sockaddr_ll s_addr;
+
+  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
+  addr_len = sizeof (s_addr);
+
+  /* we can read directly to the stream */
+  bytesread = recvfrom (circuit->fd, STREAM_DATA (circuit->rcv_stream),
+                        circuit->interface->mtu, 0,
+                        (struct sockaddr *)&s_addr, &addr_len);
+
+    if(s_addr.sll_pkttype == PACKET_OUTGOING) {
+    /*  Read the packet into discard buff */
+    bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
+    if (bytesread < 0)
+      zlog_warn ("isis_recv_pdu_p2p(): read() failed");
+    return ISIS_WARNING;
+  }
+
+  circuit->rcv_stream->putp = bytesread;
+  circuit->rcv_stream->endp = bytesread;
+
+  /* If we don't have protocol type 0x00FE which is
+   * ISO over GRE we exit with pain :)
+   */
+  if (ntohs(s_addr.sll_protocol) != 0x00FE) {
+    zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X", 
+               ntohs(s_addr.sll_protocol));
+    return ISIS_WARNING;
+  }
+  
+  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); 
+  
+  return ISIS_OK;
+}
+
+
+  
+int 
+isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
+{
+  /* we need to do the LLC in here because of P2P circuits, which will
+   * not need it
+   */
+  int  written = 1;
+  struct sockaddr_ll sa;
+
+  stream_set_getp (circuit->snd_stream, 0);
+  memset (&sa, 0, sizeof (struct sockaddr_ll));
+  sa.sll_family = AF_PACKET;
+  sa.sll_protocol = htons (stream_get_endp(circuit->snd_stream)+LLC_LEN);
+  sa.sll_ifindex = circuit->interface->ifindex;
+  sa.sll_halen = ETH_ALEN;
+  if (level == 1)
+    memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
+  else
+    memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
+
+  /* on a broadcast circuit */
+  /* first we put the LLC in */
+  sock_buff[0] = 0xFE;
+  sock_buff[1] = 0xFE;
+  sock_buff[2] = 0x03;
+
+  /* then we copy the data */
+  memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, 
+          stream_get_endp (circuit->snd_stream));
+
+  /* now we can send this */
+  written = sendto (circuit->fd, sock_buff,
+                    circuit->snd_stream->putp + LLC_LEN, 0,
+                    (struct sockaddr *)&sa, sizeof (struct sockaddr_ll));
+
+
+  return ISIS_OK;
+}
+
+int 
+isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
+{
+
+  int  written = 1;
+  struct sockaddr_ll sa;
+
+  stream_set_getp (circuit->snd_stream, 0);
+  memset (&sa, 0, sizeof (struct sockaddr_ll));
+  sa.sll_family = AF_PACKET;
+  sa.sll_protocol = htons (stream_get_endp(circuit->snd_stream)+LLC_LEN);
+  sa.sll_ifindex = circuit->interface->ifindex;
+  sa.sll_halen = ETH_ALEN;
+  if (level == 1)
+    memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
+  else
+    memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
+
+
+  /* lets try correcting the protocol */
+  sa.sll_protocol = htons(0x00FE);
+  written = sendto (circuit->fd, circuit->snd_stream->data, 
+                    circuit->snd_stream->putp, 0, (struct sockaddr *)&sa, 
+                    sizeof (struct sockaddr_ll));
+    
+  return ISIS_OK;
+}
+
+
+#else
+
+int
+isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char *ssnpa)
+{
+  int bytesread = 0, bytestoread, offset, one = 1;
+  struct bpf_hdr *bpf_hdr;
+
+  assert (circuit->fd > 0);
+
+  if (ioctl (circuit->fd, FIONREAD, (caddr_t)&bytestoread) < 0 ) {
+    zlog_warn ("ioctl() FIONREAD failed: %s", strerror (errno));
+  } 
+
+  if (bytestoread) {
+    bytesread = read (circuit->fd, readbuff, readblen);
+  }
+  if (bytesread < 0) {
+    zlog_warn ("isis_recv_pdu_bcast(): read() failed: %s", strerror (errno));
+    return ISIS_WARNING;
+  }
+
+  if (bytesread == 0)
+    return ISIS_WARNING;
+
+  bpf_hdr = (struct bpf_hdr*)readbuff;
+
+  assert (bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
+  
+  offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN;
+  
+  /* then we lose the BPF, LLC and ethernet headers */
+  memcpy (STREAM_DATA (circuit->rcv_stream), 
+          readbuff + offset, 
+          bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
+
+  circuit->rcv_stream->putp = bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN;
+  circuit->rcv_stream->endp = bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN;
+  circuit->rcv_stream->getp = 0;
+
+  memcpy (ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN, 
+          ETHER_ADDR_LEN);
+  
+  if (ioctl (circuit->fd, BIOCFLUSH, &one) < 0)
+    zlog_warn ("Flushing failed: %s", strerror (errno));
+  
+  return ISIS_OK;
+}
+
+int
+isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char *ssnpa)
+{
+  int bytesread;
+  
+  bytesread = read (circuit->fd, STREAM_DATA(circuit->rcv_stream), 
+                    circuit->interface->mtu);
+
+  if (bytesread < 0) {
+    zlog_warn ("isis_recv_pdu_p2p(): read () failed: %s", strerror (errno));
+    return ISIS_WARNING;
+  }
+
+  circuit->rcv_stream->putp = bytesread;
+  circuit->rcv_stream->endp = bytesread;
+  
+  return ISIS_OK;
+}
+
+
+  
+int 
+isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
+{
+  struct ether_header *eth;
+  int written;
+
+  stream_set_getp (circuit->snd_stream, 0);
+
+  /*
+   * First the eth header
+   */
+  eth = (struct ether_header *)sock_buff;
+  if (level == 1)
+    memcpy (eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN);
+  else
+    memcpy (eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN);
+  memcpy (eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN);
+  eth->ether_type = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
+
+  /*
+   * Then the LLC
+   */
+  sock_buff[ETHER_HDR_LEN]     =  ISO_SAP;
+  sock_buff[ETHER_HDR_LEN + 1] =  ISO_SAP;
+  sock_buff[ETHER_HDR_LEN + 2] =  0x03;
+
+  /* then we copy the data */
+  memcpy (sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, 
+          stream_get_endp (circuit->snd_stream));
+
+  /* now we can send this */
+  written = write (circuit->fd, sock_buff,
+                   circuit->snd_stream->putp + LLC_LEN + ETHER_HDR_LEN);
+
+
+  return ISIS_OK;
+}
+
+int 
+isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
+{
+  
+    
+  return ISIS_OK;
+}
+
+
+
+
+#endif /* GNU_LINUX */
+
+
+
+
+
diff --git a/isisd/isis_network.h b/isisd/isis_network.h
new file mode 100644
index 0000000..7633f9e
--- /dev/null
+++ b/isisd/isis_network.h
@@ -0,0 +1,37 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_network.h   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+#ifndef _ZEBRA_ISIS_NETWORK_H
+#define _ZEBRA_ISIS_NETWORK_H
+
+extern u_char ALL_L1_ISYSTEMS[];
+extern u_char ALL_L2_ISYSTEMS[];
+
+int isis_sock_init (struct isis_circuit *circuit);
+
+int isis_recv_pdu_bcast  (struct isis_circuit *circuit, u_char *ssnpa);
+int isis_recv_pdu_p2p  (struct isis_circuit *circuit, u_char *ssnpa);
+int isis_send_pdu_bcast (struct isis_circuit *circuit, int level);
+int isis_send_pdu_p2p (struct isis_circuit *circuit, int level);
+
+#endif /* _ZEBRA_ISIS_NETWORK_H */
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
new file mode 100644
index 0000000..8d636b3
--- /dev/null
+++ b/isisd/isis_pdu.c
@@ -0,0 +1,2478 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_pdu.c   
+ *                             PDU processing
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "memory.h"
+#include "thread.h"
+#include "linklist.h"
+#include "log.h"
+#include "stream.h"
+#include "vty.h"
+#include "hash.c"
+#include "prefix.h"
+#include "if.h"
+
+#include "isisd/dict.h"
+#include "isisd/include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_network.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_dr.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_dynhn.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/iso_checksum.h"
+#include "isisd/isis_csm.h"
+#include "isisd/isis_events.h"
+
+extern struct thread_master *master;
+extern struct isis *isis;
+
+#define ISIS_MINIMUM_FIXED_HDR_LEN 15
+#define ISIS_MIN_PDU_LEN           13 /* partial seqnum pdu with id_len=2 */
+
+#ifndef PNBBY
+#define PNBBY 8
+#endif /* PNBBY */
+
+/* Utility mask array. */
+static u_char maskbit[] = 
+{
+  0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
+};
+
+/*
+ * HELPER FUNCS
+ */
+
+/*
+ * Compares two sets of area addresses
+ */
+static int 
+area_match (struct list *left, struct list *right)
+{
+  struct area_addr *addr1, *addr2;
+  struct listnode *node1, *node2;
+
+  LIST_LOOP (left, addr1, node1) {
+    LIST_LOOP (right, addr2, node2) {
+      if (addr1->addr_len == addr2->addr_len && 
+        !memcmp (addr1->area_addr, addr2->area_addr, (int)addr1->addr_len))
+        return 1; /* match */
+    }
+  }
+
+  return 0; /* mismatch */
+}
+
+/*
+ * Check if ip2 is in the ip1's network (function like Prefix.h:prefix_match() )
+ * param ip1            the IS interface ip address structure
+ * param ip2            the IIH's ip address
+ * return  0            the IIH's IP is not in the IS's subnetwork
+ *         1            the IIH's IP is in the IS's subnetwork
+ */
+int
+ip_same_subnet  (struct prefix_ipv4 *ip1, struct in_addr *ip2)
+{
+  u_char *addr1, *addr2;
+  int shift, offset;
+  int len;
+    
+  addr1 = (u_char *) &ip1->prefix.s_addr;
+  addr2 = (u_char *) &ip2->s_addr;
+  len = ip1->prefixlen;
+
+  shift = len % PNBBY;
+  offset = len / PNBBY;
+
+  while (offset--) {
+    if (addr1[offset] != addr2[offset]) {
+      return 0;
+    }
+  }
+
+  if (shift) {
+    if (maskbit[shift] & (addr1[offset] ^ addr2[offset])) {
+      return 0;
+    }
+  }
+    
+ return 1; /* match  */
+}
+
+
+/*
+ * Compares two set of ip addresses
+ * param left     the local interface's ip addresses
+ * param right    the iih interface's ip address
+ * return         0   no match;
+ *                1   match;
+ */
+static int 
+ip_match (struct list *left, struct list *right)
+{
+  struct prefix_ipv4 *ip1;
+  struct in_addr *ip2;
+  struct listnode *node1, *node2;
+
+  LIST_LOOP (left, ip1, node1) {
+    LIST_LOOP (right, ip2, node2) {
+      if (ip_same_subnet(ip1, ip2)) {
+        return 1;  /* match */
+      }
+    }
+  
+  }
+  return 0;
+}
+
+/*
+ * Checks whether we should accept a PDU of given level 
+ */
+static int
+accept_level (int level, int circuit_t)
+{
+  int retval = ((circuit_t & level) == level); /* simple approach */
+
+  return retval;
+}
+
+int 
+authentication_check (struct isis_passwd *one, struct isis_passwd *theother)
+{
+  if (one->type != theother->type) {
+    zlog_warn ("Unsupported authentication type %d", theother->type );
+    return 1; /* Auth fail (different authentication types)*/
+  }
+  switch (one->type) {
+  case ISIS_PASSWD_TYPE_CLEARTXT:
+    if (one->len != theother->len)
+      return 1; /* Auth fail () - passwd len mismatch */
+    return memcmp (one->passwd, theother->passwd, one->len);
+    break;
+  default:
+    zlog_warn ("Unsupported authentication type");
+    break;
+  }
+  return 0; /* Auth pass */ 
+}
+
+/*
+ * Processing helper functions
+ */
+void
+tlvs_to_adj_nlpids (struct tlvs *tlvs, struct isis_adjacency *adj) 
+{
+  int i;
+  struct nlpids *tlv_nlpids;
+
+  if (tlvs->nlpids) {
+
+    tlv_nlpids = tlvs->nlpids;
+
+    adj->nlpids.count = tlv_nlpids->count;
+
+    for (i=0;i<tlv_nlpids->count;i++) {
+       adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i];
+    }
+  }
+}
+
+void  
+del_ip_addr (void *val)
+{
+  XFREE (MTYPE_ISIS_TMP, val);
+}
+
+void
+tlvs_to_adj_ipv4_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) 
+{
+  struct listnode *node;
+  struct in_addr *ipv4_addr, *malloced;
+
+  if (adj->ipv4_addrs) {
+    adj->ipv4_addrs->del = del_ip_addr;
+    list_delete (adj->ipv4_addrs);
+  }
+  adj->ipv4_addrs = list_new ();
+  if (tlvs->ipv4_addrs) {
+    LIST_LOOP (tlvs->ipv4_addrs, ipv4_addr, node) {
+      malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in_addr));
+      memcpy (malloced, ipv4_addr, sizeof (struct in_addr));
+      listnode_add (adj->ipv4_addrs, malloced);
+    }
+  }
+}
+
+#ifdef HAVE_IPV6
+void
+tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) 
+{
+  struct listnode *node;
+  struct in6_addr *ipv6_addr, *malloced;
+
+  if (adj->ipv6_addrs) {
+    adj->ipv6_addrs->del = del_ip_addr;
+    list_delete (adj->ipv6_addrs);
+  }
+  adj->ipv6_addrs = list_new ();
+  if (tlvs->ipv6_addrs) {
+    LIST_LOOP (tlvs->ipv6_addrs, ipv6_addr, node) {
+      malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in6_addr));
+      memcpy (malloced, ipv6_addr, sizeof (struct in6_addr));
+      listnode_add (adj->ipv6_addrs, malloced);
+    }
+  }
+
+}
+#endif /* HAVE_IPV6 */
+
+
+
+/*
+ *  RECEIVE SIDE                           
+ */
+
+/*
+ * Process P2P IIH
+ * ISO - 10589
+ * Section 8.2.5 - Receiving point-to-point IIH PDUs
+ *
+ */
+static int
+process_p2p_hello (struct isis_circuit *circuit)
+{
+  int retval = ISIS_OK;
+  struct isis_p2p_hello_hdr *hdr;
+  struct isis_adjacency *adj;
+  u_int32_t expected = 0, found;
+  struct tlvs tlvs;
+
+  if ((stream_get_endp (circuit->rcv_stream) - 
+       stream_get_getp (circuit->rcv_stream)) <
+      ISIS_P2PHELLO_HDRLEN) {
+    zlog_warn ("Packet too short");
+    return ISIS_WARNING;
+  }
+
+  /* 8.2.5.1 PDU acceptance tests */
+
+  /* 8.2.5.1 a) external domain untrue */
+  /* FIXME: not useful at all?         */
+
+  /* 8.2.5.1 b) ID Length mismatch */
+  /* checked at the handle_pdu     */
+
+  /* 8.2.5.2 IIH PDU Processing */
+
+  /* 8.2.5.2 a) 1) Maximum Area Addresses */
+  /* Already checked, and can also be ommited */
+
+  /*
+   * Get the header
+   */
+  hdr = (struct isis_p2p_hello_hdr*) STREAM_PNT(circuit->rcv_stream);
+  circuit->rcv_stream->getp += ISIS_P2PHELLO_HDRLEN;
+
+  /*  hdr.circuit_t = stream_getc (stream);
+      stream_get (hdr.source_id, stream, ISIS_SYS_ID_LEN);
+      hdr.hold_time = stream_getw (stream);
+      hdr.pdu_len   = stream_getw (stream);
+      hdr.local_id  = stream_getc (stream); */
+
+  /*
+   * My interpertation of the ISO, if no adj exists we will create one for 
+   * the circuit
+   */
+
+  if (isis->debugs  & DEBUG_ADJ_PACKETS) {
+     zlog_info("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s,"
+	       " cir id %02d, length %d",
+	       circuit->area->area_tag, circuit->interface->name, 
+	       circuit_t2string(circuit->circuit_is_type),
+	       circuit->circuit_id,ntohs(hdr->pdu_len));
+  }
+
+  adj = circuit->u.p2p.neighbor;
+  if ( !adj ) {
+    adj = isis_new_adj (hdr->source_id,"      ", 0, circuit);
+    if (adj == NULL)
+      return ISIS_ERROR;
+    circuit->u.p2p.neighbor = adj;
+    isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL);
+    adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
+  }
+
+  /* 8.2.6 Monitoring point-to-point adjacencies */
+  adj->hold_time = ntohs (hdr->hold_time);
+  adj->last_upd  = time (NULL);
+
+  /*
+   * Lets get the TLVS now
+   */
+  expected |= TLVFLAG_AREA_ADDRS;
+  expected |= TLVFLAG_AUTH_INFO;
+  expected |= TLVFLAG_NLPID;
+  expected |= TLVFLAG_IPV4_ADDR;
+  expected |= TLVFLAG_IPV6_ADDR;
+
+  retval = parse_tlvs (circuit->area->area_tag,
+		       STREAM_PNT (circuit->rcv_stream),
+		       ntohs (hdr->pdu_len) - ISIS_P2PHELLO_HDRLEN 
+		       - ISIS_FIXED_HDR_LEN,
+		       &expected,
+		       &found,
+		       &tlvs);
+
+  if (retval > ISIS_WARNING) {
+    free_tlvs (&tlvs);
+    return retval;
+  };
+
+  /* 8.2.5.1 c) Authentication */
+  if (circuit->passwd.type) {
+    if (!(found & TLVFLAG_AUTH_INFO) || 
+	authentication_check (&circuit->passwd, &tlvs.auth_info)) {
+      isis_event_auth_failure (circuit->area->area_tag, 
+			       "P2P hello authentication failure", 
+			       hdr->source_id);
+      return ISIS_OK;
+    }
+  }
+
+  /* we do this now because the adj may not survive till the end... */
+
+  /* we need to copy addresses to the adj */
+  tlvs_to_adj_ipv4_addrs (&tlvs,adj);
+
+#ifdef HAVE_IPV6
+  tlvs_to_adj_ipv6_addrs (&tlvs,adj);
+#endif /* HAVE_IPV6 */
+
+  /* lets take care of the expiry */
+  if(adj->t_expire) {
+    thread_cancel (adj->t_expire);
+  }
+  adj->t_expire = thread_add_timer (master, isis_adj_expire, adj,
+                                    (long)adj->hold_time);
+
+  /* 8.2.5.2 a) a match was detected */
+  if (area_match (circuit->area->area_addrs, tlvs.area_addrs)) {
+    /* 8.2.5.2 a) 2) If the system is L1 - table 5 */
+    if (circuit->area->is_type == IS_LEVEL_1) {
+      switch (hdr->circuit_t) {
+      case IS_LEVEL_1:
+      case IS_LEVEL_1_AND_2:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (4) adj state up */
+          isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
+          /* (5) adj usage level 1 */
+          adj->adj_usage = ISIS_ADJ_LEVEL1;
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
+          ; /* accept */
+        }
+        break;
+      case IS_LEVEL_2:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (7) reject - wrong system type event */
+          zlog_warn ("wrongSystemType");
+          return ISIS_WARNING; /* Reject */
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
+          /* (6) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        }
+        break;
+      }
+    }
+
+    /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */
+    if (circuit->area->is_type == IS_LEVEL_1_AND_2) {
+      switch (hdr->circuit_t) {
+      case IS_LEVEL_1:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (6) adj state up */
+          isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
+          /* (7) adj usage level 1 */
+          adj->adj_usage = ISIS_ADJ_LEVEL1;
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
+          ; /* accept */
+        } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
+                   (adj->adj_usage == ISIS_ADJ_LEVEL2)) {
+          /* (8) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        }
+        break;
+      case IS_LEVEL_2:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (6) adj state up */
+          isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
+          /* (9) adj usage level 2 */
+          adj->adj_usage = ISIS_ADJ_LEVEL2;
+        } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
+                   (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)) {
+          /* (8) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) {
+          ; /* Accept */
+        }
+        break;
+      case IS_LEVEL_1_AND_2:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (6) adj state up */
+          isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
+          /* (10) adj usage level 1 */
+          adj->adj_usage = ISIS_ADJ_LEVEL1AND2;
+        } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
+                   (adj->adj_usage == ISIS_ADJ_LEVEL2)) {
+          /* (8) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) {
+          ; /* Accept */
+        }
+        break;
+      }
+    }
+
+    /* 8.2.5.2 a) 4) If the system is L2 - table 7 */
+    if (circuit->area->is_type == IS_LEVEL_2) {
+      switch (hdr->circuit_t) {
+      case IS_LEVEL_1:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (5) reject - wrong system type event */
+          zlog_warn ("wrongSystemType");
+          return ISIS_WARNING; /* Reject */
+        } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
+                   (adj->adj_usage == ISIS_ADJ_LEVEL2)) {
+          /* (6) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        }
+        break;
+      case IS_LEVEL_1_AND_2:
+      case IS_LEVEL_2:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (7) adj state up */
+          isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
+          /* (8) adj usage level 2 */
+          adj->adj_usage = ISIS_ADJ_LEVEL2;
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) {
+          /* (6) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) {
+          ; /* Accept */
+        }
+        break;
+      }
+    }
+  }
+  /* 8.2.5.2 b) if no match was detected */
+  else
+  {
+    if (circuit->area->is_type == IS_LEVEL_1) {
+      /* 8.2.5.2 b) 1) is_type L1 and adj is not up */
+      if (adj->adj_state != ISIS_ADJ_UP) {
+        isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
+      /* 8.2.5.2 b) 2)is_type L1 and adj is up */
+      } else {
+        isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Down - Area Mismatch");
+      }
+    }
+    /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */
+    else
+    {
+      switch (hdr->circuit_t) {
+      case IS_LEVEL_1:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (6) reject - Area Mismatch event */
+          zlog_warn ("AreaMismatch");
+          return ISIS_WARNING; /* Reject */
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
+          /* (7) down - area mismatch */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
+
+        } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
+                   (adj->adj_usage == ISIS_ADJ_LEVEL2)) {
+          /* (7) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        }
+        break;
+      case IS_LEVEL_1_AND_2:
+      case IS_LEVEL_2:
+        if (adj->adj_state != ISIS_ADJ_UP) {
+          /* (8) adj state up */
+          isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
+          /* (9) adj usage level 2 */
+          adj->adj_usage = ISIS_ADJ_LEVEL2;
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
+          /* (7) down - wrong system */
+          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) {
+          if (hdr->circuit_t == IS_LEVEL_2) {
+            /* (7) down - wrong system */
+            isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
+          } else {
+            /* (7) down - area mismatch */
+            isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
+          }
+        } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) {
+          ; /* Accept */
+        }
+        break;
+      }
+    }
+  }
+  /* 8.2.5.2 c) if the action was up - comparing circuit IDs */
+  /* FIXME - Missing parts */
+
+
+  /* some of my own understanding of the ISO, why the heck does
+   * it not say what should I change the system_type to...
+   */
+  switch (adj->adj_usage) {
+    case ISIS_ADJ_LEVEL1:
+      adj->sys_type = ISIS_SYSTYPE_L1_IS;
+      break;
+    case ISIS_ADJ_LEVEL2:
+      adj->sys_type = ISIS_SYSTYPE_L2_IS;
+      break;
+    case ISIS_ADJ_LEVEL1AND2:
+      adj->sys_type = ISIS_SYSTYPE_L2_IS;
+      break;
+    case ISIS_ADJ_NONE:
+      adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
+      break;
+  }
+
+  adj->circuit_t = hdr->circuit_t;
+  adj->level = hdr->circuit_t;
+
+  free_tlvs (&tlvs);
+
+  return retval;
+}
+
+
+/*
+ * Process IS-IS LAN Level 1/2 Hello PDU
+ */
+static int 
+process_lan_hello (int level, struct isis_circuit *circuit, u_char *ssnpa)
+{
+  int retval = ISIS_OK;
+  struct isis_lan_hello_hdr hdr;
+  struct isis_adjacency *adj;
+  u_int32_t expected = 0, found;
+  struct tlvs tlvs;
+  u_char *snpa;
+  struct listnode *node;
+
+  if ((stream_get_endp (circuit->rcv_stream) - 
+       stream_get_getp (circuit->rcv_stream)) < ISIS_LANHELLO_HDRLEN) {
+    zlog_warn ("Packet too short");
+    return ISIS_WARNING;
+  }
+
+  if (circuit->ext_domain) {
+    zlog_info ("level %d LAN Hello received over circuit with "
+	       "externalDomain = true", level);
+    return ISIS_WARNING;
+  }
+
+  if (!accept_level (level, circuit->circuit_is_type)) {
+    if (isis->debugs & DEBUG_ADJ_PACKETS) {
+      zlog_info ("ISIS-Adj (%s): Interface level mismatch, %s",
+                 circuit->area->area_tag, circuit->interface->name);
+    }
+    return ISIS_WARNING;
+  }
+
+#if 0
+  /* Cisco's debug message compatability */
+  if (!accept_level (level, circuit->area->is_type)) {
+    if (isis->debugs & DEBUG_ADJ_PACKETS) {
+      zlog_info ("ISIS-Adj (%s): is type mismatch",
+                 circuit->area->area_tag);
+    }
+    return ISIS_WARNING;
+  }
+#endif
+  /*
+   * Fill the header
+   */
+  hdr.circuit_t = stream_getc (circuit->rcv_stream);
+  stream_get (hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
+  hdr.hold_time = stream_getw (circuit->rcv_stream);
+  hdr.pdu_len   = stream_getw (circuit->rcv_stream);
+  hdr.prio      = stream_getc (circuit->rcv_stream);
+  stream_get (hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1);
+
+  if (hdr.circuit_t != IS_LEVEL_1 && hdr.circuit_t != IS_LEVEL_2 &&
+      hdr.circuit_t != IS_LEVEL_1_AND_2 ) {
+    zlog_warn ("Level %d LAN Hello with Circuit Type %d", level, 
+	       hdr.circuit_t);
+    return ISIS_ERROR;
+  }
+  /*
+   * Then get the tlvs
+   */
+  expected |= TLVFLAG_AUTH_INFO;
+  expected |= TLVFLAG_AREA_ADDRS;
+  expected |= TLVFLAG_LAN_NEIGHS;
+  expected |= TLVFLAG_NLPID;
+  expected |= TLVFLAG_IPV4_ADDR;
+  expected |= TLVFLAG_IPV6_ADDR;
+
+  retval = parse_tlvs (circuit->area->area_tag,
+                       STREAM_PNT (circuit->rcv_stream),
+                       hdr.pdu_len - ISIS_LANHELLO_HDRLEN - ISIS_FIXED_HDR_LEN,
+                       &expected,
+                       &found,
+                       &tlvs);
+
+  if (retval > ISIS_WARNING) {
+    zlog_warn ("parse_tlvs() failed");
+    goto out;
+  }
+
+  if (!(found & TLVFLAG_AREA_ADDRS)) {
+    zlog_warn ("No Area addresses TLV in Level %d LAN IS to IS hello", level);
+    retval = ISIS_WARNING;
+    goto out;
+  }
+
+  if (circuit->passwd.type) {
+    if (!(found & TLVFLAG_AUTH_INFO) || 
+	authentication_check (&circuit->passwd, &tlvs.auth_info)) {
+      isis_event_auth_failure (circuit->area->area_tag, 
+			       "LAN hello authentication failure", 
+        hdr.source_id);
+      retval = ISIS_WARNING;
+      goto out;
+    }
+  }
+
+  /*
+   * Accept the level 1 adjacency only if a match between local and
+   * remote area addresses is found
+   */
+  if (level == 1 && !area_match (circuit->area->area_addrs, tlvs.area_addrs)) {
+    if (isis->debugs & DEBUG_ADJ_PACKETS) {
+      zlog_info ("ISIS-Adj (%s): Area mismatch, level %d IIH on %s",
+                 circuit->area->area_tag, level,circuit->interface->name);
+    }
+    retval = ISIS_OK;
+    goto out;
+  }
+
+  /* 
+   * it's own IIH PDU - discard silently 
+   */ 
+  if (!memcmp (circuit->u.bc.snpa, ssnpa, ETH_ALEN)) {
+    zlog_info ("ISIS-Adj (%s): it's own IIH PDU - discarded", 
+	       circuit->area->area_tag);
+
+    retval = ISIS_OK;
+    goto out;
+  }
+
+  /*
+   * check if it's own interface ip match iih ip addrs
+   */
+  if (!(found & TLVFLAG_IPV4_ADDR) || !ip_match(circuit->ip_addrs, tlvs.ipv4_addrs)) {
+    zlog_info("ISIS-Adj: No usable IP interface addresses in LAN IIH from %s\n",
+   		circuit->interface->name);
+    retval = ISIS_WARNING;
+    goto out;
+  }
+
+
+  adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]);
+  if (!adj) {
+    /*
+     * Do as in 8.4.2.5
+     */
+    adj = isis_new_adj (hdr.source_id, ssnpa, level, circuit);
+    if (adj == NULL)
+      retval = ISIS_ERROR;
+      goto out;
+
+    adj->level = level;
+    isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL);
+
+    if (level == 1) {
+      adj->sys_type = ISIS_SYSTYPE_L1_IS;
+    } else {
+      adj->sys_type = ISIS_SYSTYPE_L2_IS;
+    }
+    list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
+    isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
+                               circuit->u.bc.lan_neighs[level - 1]); 
+  }
+
+  switch (level) {
+  case 1 :
+    if (memcmp(circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1)) {
+      thread_add_event (master, isis_event_dis_status_change, circuit, 0);
+      memcpy (&circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
+    }
+    break;
+  case 2 : 
+    if (memcmp (circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1)) {
+      thread_add_event (master, isis_event_dis_status_change, circuit, 0);
+      memcpy (&circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
+    }
+    break;
+  }
+
+#if 0
+ /* Old solution: believe the lan-header always
+  */
+  if (level == 1) {
+    memcpy(circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
+  } else if (level == 2) {
+    memcpy(circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
+  }
+#endif
+
+  adj->hold_time = hdr.hold_time;
+  adj->last_upd  = time (NULL);
+  adj->prio[level-1] = hdr.prio;
+
+  memcpy (adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
+
+  /* which protocol are spoken ??? */
+  if (found & TLVFLAG_NLPID) 
+    tlvs_to_adj_nlpids (&tlvs, adj);
+
+  /* we need to copy addresses to the adj */
+  if (found & TLVFLAG_IPV4_ADDR) 
+    tlvs_to_adj_ipv4_addrs (&tlvs, adj);
+
+#ifdef HAVE_IPV6
+  if (found & TLVFLAG_IPV6_ADDR) 
+    tlvs_to_adj_ipv6_addrs (&tlvs, adj);
+#endif /* HAVE_IPV6 */
+
+  adj->circuit_t = hdr.circuit_t;
+
+  /* lets take care of the expiry */
+  if (adj->t_expire) {
+    thread_cancel (adj->t_expire);
+  }
+  adj->t_expire = thread_add_timer (master, isis_adj_expire, adj,
+                                    (long)adj->hold_time);
+
+  /*
+   * If the snpa for this circuit is found from LAN Neighbours TLV
+   * we have two-way communication -> adjacency can be put to state "up"
+   */
+
+  if (found & TLVFLAG_LAN_NEIGHS) {
+    if (adj->adj_state != ISIS_ADJ_UP) {
+      LIST_LOOP (tlvs.lan_neighs, snpa, node)
+        if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN)) {
+          isis_adj_state_change (adj, ISIS_ADJ_UP, 
+                                 "own SNPA found in LAN Neighbours TLV");
+        }
+    }
+  }
+
+ out:
+  /* DEBUG_ADJ_PACKETS */
+  if (isis->debugs & DEBUG_ADJ_PACKETS) {
+    /* FIXME: is this place right? fix missing info */
+    zlog_info ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, "
+               "cirID %u, length %ld",
+	       circuit->area->area_tag, 
+               level,snpa_print(ssnpa), circuit->interface->name,
+               circuit_t2string(circuit->circuit_is_type),
+               circuit->circuit_id,
+               stream_get_endp (circuit->rcv_stream));
+  }
+
+
+  free_tlvs (&tlvs);
+
+  return retval;
+}
+
+/*
+ * Process Level 1/2 Link State
+ * ISO - 10589
+ * Section 7.3.15.1 - Action on receipt of a link state PDU
+ */ 
+static int 
+process_lsp (int level, struct isis_circuit *circuit, u_char *ssnpa)
+{
+  struct isis_link_state_hdr *hdr;
+  struct isis_adjacency *adj = NULL;
+  struct isis_lsp *lsp, *lsp0 = NULL;
+  int retval = ISIS_OK, comp = 0;
+  u_char lspid[ISIS_SYS_ID_LEN + 2];
+  struct isis_passwd *passwd;
+
+  /* Sanity check - FIXME: move to correct place */
+  if ((stream_get_endp (circuit->rcv_stream) - 
+       stream_get_getp (circuit->rcv_stream)) < ISIS_LSP_HDR_LEN ) {
+    zlog_warn ("Packet too short");
+    return ISIS_WARNING;
+  }
+
+  /* Reference the header   */
+  hdr = (struct isis_link_state_hdr*)STREAM_PNT (circuit->rcv_stream);
+
+  if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+    zlog_info ("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, "
+               "lifetime %us, len %lu, on %s",
+	       circuit->area->area_tag,
+	       level, 
+               rawlspid_print(hdr->lsp_id),
+	       ntohl(hdr->seq_num),
+	       ntohs(hdr->checksum),
+	       ntohs(hdr->rem_lifetime),
+	       circuit->rcv_stream->endp,
+               circuit->interface->name);
+  }
+
+  assert (ntohs (hdr->pdu_len) > ISIS_LSP_HDR_LEN);
+
+  /* Checksum sanity check - FIXME: move to correct place */
+  /* 12 = sysid+pdu+remtime */
+  if (iso_csum_verify (STREAM_PNT (circuit->rcv_stream) + 4, 
+      ntohs (hdr->pdu_len) - 12, &hdr->checksum)) {
+    zlog_info ("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x",
+	       circuit->area->area_tag,
+	       rawlspid_print (hdr->lsp_id),
+	       ntohs(hdr->checksum));
+
+    return ISIS_WARNING;
+  }
+
+  /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */
+  if (circuit->ext_domain) {
+    zlog_info ("ISIS-Upd (%s): LSP %s received at level %d over circuit with "
+               "externalDomain = true",
+	       circuit->area->area_tag,
+	       rawlspid_print (hdr->lsp_id),	       
+	       level);
+
+    return ISIS_WARNING;
+  }
+
+  /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */
+  if (!accept_level (level, circuit->circuit_is_type)) {
+    zlog_info ("ISIS-Upd (%s): LSP %s received at level %d over circuit of"
+               " type %s", 
+	       circuit->area->area_tag,
+	       rawlspid_print(hdr->lsp_id),	
+               level,
+	       circuit_t2string (circuit->circuit_is_type));
+
+    return ISIS_WARNING;
+  }
+
+  /* 7.3.15.1 a) 4 - need to make sure IDLength matches */
+
+  /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use 3 */
+
+  /* 7.3.15.1 a) 7 - password check */
+  (level == ISIS_LEVEL1) ? (passwd = &circuit->area->area_passwd) :
+    (passwd = &circuit->area->domain_passwd);
+  if (passwd->type) {
+    if (isis_lsp_authinfo_check (circuit->rcv_stream, circuit->area,
+				 ntohs (hdr->pdu_len), passwd)) {
+      isis_event_auth_failure (circuit->area->area_tag,
+			       "LSP authentication failure",
+			       hdr->lsp_id);
+      return ISIS_WARNING;
+    }
+  }
+  /* Find the LSP in our database and compare it to this Link State header */
+  lsp = lsp_search (hdr->lsp_id, circuit->area->lspdb[level - 1]);
+  if (lsp)
+    comp = lsp_compare (circuit->area->area_tag, lsp, hdr->seq_num, 
+                        hdr->checksum, hdr->rem_lifetime);
+  if (lsp && (lsp->own_lsp 
+#ifdef TOPOLOGY_GENERATE
+              || lsp->from_topology
+#endif /* TOPOLOGY_GENERATE */
+              ))
+    goto dontcheckadj;
+
+  /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same level  */
+  /* for broadcast circuits, snpa should be compared */
+  /* FIXME : Point To Point */
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    adj = isis_adj_lookup_snpa (ssnpa, circuit->u.bc.adjdb[level - 1]);
+    if (!adj) {
+      zlog_info ("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, "
+		 "lifetime %us on %s",
+		 circuit->area->area_tag,
+		 rawlspid_print (hdr->lsp_id),
+		 ntohl (hdr->seq_num),
+		 ntohs (hdr->checksum),
+		 ntohs (hdr->rem_lifetime), 
+		 circuit->interface->name);
+      return ISIS_WARNING; /* Silently discard */
+    }
+  }
+
+  /* for non broadcast, we just need to find same level adj */
+  else {
+    /* If no adj, or no sharing of level */
+    if (!circuit->u.p2p.neighbor) {
+      return ISIS_OK; /* Silently discard */
+    } else {
+      if (((level == 1) && 
+           (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL2)) ||
+          ((level == 2) && 
+           (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1)))
+      return ISIS_WARNING; /* Silently discard */
+    }
+  }
+ dontcheckadj:
+  /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented  */
+
+  /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented  */
+
+  /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented  FIXME: do it*/
+
+
+  /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4*/
+  if (hdr->rem_lifetime == 0) {
+    if (!lsp) {
+      /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't save */
+      /* only needed on explicit update, eg - p2p */
+      if (circuit->circ_type == CIRCUIT_T_P2P)
+        ack_lsp (hdr, circuit, level);
+      return retval; /* FIXME: do we need a purge? */
+    } else {
+      if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN )) {
+        /* LSP by some other system -> do 7.3.16.4 b) */
+        /* 7.3.16.4 b) 1)  */
+        if (comp == LSP_NEWER) {
+          lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area);
+          /* ii */
+          ISIS_FLAGS_SET_ALL (lsp->SRMflags);   
+          /* iii */
+          ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
+          /* v */
+          ISIS_FLAGS_CLEAR_ALL(lsp->SSNflags); /* FIXME: OTHER than c */
+          /* iv */
+          if (circuit->circ_type != CIRCUIT_T_BROADCAST)
+            ISIS_SET_FLAG(lsp->SSNflags, circuit);
+
+        } /* 7.3.16.4 b) 2) */
+        else if (comp == LSP_EQUAL) {
+          /* i */
+          ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
+          /* ii*/
+          if (circuit->circ_type != CIRCUIT_T_BROADCAST)
+            ISIS_SET_FLAG(lsp->SSNflags, circuit);
+        }  /* 7.3.16.4 b) 3) */
+        else {
+          ISIS_SET_FLAG(lsp->SRMflags, circuit);
+          ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
+        }
+      } else {
+        /* our own LSP -> 7.3.16.4 c) */
+        if (LSP_PSEUDO_ID(lsp->lsp_header->lsp_id) != circuit->circuit_id ||
+            (LSP_PSEUDO_ID(lsp->lsp_header->lsp_id) == circuit->circuit_id &&
+             circuit->u.bc.is_dr[level - 1] == 1) ) { 
+          lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1);
+          zlog_info ("LSP LEN: %d", ntohs (lsp->lsp_header->pdu_len));
+          iso_csum_create (STREAM_DATA (lsp->pdu) + 12, 
+                           ntohs (lsp->lsp_header->pdu_len) - 12, 12);
+          ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+          zlog_info ("ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08x",
+                     circuit->area->area_tag,
+                     rawlspid_print (hdr->lsp_id),
+                     ntohl (lsp->lsp_header->seq_num));
+          lsp->lsp_header->rem_lifetime = htons (isis_jitter 
+                                                 (circuit->area->
+                                                  max_lsp_lifetime[level-1],
+                                                  MAX_AGE_JITTER));
+
+        } else {
+          /* Got purge for own pseudo-lsp, and we are not DR  */
+            lsp_purge_dr (lsp->lsp_header->lsp_id, circuit, level);
+        } 
+      }
+    }
+    return retval;
+  }
+  /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a 
+   * purge */
+  if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN ) == 0) {
+    if (!lsp) {
+    /* 7.3.16.4: initiate a purge */
+      lsp_purge_non_exist (hdr, circuit->area);
+      return ISIS_OK;
+    }
+    /* 7.3.15.1 d) - If this is our own lsp and we have it */
+
+    /* In 7.3.16.1, If an Intermediate system R somewhere in the domain
+     * has information that the current sequence number for source S is
+     * "greater" than that held by S, ... */
+
+    else if (ntohl (hdr->seq_num) > ntohl (lsp->lsp_header->seq_num)) {
+      /* 7.3.16.1  */
+      lsp->lsp_header->seq_num = htonl (ntohl (hdr->seq_num) + 1);
+
+      iso_csum_create (STREAM_DATA (lsp->pdu) + 12, 
+                       ntohs(lsp->lsp_header->pdu_len) - 12, 12);
+
+      ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+      zlog_info ("ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08x",
+                 circuit->area->area_tag,
+                 rawlspid_print (hdr->lsp_id),
+                 ntohl (lsp->lsp_header->seq_num));
+      lsp->lsp_header->rem_lifetime = htons (isis_jitter 
+                                             (circuit->
+                                              area->max_lsp_lifetime[level-1],
+                                              MAX_AGE_JITTER));
+
+    }
+  } else {
+  /* 7.3.15.1 e) - This lsp originated on another system */
+
+    /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */
+    if ((!lsp || comp == LSP_NEWER)){
+      /* i */
+      if (lsp) {
+#ifdef EXTREME_DEBUG
+        zlog_info ("level %d number is - %ld", level, 
+                   circuit->area->lspdb[level-1]->dict_nodecount);
+#endif /* EXTREME DEBUG */
+        lsp_search_and_destroy (hdr->lsp_id, circuit->area->lspdb[level-1]);
+        /* exists, so we overwrite */
+#ifdef EXTREME_DEBUG
+        zlog_info ("level %d number is - %ld",level, 
+                   circuit->area->lspdb[level-1]->dict_nodecount);
+#endif /* EXTREME DEBUG */
+      }
+      /*
+       * If this lsp is a frag, need to see if we have zero lsp present
+       */
+      if (LSP_FRAGMENT (hdr->lsp_id) != 0) {
+        memcpy (lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1);
+        LSP_FRAGMENT (lspid) = 0;
+        lsp0 = lsp_search (lspid, circuit->area->lspdb[level - 1]);
+        if (!lsp0) {
+          zlog_info ("Got lsp frag, while zero lsp not database");
+          return ISIS_OK;
+        }
+      }
+      lsp = lsp_new_from_stream_ptr (circuit->rcv_stream, ntohs (hdr->pdu_len),
+                                     lsp0, circuit->area);
+      lsp->level = level;
+      lsp->adj = adj;
+      lsp_insert (lsp, circuit->area->lspdb[level-1]);
+      /* ii */
+      ISIS_FLAGS_SET_ALL (lsp->SRMflags);
+      /* iii */
+      ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
+
+      /* iv */
+      if (circuit->circ_type != CIRCUIT_T_BROADCAST)
+        ISIS_SET_FLAG (lsp->SSNflags, circuit);
+      /* FIXME: v) */
+    }
+    /* 7.3.15.1 e) 2) LSP equal to the one in db */
+    else if (comp == LSP_EQUAL) {
+      ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
+      lsp_update (lsp, hdr, circuit->rcv_stream, circuit->area);
+      if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
+        ISIS_SET_FLAG (lsp->SSNflags, circuit);
+      }
+    }
+    /* 7.3.15.1 e) 3) LSP older than the one in db */
+    else {
+      ISIS_SET_FLAG(lsp->SRMflags, circuit);
+      ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
+    }
+  }
+  if (lsp)
+    lsp->adj = adj;
+  return retval;
+}
+
+/*
+ * Process Sequence Numbers
+ * ISO - 10589
+ * Section 7.3.15.2 - Action on receipt of a sequence numbers PDU
+ */
+
+int
+process_snp (int snp_type, int level, struct isis_circuit *circuit, 
+             u_char *ssnpa)
+{
+  int retval = ISIS_OK;
+  int cmp, own_lsp;
+  char typechar = ' ';
+  int len;
+  struct isis_adjacency *adj;
+  struct isis_complete_seqnum_hdr *chdr = NULL;
+  struct isis_partial_seqnum_hdr *phdr = NULL;
+  uint32_t found = 0, expected = 0;
+  struct isis_lsp *lsp;
+  struct lsp_entry *entry;
+  struct listnode *node,*node2;
+  struct tlvs tlvs;
+  struct list *lsp_list = NULL;
+  struct isis_passwd *passwd;
+
+  if (snp_type == ISIS_SNP_CSNP_FLAG) {
+  /* getting the header info */
+    typechar = 'C';
+    chdr = (struct isis_complete_seqnum_hdr*)STREAM_PNT(circuit->rcv_stream);
+    circuit->rcv_stream->getp += ISIS_CSNP_HDRLEN;
+    len = ntohs(chdr->pdu_len);
+    if (len < ISIS_CSNP_HDRLEN) {
+      zlog_warn ("Received a CSNP with bogus length!");
+      return ISIS_OK;
+    }
+  } else {
+    typechar = 'P';
+    phdr = (struct isis_partial_seqnum_hdr*)STREAM_PNT(circuit->rcv_stream);
+    circuit->rcv_stream->getp += ISIS_PSNP_HDRLEN;
+    len = ntohs(phdr->pdu_len);
+    if (len < ISIS_PSNP_HDRLEN) {
+      zlog_warn ("Received a CSNP with bogus length!");
+      return ISIS_OK;
+    }
+  }
+
+  /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */
+  if (circuit->ext_domain) {
+
+    zlog_info ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
+	       "skipping: circuit externalDomain = true",
+	       circuit->area->area_tag,
+	       level,
+	       typechar,
+	       circuit->interface->name);
+
+    return ISIS_OK;
+  }
+
+  /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */
+  if (!accept_level (level, circuit->circuit_is_type)) {
+
+    zlog_info ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
+	       "skipping: circuit type %s does not match level %d",
+	       circuit->area->area_tag,
+	       level, 
+               typechar,
+	       circuit->interface->name,
+	       circuit_t2string (circuit->circuit_is_type),
+	       level);
+
+    return ISIS_OK;
+  }
+
+  /* 7.3.15.2 a) 4 - not applicable for CSNP  only PSNPs on broadcast */
+  if ((snp_type == ISIS_SNP_PSNP_FLAG) && 
+      (circuit->circ_type == CIRCUIT_T_BROADCAST)) {
+    if (!circuit->u.bc.is_dr[level-1]) {
+
+      zlog_info ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, "
+		 "skipping: we are not the DIS",
+		 circuit->area->area_tag,
+                 level,
+		 typechar,
+		 snpa_print(ssnpa),
+		 circuit->interface->name);
+
+      return ISIS_OK;
+    }
+  }
+
+  /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked */
+
+  /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use 3
+   * - already checked */
+
+  /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same level  */
+  /* for broadcast circuits, snpa should be compared */
+  /* FIXME : Do we need to check SNPA? */
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    if (snp_type == ISIS_SNP_CSNP_FLAG) {
+      adj = isis_adj_lookup (chdr->source_id, circuit->u.bc.adjdb[level - 1]);
+    } else {
+      /* a psnp on a broadcast, how lovely of Juniper :) */
+      adj = isis_adj_lookup (phdr->source_id, circuit->u.bc.adjdb[level - 1]);
+    }
+    if (!adj)
+      return ISIS_OK; /* Silently discard */
+  } else {
+    if (!circuit->u.p2p.neighbor)
+      return ISIS_OK; /* Silently discard */
+  }
+
+  /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented  */
+
+  /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented  */
+
+  memset (&tlvs, 0, sizeof (struct tlvs));
+
+  /* parse the SNP */
+  expected |= TLVFLAG_LSP_ENTRIES;
+  expected |= TLVFLAG_AUTH_INFO;
+  retval = parse_tlvs (circuit->area->area_tag,
+		       STREAM_PNT(circuit->rcv_stream),
+		       len - circuit->rcv_stream->getp,
+		       &expected,
+		       &found,
+		       &tlvs);
+
+  if (retval > ISIS_WARNING) {
+    zlog_warn ("something went very wrong processing SNP");
+    free_tlvs (&tlvs);
+    return retval;
+  }
+
+  (level == 1) ? (passwd = &circuit->area->area_passwd) :
+		  (passwd = &circuit->area->domain_passwd);
+  if (passwd->type) {
+    if (!(found & TLVFLAG_AUTH_INFO) ||
+	authentication_check (passwd, &tlvs.auth_info)) {
+      isis_event_auth_failure (circuit->area->area_tag, "SNP authentication"
+			       " failure", phdr ?
+			       phdr->source_id : chdr->source_id);
+      return ISIS_OK;
+    } 
+  }
+
+  /* debug isis snp-packets */
+  if (isis->debugs & DEBUG_SNP_PACKETS) {
+    zlog_info ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s", 
+               circuit->area->area_tag,
+	       level,
+	       typechar,
+	       snpa_print(ssnpa),
+               circuit->interface->name);
+    if (tlvs.lsp_entries) {
+      LIST_LOOP (tlvs.lsp_entries,entry,node) {
+        zlog_info("ISIS-Snp (%s):         %cSNP entry %s, seq 0x%08x,"
+                  " cksum 0x%04x, lifetime %us", 
+                  circuit->area->area_tag,
+                  typechar, 
+                  rawlspid_print (entry->lsp_id),
+                  ntohl (entry->seq_num),
+                  ntohs (entry->checksum),
+                  ntohs (entry->rem_lifetime));
+      }
+    }
+  }
+
+  /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */
+  if (tlvs.lsp_entries) {
+    LIST_LOOP (tlvs.lsp_entries, entry, node) {
+      lsp = lsp_search (entry->lsp_id, circuit->area->lspdb[level - 1]);
+      own_lsp = !memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
+      if (lsp) {
+        /* 7.3.15.2 b) 1) is this LSP newer */
+        cmp = lsp_compare (circuit->area->area_tag, lsp, entry->seq_num, 
+                           entry->checksum, entry->rem_lifetime);
+        /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */
+        if (cmp == LSP_EQUAL) {
+          if (circuit->circ_type != CIRCUIT_T_BROADCAST) 
+            ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
+          /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM */
+        } else if (cmp == LSP_OLDER) {
+          ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
+        ISIS_SET_FLAG (lsp->SRMflags, circuit);
+        } else {
+          /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM on p2p*/
+          if (own_lsp) {
+            lsp_inc_seqnum (lsp, ntohl (entry->seq_num));
+            ISIS_SET_FLAG (lsp->SRMflags, circuit);
+          } else {
+            ISIS_SET_FLAG (lsp->SSNflags, circuit);
+            if (circuit->circ_type != CIRCUIT_T_BROADCAST)
+            ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); 
+          }
+        }
+      } else {
+        /* 7.3.15.2 b) 5) if it was not found, and all of those are not 0, 
+         * insert it and set SSN on it */
+        if (entry->rem_lifetime && entry->checksum && entry->seq_num && 
+            memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) {
+          lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime),
+                       0, 0, entry->checksum, level);
+          lsp_insert (lsp, circuit->area->lspdb[level - 1]);
+          ISIS_SET_FLAG (lsp->SSNflags, circuit);
+        }
+      }
+    }
+  }
+
+  /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported */
+  if (snp_type == ISIS_SNP_CSNP_FLAG) {
+    /*
+     * Build a list from our own LSP db bounded with start_ and stop_lsp_id
+     */
+    lsp_list = list_new ();
+    lsp_build_list_nonzero_ht (chdr->start_lsp_id, chdr->stop_lsp_id, 
+                               lsp_list, circuit->area->lspdb[level - 1]);
+
+    /* Fixme: Find a better solution */
+    if (tlvs.lsp_entries) {
+      LIST_LOOP (tlvs.lsp_entries, entry, node) {
+        LIST_LOOP (lsp_list, lsp, node2) {
+          if (lsp_id_cmp (lsp->lsp_header->lsp_id, entry->lsp_id) == 0) {
+            list_delete_node (lsp_list, node2);
+          break;
+          }
+        }
+      }
+    }
+    /* on remaining LSPs we set SRM (neighbor knew not of) */
+    LIST_LOOP (lsp_list, lsp, node2) {
+      ISIS_SET_FLAG (lsp->SRMflags, circuit);
+    }
+    /* lets free it */
+    list_free (lsp_list);
+  }
+
+  free_tlvs (&tlvs);
+  return retval;
+}
+
+int
+process_csnp (int level, struct isis_circuit *circuit, u_char *ssnpa)
+{
+
+  /* Sanity check - FIXME: move to correct place */
+  if ((stream_get_endp (circuit->rcv_stream) - 
+       stream_get_getp (circuit->rcv_stream)) < ISIS_CSNP_HDRLEN) {
+    zlog_warn ("Packet too short ( < %d)",  ISIS_CSNP_HDRLEN);
+    return ISIS_WARNING;
+  }
+
+  return process_snp (ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa);
+}
+
+int 
+process_psnp (int level, struct isis_circuit *circuit, u_char *ssnpa)
+{
+
+  if ((stream_get_endp (circuit->rcv_stream) - 
+       stream_get_getp (circuit->rcv_stream)) < ISIS_PSNP_HDRLEN) {
+    zlog_warn ("Packet too short");
+    return ISIS_WARNING;
+  }
+
+  return process_snp (ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa);
+}
+
+
+
+/*
+ * Process ISH
+ * ISO - 10589
+ * Section 8.2.2 - Receiving ISH PDUs by an intermediate system
+ * FIXME: sample packet dump, need to figure 0x81 - looks like NLPid
+            0x82	0x15	0x01	0x00	0x04	0x01	0x2c	0x59
+            0x38	0x08	0x47	0x00	0x01	0x00	0x02	0x00
+          	0x03	0x00	0x81	0x01	0xcc
+ */
+int
+process_is_hello (struct isis_circuit *circuit)
+{
+  struct isis_adjacency *adj;
+  int retval = ISIS_OK;
+  u_char neigh_len;
+  u_char *sysid;
+
+  /* In this point in time we are not yet able to handle is_hellos
+   * on lan - Sorry juniper...
+   */
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+    return retval;
+
+  neigh_len = stream_getc (circuit->rcv_stream);
+  sysid = STREAM_PNT(circuit->rcv_stream) + neigh_len - 1 - ISIS_SYS_ID_LEN;
+  adj = circuit->u.p2p.neighbor;
+  if (!adj) {
+    /* 8.2.2 */
+    adj = isis_new_adj (sysid, "      ", 0, circuit);
+    if (adj == NULL)
+      return ISIS_ERROR;
+
+    isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
+    adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
+    circuit->u.p2p.neighbor = adj;
+  }
+  /* 8.2.2 a)*/
+  if ((adj->adj_state == ISIS_ADJ_UP) && memcmp (adj->sysid,sysid,
+                                                 ISIS_SYS_ID_LEN)) {
+    /* 8.2.2 a) 1) FIXME: adjStateChange(down) event */
+    /* 8.2.2 a) 2) delete the adj */
+    XFREE (MTYPE_ISIS_ADJACENCY, adj);
+    /* 8.2.2 a) 3) create a new adj */
+    adj = isis_new_adj (sysid, "      ", 0, circuit);
+    if (adj == NULL)
+      return ISIS_ERROR;
+
+    /* 8.2.2 a) 3) i */
+    isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
+    /* 8.2.2 a) 3) ii */
+    adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
+    /* 8.2.2 a) 4) quite meaningless */
+  }
+  /* 8.2.2 b) ignore on condition */
+  if ((adj->adj_state == ISIS_ADJ_INITIALIZING) && 
+      (adj->sys_type == ISIS_SYSTYPE_IS)) {
+    /* do nothing */
+  } else {
+  /* 8.2.2 c) respond with a p2p IIH */
+    send_hello (circuit, 1);
+  }
+  /* 8.2.2 d) type is IS */
+    adj->sys_type = ISIS_SYSTYPE_IS;
+  /* 8.2.2 e) FIXME: Circuit type of? */
+
+
+  return retval;
+}
+
+
+/*
+ * PDU Dispatcher
+ */
+
+int 
+isis_handle_pdu (struct isis_circuit *circuit, u_char *ssnpa)
+{
+
+  struct isis_fixed_hdr *hdr;
+  struct esis_fixed_hdr *esis_hdr;
+
+  int retval=ISIS_OK;
+
+  /*
+   * Let's first read data from stream to the header
+   */
+  hdr = (struct isis_fixed_hdr*)STREAM_DATA(circuit->rcv_stream);
+
+  if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS)){
+    zlog_warn ("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp);
+    return ISIS_ERROR;
+  }
+
+  /* now we need to know if this is an ISO 9542 packet and
+   * take real good care of it, waaa!
+   */
+  if (hdr->idrp == ISO9542_ESIS){
+    esis_hdr = (struct esis_fixed_hdr*)STREAM_DATA(circuit->rcv_stream);
+    stream_set_getp (circuit->rcv_stream, ESIS_FIXED_HDR_LEN);
+    /* FIXME: Need to do some acceptence tests */
+    /* example length... */
+    switch (esis_hdr->pdu_type) {
+      case ESH_PDU:
+        /* FIXME */
+        break;
+      case ISH_PDU:
+        zlog_info ("AN ISH PDU!!");
+        retval = process_is_hello (circuit);
+        break;
+      default:
+        return ISIS_ERROR;
+      }
+    return retval;
+  } else {
+    stream_set_getp (circuit->rcv_stream, ISIS_FIXED_HDR_LEN);
+  }
+  /*
+   * and then process it
+   */
+
+  if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) {
+    zlog_err ("Fixed header length = %d", hdr->length);
+    return ISIS_ERROR;
+  }
+
+  if (hdr->version1 != 1) {
+    zlog_warn ("Unsupported ISIS version %u", hdr->version1);
+    return ISIS_WARNING;
+  }
+  /* either 6 or 0 */
+  if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN))  { 
+    zlog_err ("IDFieldLengthMismatch: ID Length field in a received PDU  %u, "
+                      "while the parameter for this IS is %u", hdr->id_len,
+                       ISIS_SYS_ID_LEN);
+    return ISIS_ERROR;
+  }
+
+  if (hdr->version2 != 1) {
+    zlog_warn ("Unsupported ISIS version %u", hdr->version2);
+    return ISIS_WARNING;
+  }
+  /* either 3 or 0 */
+  if ((hdr->max_area_addrs != 0) && (hdr->max_area_addrs != isis->max_area_addrs)) { 
+    zlog_err ("maximumAreaAddressesMismatch: maximumAreaAdresses in a "
+                      "received PDU %u while the parameter for this IS is %u",
+                       hdr->max_area_addrs, isis->max_area_addrs);
+    return ISIS_ERROR;
+  }
+
+  switch (hdr->pdu_type) {
+  case L1_LAN_HELLO:
+    retval = process_lan_hello (ISIS_LEVEL1, circuit, ssnpa);
+    break;
+  case L2_LAN_HELLO:
+    retval = process_lan_hello (ISIS_LEVEL2, circuit, ssnpa);
+    break;
+  case P2P_HELLO:
+    retval = process_p2p_hello (circuit);
+    break;
+  case L1_LINK_STATE:
+    retval = process_lsp (ISIS_LEVEL1, circuit, ssnpa);
+    break;
+  case L2_LINK_STATE:
+    retval = process_lsp (ISIS_LEVEL2, circuit, ssnpa);
+    break;
+  case L1_COMPLETE_SEQ_NUM:
+    retval = process_csnp (ISIS_LEVEL1, circuit, ssnpa);
+    break;
+  case L2_COMPLETE_SEQ_NUM:
+    retval = process_csnp (ISIS_LEVEL2, circuit, ssnpa);
+    break;
+  case L1_PARTIAL_SEQ_NUM:
+    retval = process_psnp (ISIS_LEVEL1, circuit, ssnpa);
+    break;
+  case L2_PARTIAL_SEQ_NUM:
+    retval = process_psnp (ISIS_LEVEL2, circuit, ssnpa);
+    break;
+  default:
+    return ISIS_ERROR;
+  }
+
+  return retval;
+}
+
+
+#ifdef GNU_LINUX
+int
+isis_receive (struct thread *thread)
+{
+
+  struct isis_circuit *circuit;
+  u_char ssnpa[ETH_ALEN];
+  int retval;
+
+  /*
+   * Get the circuit 
+   */
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  if (circuit->rcv_stream == NULL)
+    circuit->rcv_stream = stream_new (ISO_MTU(circuit));
+  else
+    stream_reset (circuit->rcv_stream);
+
+  retval = circuit->rx (circuit, ssnpa);
+  circuit->t_read = NULL;  
+
+  if (retval == ISIS_OK)
+    retval = isis_handle_pdu (circuit, ssnpa);
+
+  /* 
+   * prepare for next packet. 
+   */
+  circuit->t_read = thread_add_read (master, isis_receive, circuit, 
+                                     circuit->fd);
+
+  return retval;
+}
+
+#else
+int
+isis_receive (struct thread *thread)
+{
+
+  struct isis_circuit *circuit;
+  u_char ssnpa[ETH_ALEN];
+  int retval;
+
+  /*
+   * Get the circuit 
+   */
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  circuit->t_read = NULL;  
+
+  if (circuit->rcv_stream == NULL)
+    circuit->rcv_stream = stream_new (ISO_MTU(circuit));
+  else
+    stream_reset (circuit->rcv_stream);
+
+  retval = circuit->rx (circuit, ssnpa);
+
+  if (retval == ISIS_OK)
+    retval = isis_handle_pdu (circuit, ssnpa);
+
+  /* 
+   * prepare for next packet. 
+   */
+  circuit->t_read = thread_add_timer_msec (master, isis_receive, circuit, 
+                                           listcount
+                                           (circuit->area->circuit_list)*100);
+
+
+  return retval;
+}
+
+#endif
+
+ /* filling of the fixed isis header */
+void
+fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type)
+{
+  memset (hdr, 0, sizeof (struct isis_fixed_hdr));
+
+  hdr->idrp = ISO10589_ISIS;
+
+  switch (pdu_type) {
+  case L1_LAN_HELLO:
+  case L2_LAN_HELLO:
+    hdr->length = ISIS_LANHELLO_HDRLEN;
+    break;
+  case P2P_HELLO:
+    hdr->length = ISIS_P2PHELLO_HDRLEN;
+    break;
+  case L1_LINK_STATE:
+  case L2_LINK_STATE:
+    hdr->length = ISIS_LSP_HDR_LEN;
+    break;
+  case L1_COMPLETE_SEQ_NUM:
+  case L2_COMPLETE_SEQ_NUM:
+    hdr->length = ISIS_CSNP_HDRLEN;
+    break;
+  case L1_PARTIAL_SEQ_NUM:
+  case L2_PARTIAL_SEQ_NUM:
+    hdr->length = ISIS_PSNP_HDRLEN;
+    break;
+  default:
+    zlog_warn ("fill_fixed_hdr(): unknown pdu type %d", pdu_type);
+    return;
+  }
+  hdr->length += ISIS_FIXED_HDR_LEN;
+  hdr->pdu_type = pdu_type;
+  hdr->version1 = 1;
+  hdr->id_len = 0; /* ISIS_SYS_ID_LEN -  0==6 */
+  hdr->version2 = 1;
+  hdr->max_area_addrs = 0; /* isis->max_area_addrs -  0==3 */
+}
+
+
+/*
+ * SEND SIDE                             
+ */
+void
+fill_fixed_hdr_andstream (struct isis_fixed_hdr *hdr, u_char pdu_type,
+		struct stream *stream)
+{
+  fill_fixed_hdr (hdr,pdu_type);
+
+  stream_putc (stream, hdr->idrp);
+  stream_putc (stream, hdr->length);
+  stream_putc (stream, hdr->version1);
+  stream_putc (stream, hdr->id_len);
+  stream_putc (stream, hdr->pdu_type);
+  stream_putc (stream, hdr->version2);
+  stream_putc (stream, hdr->reserved);
+  stream_putc (stream, hdr->max_area_addrs);
+
+  return;
+}
+
+
+int
+send_hello (struct isis_circuit *circuit, int level)
+{
+  struct isis_fixed_hdr fixed_hdr;
+  struct isis_lan_hello_hdr hello_hdr;
+  struct isis_p2p_hello_hdr p2p_hello_hdr;
+
+  u_int32_t interval;
+  unsigned long len_pointer, length;
+  int retval;
+
+  if (circuit->interface->mtu == 0) {
+    zlog_warn ("circuit has zero MTU");
+    return ISIS_WARNING;
+  }
+
+  if (!circuit->snd_stream)
+    circuit->snd_stream = stream_new (ISO_MTU(circuit));
+  else
+    stream_reset (circuit->snd_stream);
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+    if (level == 1)
+      fill_fixed_hdr_andstream(&fixed_hdr, L1_LAN_HELLO, circuit->snd_stream);
+    else
+      fill_fixed_hdr_andstream(&fixed_hdr, L2_LAN_HELLO, circuit->snd_stream);
+  else
+      fill_fixed_hdr_andstream(&fixed_hdr, P2P_HELLO, circuit->snd_stream);
+
+  /*
+   * Fill LAN Level 1 or 2 Hello PDU header
+   */
+  memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr));
+  interval = circuit->hello_multiplier[level - 1] * 
+    circuit->hello_interval[level - 1];
+  if (interval > USHRT_MAX)
+    interval = USHRT_MAX;
+  hello_hdr.circuit_t = circuit->circuit_is_type;
+  memcpy (hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN);
+  hello_hdr.hold_time = htons((u_int16_t)interval);
+
+  hello_hdr.pdu_len   = 0;                   /* Update the PDU Length later */
+  len_pointer = stream_get_putp (circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN;   
+
+
+  /* copy the shared part of the hello to the p2p hello if needed */
+  if (circuit->circ_type == CIRCUIT_T_P2P) {
+    memcpy (&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN);
+    p2p_hello_hdr.local_id = circuit->circuit_id; 
+    /* FIXME: need better understanding */
+    stream_put  (circuit->snd_stream, &p2p_hello_hdr, ISIS_P2PHELLO_HDRLEN);
+  } else {
+    hello_hdr.prio = circuit->u.bc.priority[level - 1];
+    if(level == 1 && circuit->u.bc.l1_desig_is) {
+      memcpy(hello_hdr.lan_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
+    } else if (level == 2 && circuit->u.bc.l2_desig_is){
+      memcpy(hello_hdr.lan_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
+    }
+    stream_put  (circuit->snd_stream, &hello_hdr, ISIS_LANHELLO_HDRLEN);
+  }
+
+  /*
+   * Then the variable length part 
+   */
+  /* add circuit password */
+  if (circuit->passwd.type)
+    if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len,
+			  circuit->passwd.passwd, circuit->snd_stream))
+      return ISIS_WARNING;
+  /*  Area Addresses TLV */
+  assert (circuit->area);
+  if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0)
+    if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream))
+      return ISIS_WARNING;
+
+  /*  LAN Neighbors TLV */
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+    if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0)
+      if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], 
+          circuit->snd_stream))
+        return ISIS_WARNING;
+    if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0)
+      if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], 
+          circuit->snd_stream))
+        return ISIS_WARNING;
+  }
+
+  /* Protocols Supported TLV */
+  if (circuit->nlpids.count > 0) 
+    if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream))
+      return ISIS_WARNING;
+  /* IP interface Address TLV */
+  if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0)
+    if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream))
+      return ISIS_WARNING;
+
+#ifdef HAVE_IPV6 
+  /* IPv6 Interface Address TLV */
+  if (circuit->ipv6_router && circuit->ipv6_link && 
+      circuit->ipv6_link->count > 0)
+    if (tlv_add_ipv6_addrs (circuit->ipv6_link, circuit->snd_stream))
+      return ISIS_WARNING;
+#endif /* HAVE_IPV6 */
+
+  if (circuit->u.bc.pad_hellos)
+    if (tlv_add_padding (circuit->snd_stream))
+      return ISIS_WARNING;
+
+  length = stream_get_putp (circuit->snd_stream);
+  /* Update PDU length */
+  stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t)length);
+
+  retval = circuit->tx (circuit, level);
+  if (retval)
+    zlog_warn ("sending of LAN Level %d Hello failed", level);
+
+  /* DEBUG_ADJ_PACKETS */
+  if (isis->debugs & DEBUG_ADJ_PACKETS) {
+    if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+      zlog_info ("ISIS-Adj (%s): Sent L%d LAN IIH on %s, length %ld",
+                 circuit->area->area_tag, level, circuit->interface->name,
+                 STREAM_SIZE(circuit->snd_stream));
+    } else {
+      zlog_info ("ISIS-Adj (%s): Sent P2P IIH on %s, length %ld",
+                 circuit->area->area_tag, circuit->interface->name,
+                 STREAM_SIZE(circuit->snd_stream));
+    }
+  }
+
+
+  return retval;
+}
+
+int
+send_lan_hello (struct isis_circuit *circuit, int level)
+{
+  return send_hello (circuit,level);
+}
+
+int
+send_lan_l1_hello (struct thread *thread)
+{
+
+  struct isis_circuit *circuit;
+  int retval;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+  circuit->u.bc.t_send_lan_hello[0] = NULL;
+
+  if (circuit->u.bc.run_dr_elect[0])
+    retval = isis_dr_elect (circuit, 1); 
+
+  retval = send_lan_hello (circuit, 1);
+
+  /* set next timer thread */
+  circuit->u.bc.t_send_lan_hello[0] = 
+    thread_add_timer (master, send_lan_l1_hello, circuit, 
+                     isis_jitter (circuit->hello_interval[0], IIH_JITTER));
+
+  return retval;
+}
+
+int
+send_lan_l2_hello (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  int retval;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+  circuit->u.bc.t_send_lan_hello[1] = NULL;
+
+  if (circuit->u.bc.run_dr_elect[1])
+    retval = isis_dr_elect (circuit, 2);
+
+  retval = send_lan_hello (circuit, 2);
+
+  /* set next timer thread*/
+  circuit->u.bc.t_send_lan_hello[1] = 
+    thread_add_timer (master, send_lan_l2_hello, circuit, 
+                      isis_jitter (circuit->hello_interval[1], IIH_JITTER));
+
+  return retval;
+}
+
+int
+send_p2p_hello (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+  circuit->u.p2p.t_send_p2p_hello = NULL;
+
+  send_hello(circuit,1);
+
+  /* set next timer thread*/
+  circuit->u.p2p.t_send_p2p_hello = thread_add_timer
+    (master, send_p2p_hello, circuit, isis_jitter (circuit->hello_interval[1],
+                                                   IIH_JITTER));
+
+  return ISIS_OK;
+}
+
+int
+build_csnp (int level, u_char *start, u_char *stop, struct list *lsps, 
+            struct isis_circuit *circuit)
+{
+  struct isis_fixed_hdr fixed_hdr;
+  struct isis_passwd *passwd;
+  int retval = ISIS_OK;
+  unsigned long lenp;
+  u_int16_t length;
+
+  if (level ==1)
+    fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM, 
+                              circuit->snd_stream);
+  else
+    fill_fixed_hdr_andstream (&fixed_hdr, L2_COMPLETE_SEQ_NUM, 
+                              circuit->snd_stream);
+
+  /*
+   * Fill Level 1 or 2 Complete Sequence Numbers header
+   */
+
+  lenp = stream_get_putp (circuit->snd_stream);
+  stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */
+  /* no need to send the source here, it is always us if we csnp */
+  stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
+  /* with zero circuit id - ref 9.10, 9.11 */
+  stream_putc (circuit->snd_stream, 0x00);
+
+  stream_put (circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2);
+  stream_put (circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2);
+
+  /*
+   * And TLVs
+   */
+  if (level == 1)
+    passwd = &circuit->area->area_passwd;
+  else
+    passwd = &circuit->area->domain_passwd;
+
+  if (passwd->type)
+    retval = tlv_add_authinfo (passwd->type, passwd->len,
+			       passwd->passwd, circuit->snd_stream);
+
+  if (!retval && lsps) { 
+    retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
+  } 
+  length = (u_int16_t)stream_get_putp (circuit->snd_stream);
+  assert (length >= ISIS_CSNP_HDRLEN);
+  /* Update PU length */
+  stream_putw_at (circuit->snd_stream, lenp, length);
+
+  return retval;
+}
+
+/*
+ * FIXME: support multiple CSNPs
+ */
+
+int
+send_csnp (struct isis_circuit *circuit, int level)
+{
+  int retval = ISIS_OK;
+  u_char start[ISIS_SYS_ID_LEN + 2];
+  u_char stop[ISIS_SYS_ID_LEN + 2];
+  struct list *list = NULL;
+  struct listnode *node;
+  struct isis_lsp *lsp;
+
+  memset (start,0x00, ISIS_SYS_ID_LEN + 2);
+  memset (stop, 0xff, ISIS_SYS_ID_LEN + 2);
+
+  if (circuit->area->lspdb[level-1] && 
+      dict_count (circuit->area->lspdb[level-1]) > 0) {
+    list = list_new ();
+    lsp_build_list (start, stop, list, circuit->area->lspdb[level-1]);
+
+    if (circuit->snd_stream == NULL)
+      circuit->snd_stream = stream_new (ISO_MTU(circuit));
+    else
+      stream_reset (circuit->snd_stream);
+
+    retval = build_csnp  (level, start, stop, list, circuit);
+
+    if (isis->debugs & DEBUG_SNP_PACKETS) { 
+      zlog_info ("ISIS-Snp (%s): Sent L%d CSNP on %s, length %ld",
+                 circuit->area->area_tag, level, circuit->interface->name,
+                 STREAM_SIZE(circuit->snd_stream));
+      LIST_LOOP (list, lsp, node) {
+        zlog_info("ISIS-Snp (%s):         CSNP entry %s, seq 0x%08x,"
+                  " cksum 0x%04x, lifetime %us", 
+                  circuit->area->area_tag,
+                  rawlspid_print (lsp->lsp_header->lsp_id),
+                  ntohl (lsp->lsp_header->seq_num),
+                  ntohs (lsp->lsp_header->checksum),
+                  ntohs (lsp->lsp_header->rem_lifetime));
+      }
+    }
+
+    list_delete (list);
+
+    if (retval == ISIS_OK)
+      retval = circuit->tx (circuit, level);
+  }
+  return retval;
+}
+
+int
+send_l1_csnp (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  int retval = ISIS_OK;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  circuit->t_send_csnp[0] = NULL;
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0]) {
+    send_csnp(circuit,1);
+  }
+  /* set next timer thread */
+  circuit->t_send_csnp[0] = thread_add_timer (master, 
+                                              send_l1_csnp,
+                                              circuit, 
+                                              isis_jitter 
+                                              (circuit->csnp_interval[0],
+                                               CSNP_JITTER));
+
+  return retval;
+}
+
+int
+send_l2_csnp (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  int retval = ISIS_OK;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  circuit->t_send_csnp[1] = NULL;
+
+  if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1]) {
+    send_csnp(circuit,2);
+  }
+  /* set next timer thread */
+  circuit->t_send_csnp[1] = thread_add_timer (master, 
+                                              send_l2_csnp,
+                                              circuit, 
+                                              isis_jitter 
+                                              (circuit->csnp_interval[1],
+                                               CSNP_JITTER));
+  return retval;
+}
+
+int
+build_psnp (int level, struct isis_circuit *circuit, struct list *lsps)
+{
+  struct isis_fixed_hdr fixed_hdr;
+  unsigned long lenp;
+  u_int16_t length;
+  int retval = 0;
+  struct isis_lsp *lsp;
+  struct isis_passwd *passwd;
+  struct listnode *node;
+
+  if (level == 1)
+    fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, 
+                              circuit->snd_stream);
+  else
+    fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM,
+                              circuit->snd_stream);
+
+  /*
+   * Fill Level 1 or 2 Partial Sequence Numbers header
+   */
+  lenp = stream_get_putp (circuit->snd_stream);
+  stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */
+  stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
+  stream_putc (circuit->snd_stream, circuit->idx);
+
+  /*
+   * And TLVs
+   */
+
+  if (level == 1)
+    passwd = &circuit->area->area_passwd;
+  else
+    passwd = &circuit->area->domain_passwd;
+
+  if (passwd->type)
+    retval = tlv_add_authinfo (passwd->type, passwd->len,
+			       passwd->passwd, circuit->snd_stream);
+
+  if (!retval && lsps) { 
+    retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
+  }
+
+  if (isis->debugs & DEBUG_SNP_PACKETS) {
+    LIST_LOOP (lsps, lsp, node) {
+      zlog_info("ISIS-Snp (%s):         PSNP entry %s, seq 0x%08x,"
+                " cksum 0x%04x, lifetime %us", 
+                circuit->area->area_tag,
+                rawlspid_print (lsp->lsp_header->lsp_id),
+                ntohl (lsp->lsp_header->seq_num),
+                ntohs (lsp->lsp_header->checksum),
+                ntohs (lsp->lsp_header->rem_lifetime));
+    }
+  }
+
+  length = (u_int16_t)stream_get_putp (circuit->snd_stream);
+  assert (length >= ISIS_PSNP_HDRLEN);
+  /* Update PDU length */
+  stream_putw_at (circuit->snd_stream, lenp, length);
+
+  return ISIS_OK;
+}
+
+/*
+ *  7.3.15.4 action on expiration of partial SNP interval
+ *  level 1
+ */
+int
+send_psnp (int level, struct isis_circuit *circuit)
+{
+  int retval = ISIS_OK;
+  struct isis_lsp *lsp;
+  struct list *list = NULL;
+  struct listnode *node;
+
+  if ((circuit->circ_type == CIRCUIT_T_BROADCAST && 
+       !circuit->u.bc.is_dr[level - 1]) ||
+      circuit->circ_type != CIRCUIT_T_BROADCAST) {
+
+    if (circuit->area->lspdb[level-1] && 
+        dict_count (circuit->area->lspdb[level-1]) > 0) {
+      list = list_new ();
+      lsp_build_list_ssn (circuit, list, circuit->area->lspdb[level-1]);
+
+      if (listcount(list) > 0) {
+        if (circuit->snd_stream == NULL)
+          circuit->snd_stream = stream_new (ISO_MTU(circuit));
+        else
+          stream_reset (circuit->snd_stream);
+
+
+        if (isis->debugs & DEBUG_SNP_PACKETS) 
+          zlog_info ("ISIS-Snp (%s): Sent L%d PSNP on %s, length %ld",
+                     circuit->area->area_tag, level, circuit->interface->name,
+                     STREAM_SIZE(circuit->snd_stream));
+
+        retval = build_psnp (level, circuit, list);
+        if (retval == ISIS_OK)
+          retval = circuit->tx (circuit, level);
+
+        if (retval == ISIS_OK) {
+          /*
+           * sending succeeded, we can clear SSN flags of this circuit
+           * for the LSPs in list
+           */
+          for (node = listhead (list); node; nextnode(node)) {
+            lsp = getdata (node);
+            ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
+          }
+        }
+      }
+      list_delete (list);
+    }
+  }
+
+  return retval;
+}
+
+int
+send_l1_psnp (struct thread *thread)
+{
+
+  struct isis_circuit *circuit;
+  int retval = ISIS_OK;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  circuit->t_send_psnp[0] = NULL;
+
+  send_psnp (1, circuit);
+  /* set next timer thread */
+  circuit->t_send_psnp[0] = thread_add_timer (master,
+                                              send_l1_psnp,
+                                              circuit,
+                                              isis_jitter
+                                              (circuit->psnp_interval[0], 
+                                               PSNP_JITTER));
+
+  return retval;
+}
+
+/*
+ *  7.3.15.4 action on expiration of partial SNP interval
+ *  level 2
+ */
+int
+send_l2_psnp (struct thread *thread)
+{
+
+  struct isis_circuit *circuit;
+  int retval = ISIS_OK;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  circuit->t_send_psnp[1] = NULL;
+
+  send_psnp (2, circuit);
+
+  /* set next timer thread */
+  circuit->t_send_psnp[1] = thread_add_timer (master,
+                                              send_l2_psnp,
+                                              circuit,
+                                              isis_jitter
+                                              (circuit->psnp_interval[1],
+                                               PSNP_JITTER));
+
+  return retval;
+}
+
+
+void
+build_link_state (struct isis_lsp *lsp, struct isis_circuit *circuit,
+                  struct stream *stream)
+{
+  unsigned long length;
+
+  stream_put  (stream, lsp->pdu, ntohs(lsp->lsp_header->pdu_len));
+  length = stream_get_putp (stream); 
+
+  return;
+}
+
+
+/*
+ * ISO 10589 - 7.3.14.3
+ */
+int
+send_lsp (struct thread *thread)
+{
+  struct isis_circuit *circuit;
+  struct isis_lsp *lsp;
+  struct listnode *node;
+  int retval = 0;
+
+  circuit = THREAD_ARG (thread);
+  assert (circuit);
+
+  if (circuit->state == C_STATE_UP) {
+    node = listhead (circuit->lsp_queue);
+    assert (node);
+
+    lsp = getdata (node);
+
+    /*
+     * Do not send if levels do not match
+     */
+    if (!(lsp->level & circuit->circuit_is_type))
+      goto dontsend;
+
+    /*
+     * Do not send if we do not have adjacencies in state up on the circuit
+     */
+    if (circuit->upadjcount[lsp->level - 1] == 0)
+      goto dontsend;
+    /* only send if it needs sending */
+    if ((time(NULL) - lsp->last_sent) >= 
+         circuit->area->lsp_gen_interval[lsp->level-1]) {
+
+      if (isis->debugs & DEBUG_UPDATE_PACKETS) {
+        zlog_info ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x,"
+                   " lifetime %us on %s",
+                   circuit->area->area_tag,
+		   lsp->level, 
+                   rawlspid_print (lsp->lsp_header->lsp_id),
+                   ntohl(lsp->lsp_header->seq_num),
+		   ntohs(lsp->lsp_header->checksum),
+                   ntohs(lsp->lsp_header->rem_lifetime), 
+                   circuit->interface->name);
+      }
+      /* copy our lsp to the send buffer */
+      circuit->snd_stream->getp = lsp->pdu->getp;
+      circuit->snd_stream->putp = lsp->pdu->putp;
+      circuit->snd_stream->endp = lsp->pdu->endp;
+      memcpy (circuit->snd_stream->data, lsp->pdu->data, lsp->pdu->endp);
+
+      retval = circuit->tx (circuit, lsp->level);
+
+      /*
+       * If the sending succeeded, we can del the lsp from circuits lsp_queue
+       */
+      if (retval == ISIS_OK) {
+        list_delete_node (circuit->lsp_queue, node);
+
+	/*
+	 * On broadcast circuits also the SRMflag can be cleared
+	 */
+	if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+	  ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
+
+	if (flags_any_set (lsp->SRMflags) == 0) {
+	  /*
+	   * need to remember when we were last sent
+	   */
+	  lsp->last_sent = time (NULL);
+	}
+      } else {
+        zlog_info ("sending of level %d link state failed", lsp->level);
+      }
+    } else {
+      /* my belief is that if it wasn't his time, the lsp can be removed
+       * from the queue
+       */
+    dontsend:
+      list_delete_node (circuit->lsp_queue, node);
+    }
+#if 0
+    /*
+     * If there are still LSPs send next one after lsp-interval (33 msecs)
+     */
+    if (listcount (circuit->lsp_queue) > 0)
+      thread_add_timer (master, send_lsp, circuit,
+                             1);
+#endif
+  }
+
+  return retval;
+} 
+
+int
+ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, 
+         int level)
+{
+  unsigned long lenp;
+  int retval;
+  u_int16_t length;
+  struct isis_fixed_hdr fixed_hdr;
+
+  if (!circuit->snd_stream)
+    circuit->snd_stream = stream_new (ISO_MTU(circuit));
+  else
+    stream_reset (circuit->snd_stream);
+
+//  fill_llc_hdr (stream);
+  if (level == 1)
+    fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, 
+                              circuit->snd_stream);
+  else
+    fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM, 
+                              circuit->snd_stream);
+
+
+  lenp = stream_get_putp (circuit->snd_stream);
+  stream_putw (circuit->snd_stream, 0); /* PDU length  */
+  stream_put  (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
+  stream_putc (circuit->snd_stream, circuit->idx);
+  stream_putc (circuit->snd_stream, 9); /* code */
+  stream_putc (circuit->snd_stream, 16); /* len */
+
+  stream_putw (circuit->snd_stream, ntohs(hdr->rem_lifetime));
+  stream_put  (circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2);
+  stream_putl (circuit->snd_stream, ntohl(hdr->seq_num));
+  stream_putw (circuit->snd_stream, ntohs(hdr->checksum));
+
+  length = (u_int16_t)stream_get_putp (circuit->snd_stream);
+  /* Update PDU length */
+  stream_putw_at (circuit->snd_stream, lenp, length);
+
+  retval = circuit->tx (circuit, level);
+
+  return retval;
+}
+
+#if 0
+/*
+ * ISH PDU Processing 
+ */
+
+
+  /*
+   * Let's first check if the local and remote system have any common area
+   * addresses 
+   */
+  if (area_match(tlvs.area_addrs, isis->man_area_addrs) == 0) {
+    if (circuit->circuit_t == IS_LEVEL_2) {
+      /* do as in table 8 (p. 40) */
+      switch (circuit_type) {
+      case IS_LEVEL_1:
+	if (adj->adj_state != ISIS_ADJ_UP) {
+	  /* Reject */
+	  zlog_warn("areaMismatch");
+	  retval = ISIS_WARNING;
+	} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
+	  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch",
+				 circuit->adjdb);
+	} else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2 || 
+		   adj->adj_usage == ISIS_ADJ_LEVEL2) {
+	  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System",
+				 circuit->adjdb);
+	}
+	break;
+      case IS_LEVEL_2:
+	if (adj->adj_state != ISIS_ADJ_UP) {
+	  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL, circuit->adjdb);
+	  adj->adj_usage = ISIS_ADJ_LEVEL2;
+	} else if (adj->adj_usage == ISIS_ADJ_LEVEL1 || 
+	           adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { 
+	  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System",
+				 circuit->adjdb);
+	} else if (adj->adj_usage == ISIS_ADJ_LEVEL2) {
+	    ; /* Accept */
+	}
+	break;
+      case IS_LEVEL_1_AND_2:
+	if (adj->adj_state != ISIS_ADJ_UP) {
+	  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL, circuit->adjdb);
+	  adj->adj_usage = ISIS_ADJ_LEVEL2;
+	} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
+	  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System",
+				 circuit->adjdb);
+	} else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { 
+	  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch",
+				 circuit->adjdb);
+	} else if (adj->adj_usage == ISIS_ADJ_LEVEL2) {
+	    ; /* Accept */
+	}
+	break;
+      }
+      goto mismatch;
+    } else {
+      isis_delete_adj (adj, circuit->adjdb);
+      zlog_warn("areaMismatch");
+      return ISIS_WARNING;
+    }
+  }
+
+mismatch:
+#endif
+
+
+
+
diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h
new file mode 100644
index 0000000..9940368
--- /dev/null
+++ b/isisd/isis_pdu.h
@@ -0,0 +1,257 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_pdu.h
+ *                             PDU processing
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_PDU_H
+#define _ZEBRA_ISIS_PDU_H
+
+/*
+ *                    ISO 9542 - 7.5,7.6
+ *
+ *                       ES to IS Fixed Header
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |         Intradomain Routeing Protocol Discriminator           |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                       Length Indicator                        |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                  Version/Protocol ID extension                |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                         Reserved = 0                          |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |   0   |   0   |   0   |              PDU Type                 |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                         Holding Time                          | 2
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                          Checksum                             | 2
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+
+struct esis_fixed_hdr
+{
+  u_char idrp;
+  u_char length;
+  u_char version;
+  u_char id_len;
+  u_char pdu_type;
+  u_int16_t holdtime;
+  u_int16_t checksum;
+}  __attribute__((packed));
+
+#define ESIS_FIXED_HDR_LEN   9
+
+#define ESH_PDU              2
+#define ISH_PDU              4
+#define RD_PDU               5
+
+/*
+ *                       IS to IS Fixed Header
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |         Intradomain Routeing Protocol Discriminator           | 
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                       Length Indicator                        |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                  Version/Protocol ID extension                |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |   R   |   R   |   R   |              PDU Type                 |      
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                            Version                            |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                            Reserved                           |
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  |                       Maximum Area Addresses                  |      
+ *  +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+
+struct isis_fixed_hdr 
+{
+  u_char idrp;
+  u_char length;
+  u_char version1;
+  u_char id_len;
+  u_char pdu_type;
+  u_char version2;
+  u_char reserved;
+  u_char max_area_addrs;
+};
+
+#define ISIS_FIXED_HDR_LEN 8
+
+/*
+ * IS-IS PDU types.
+ */
+
+#define L1_LAN_HELLO         15
+#define L2_LAN_HELLO         16
+/*
+ *              L1 and L2 LAN IS to IS Hello PDU header
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                       Reserved                | Circuit Type  | 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Source ID                              + id_len   
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                        Holding  Time                          | 2     
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                        PDU Lenght                             | 2    
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |   R   |                Priority                               | 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                        LAN ID                                 | id_len + 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+struct isis_lan_hello_hdr {
+  u_char circuit_t;  
+  u_char source_id[ISIS_SYS_ID_LEN];   
+  u_int16_t hold_time;     
+  u_int16_t pdu_len;      
+  u_char prio;         
+  u_char lan_id[ISIS_SYS_ID_LEN + 1];      
+}  __attribute__((packed));
+#define ISIS_LANHELLO_HDRLEN  19
+
+#define P2P_HELLO            17
+/*
+ *           Point-to-point IS to IS hello PDU header
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                        Reserved               | Circuit Type  | 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Source ID                              + id_len   
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Holding  Time                          + 2     
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        PDU Lenght                             + 2    
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                        Local Circuit ID                       | 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+struct isis_p2p_hello_hdr {
+  u_char circuit_t;  
+  u_char source_id[ISIS_SYS_ID_LEN];   
+  u_int16_t hold_time;     
+  u_int16_t pdu_len;      
+  u_char local_id;
+} __attribute__((packed));
+#define ISIS_P2PHELLO_HDRLEN 12
+
+#define L1_LINK_STATE        18
+#define L2_LINK_STATE        20
+/*
+ *              L1 and L2 IS to IS link state PDU header
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        PDU Length                             + 2
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Remaining Lifetime                     + 2 
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                        LSP ID                                 | id_len + 2
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Sequence Number                        + 4
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Checksum                               + 2
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |   P   |              ATT              |LSPDBOL|    ISTYPE     |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+struct isis_link_state_hdr {
+  u_int16_t pdu_len;      
+  u_int16_t rem_lifetime;
+  u_char  lsp_id[ISIS_SYS_ID_LEN + 2];
+  u_int32_t seq_num;
+  u_int16_t checksum;
+  u_int8_t  lsp_bits;
+} __attribute__((packed)); 
+#define ISIS_LSP_HDR_LEN 19
+
+#define L1_COMPLETE_SEQ_NUM  24
+#define L2_COMPLETE_SEQ_NUM  25
+/*
+ *      L1 and L2 IS to IS complete sequence numbers PDU header
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        PDU Lenght                             + 2    
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Source ID                              + id_len + 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Start LSP ID                           + id_len + 2
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        End LSP ID                             + id_len + 2
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+struct isis_complete_seqnum_hdr {
+  u_int16_t pdu_len;
+  u_char    source_id[ISIS_SYS_ID_LEN + 1];
+  u_char    start_lsp_id[ISIS_SYS_ID_LEN + 2];
+  u_char    stop_lsp_id[ISIS_SYS_ID_LEN + 2];
+};
+#define ISIS_CSNP_HDRLEN 25
+
+#define L1_PARTIAL_SEQ_NUM   26
+#define L2_PARTIAL_SEQ_NUM   27
+/*
+ *      L1 and L2 IS to IS partial sequence numbers PDU header
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        PDU Length                             + 2
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * +                        Source ID                              + id_len + 1
+ * +---------------------------------------------------------------+
+ */
+struct isis_partial_seqnum_hdr {
+  u_int16_t pdu_len;
+  u_char    source_id[ISIS_SYS_ID_LEN + 1];
+};
+#define ISIS_PSNP_HDRLEN 9
+
+/*
+ * Function for receiving IS-IS PDUs
+ */
+int isis_receive (struct thread *thread);
+
+/*
+ * calling arguments for snp_process ()
+ */
+#define ISIS_SNP_PSNP_FLAG 0
+#define ISIS_SNP_CSNP_FLAG 1
+
+/*
+ * Sending functions
+ */
+int  send_lan_l1_hello (struct thread *thread);
+int  send_lan_l2_hello (struct thread *thread);
+int  send_p2p_hello    (struct thread *thread);
+int  send_csnp         (struct isis_circuit *circuit, int level);
+int  send_l1_csnp      (struct thread *thread);
+int  send_l2_csnp      (struct thread *thread);
+int  send_l1_psnp      (struct thread *thread);
+int  send_l2_psnp      (struct thread *thread);
+int  send_lsp          (struct thread *thread);
+int  ack_lsp           (struct isis_link_state_hdr *hdr, 
+			struct isis_circuit *circuit, int level);
+void fill_fixed_hdr    (struct isis_fixed_hdr *hdr, u_char pdu_type);
+int  send_hello        (struct isis_circuit *circuit, int level);
+
+
+int authentication_check (struct isis_passwd *one, 
+			  struct isis_passwd *theother);
+
+#endif /* _ZEBRA_ISIS_PDU_H */
+
+
+
+
+
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
new file mode 100644
index 0000000..74231ad
--- /dev/null
+++ b/isisd/isis_route.c
@@ -0,0 +1,615 @@
+/*
+ * IS-IS Rout(e)ing protocol               - isis_route.c
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ *                                         based on ../ospf6d/ospf6_route.[ch]
+ *                                         by Yasuhiro Ohara
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "thread.h"
+#include "linklist.h"
+#include "vty.h"
+#include "log.h"
+#include "memory.h"
+#include "prefix.h"
+#include "hash.h"
+#include "if.h"
+#include "table.h"
+
+#include "isis_constants.h"
+#include "isis_common.h"
+#include "dict.h"
+#include "isisd.h"
+#include "isis_misc.h"
+#include "isis_adjacency.h"
+#include "isis_circuit.h"
+#include "isis_tlv.h"
+#include "isis_pdu.h"
+#include "isis_lsp.h"
+#include "isis_spf.h"
+#include "isis_route.h"
+#include "isis_zebra.h"
+
+extern struct isis *isis;
+extern struct thread_master *master;
+
+struct isis_nexthop *
+isis_nexthop_create (struct in_addr *ip, unsigned int ifindex)
+                     
+{
+  struct listnode *node;
+  struct isis_nexthop *nexthop;
+  
+  for (node = listhead (isis->nexthops); node; nextnode (node)) {
+    nexthop = getdata (node);
+    if (nexthop->ifindex != ifindex)
+      continue;
+    if (ip && memcmp (&nexthop->ip, ip, sizeof (struct in_addr)) != 0)
+      continue; 
+
+    nexthop->lock++;
+    return nexthop;
+  }
+  
+  nexthop = XMALLOC (MTYPE_ISIS_NEXTHOP, sizeof (struct isis_nexthop));
+  if (!nexthop) {
+    zlog_err ("ISIS-Rte: isis_nexthop_create: out of memory!");
+  }
+  
+  memset (nexthop, 0, sizeof (struct isis_nexthop));
+  nexthop->ifindex = ifindex;
+  memcpy (&nexthop->ip, ip, sizeof (struct in_addr));
+  listnode_add (isis->nexthops, nexthop);
+  nexthop->lock++;
+
+  return nexthop;
+}
+
+
+void
+isis_nexthop_delete (struct isis_nexthop *nexthop)
+{
+  nexthop->lock--;
+  if (nexthop->lock == 0) {
+    listnode_delete (isis->nexthops, nexthop);
+    XFREE (MTYPE_ISIS_NEXTHOP, nexthop);
+  }
+    
+  return;
+}
+
+int
+nexthoplookup (struct list *nexthops, struct in_addr *ip, 
+               unsigned int ifindex)
+{
+  struct listnode *node;
+  struct isis_nexthop *nh;
+
+  for (node = listhead (nexthops); node; nextnode (node)) {
+    nh = getdata (node);
+    if (!(memcmp (ip, &nh->ip, sizeof (struct in_addr))) && 
+        ifindex == nh->ifindex)
+      return 1;
+  }
+
+  return 0;
+}
+
+void
+nexthop_print (struct isis_nexthop *nh)
+{
+  u_char buf[BUFSIZ];
+  
+  inet_ntop (AF_INET, &nh->ip, buf, BUFSIZ);
+  
+  zlog_info ("      %s %u", buf, nh->ifindex);
+}
+
+void
+nexthops_print (struct list *nhs)
+{
+  struct listnode *node;
+  
+  for (node = listhead(nhs); node; nextnode (node))
+    nexthop_print (getdata (node));
+}
+
+#ifdef HAVE_IPV6
+
+struct isis_nexthop6 *
+isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex) 
+{
+  
+  struct isis_nexthop6 *nexthop6;
+  
+  nexthop6 = XMALLOC (MTYPE_ISIS_NEXTHOP6, sizeof (struct isis_nexthop6));
+  if (!nexthop6) {
+    zlog_err ("ISIS-Rte: isis_nexthop_create6: out of memory!");
+  }
+  
+  memset (nexthop6, 0, sizeof (struct isis_nexthop6));
+  nexthop6->ifindex = ifindex;
+  memcpy (&nexthop6->ip6, ip6, sizeof (struct in6_addr));
+  nexthop6->lock++;
+
+  return nexthop6;
+}
+
+struct isis_nexthop6 *
+isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex)
+                     
+{
+  struct listnode *node;
+  struct isis_nexthop6 *nexthop6;
+  
+  for (node = listhead (isis->nexthops6); node; nextnode (node)) {
+    nexthop6 = getdata (node);
+    if (nexthop6->ifindex != ifindex)
+      continue;
+    if (ip6 && memcmp (&nexthop6->ip6, ip6, sizeof (struct in6_addr)) != 0)
+      continue; 
+
+    nexthop6->lock++;
+    return nexthop6;
+  }
+  
+  nexthop6 = isis_nexthop6_new (ip6, ifindex);
+
+  return nexthop6;
+}
+
+
+void
+isis_nexthop6_delete (struct isis_nexthop6 *nexthop6)
+{
+
+  nexthop6->lock--;
+  if (nexthop6->lock == 0) {
+    listnode_delete (isis->nexthops6, nexthop6);
+    XFREE (MTYPE_ISIS_NEXTHOP6, nexthop6);
+  }
+    
+  return;
+}
+
+int
+nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6, 
+                unsigned int ifindex)
+{
+  struct listnode *node;
+  struct isis_nexthop6 *nh6;
+
+  for (node = listhead (nexthops6); node; nextnode (node)) {
+    nh6 = getdata (node);
+    if (!(memcmp (ip6, &nh6->ip6, sizeof (struct in6_addr))) && 
+        ifindex == nh6->ifindex)
+      return 1;
+  }
+
+  return 0;
+}
+
+void
+nexthop6_print (struct isis_nexthop6 *nh6)
+{
+  u_char buf[BUFSIZ];
+  
+  inet_ntop (AF_INET6, &nh6->ip6, buf, BUFSIZ);
+  
+  zlog_info ("      %s %u", buf, nh6->ifindex);
+}
+
+void
+nexthops6_print (struct list *nhs6)
+{
+  struct listnode *node;
+  
+  for (node = listhead(nhs6); node; nextnode (node))
+    nexthop6_print (getdata (node));
+}
+
+
+#endif /* HAVE_IPV6 */
+
+void
+adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj)
+{
+  struct isis_nexthop *nh;
+  struct listnode *node;
+  struct in_addr *ipv4_addr;
+
+  if (adj->ipv4_addrs == NULL)
+    return;
+  for (node = listhead (adj->ipv4_addrs); node; nextnode (node)) {
+    ipv4_addr = getdata (node);
+    if (!nexthoplookup (nexthops, ipv4_addr, 
+                        adj->circuit->interface->ifindex)) {
+      nh = isis_nexthop_create (ipv4_addr, 
+                                adj->circuit->interface->ifindex);
+      listnode_add (nexthops, nh);
+    }
+  }
+}
+
+#ifdef HAVE_IPV6
+void
+adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
+{
+  struct listnode *node;
+  struct in6_addr *ipv6_addr;
+  struct isis_nexthop6 *nh6;
+  
+  if (!adj->ipv6_addrs)
+    return;
+
+  for (node = listhead (adj->ipv6_addrs); node; nextnode (node)) {
+    ipv6_addr = getdata (node);
+    if (!nexthop6lookup (nexthops6, ipv6_addr, 
+                         adj->circuit->interface->ifindex)) {
+      nh6 = isis_nexthop6_create (ipv6_addr, 
+                                  adj->circuit->interface->ifindex);
+      listnode_add (nexthops6, nh6);
+    }
+  }
+}
+#endif /* HAVE_IPV6 */
+
+struct isis_route_info *
+isis_route_info_new (uint32_t cost, uint32_t depth, u_char family, 
+                     struct list *adjacencies)
+{
+  struct isis_route_info *rinfo;
+  struct isis_adjacency *adj;
+  struct listnode *node;
+  
+  rinfo = XMALLOC (MTYPE_ISIS_ROUTE_INFO, sizeof (struct isis_route_info));
+  if (!rinfo) {
+    zlog_err ("ISIS-Rte: isis_route_info_new: out of memory!");
+    return NULL;
+  }
+  memset (rinfo, 0, sizeof (struct isis_route_info));
+
+  if (family == AF_INET) {
+    rinfo->nexthops = list_new ();
+    for (node = listhead (adjacencies); node; nextnode (node)) {
+      adj = getdata (node);
+      adjinfo2nexthop (rinfo->nexthops, adj);
+    }
+  }
+#ifdef HAVE_IPV6
+  if (family == AF_INET6) {
+    rinfo->nexthops6 = list_new ();
+    for (node = listhead (adjacencies); node; nextnode (node)) {
+      adj =getdata (node);
+      adjinfo2nexthop6 (rinfo->nexthops6, adj);
+    }
+  }
+    
+#endif /* HAVE_IPV6 */
+
+  rinfo->cost = cost;
+  rinfo->depth = depth;
+      
+  return rinfo;
+}
+
+
+void
+isis_route_info_delete (struct isis_route_info *route_info)
+{
+  
+  if (route_info->nexthops) {
+    route_info->nexthops->del = (void *)isis_nexthop_delete;
+    list_delete (route_info->nexthops);
+  }
+   
+#ifdef HAVE_IPV6
+  if (route_info->nexthops6) {
+      route_info->nexthops6->del = (void *)isis_nexthop6_delete;
+      list_delete (route_info->nexthops6);
+  }
+#endif /* HAVE_IPV6 */
+ 
+  XFREE (MTYPE_ISIS_ROUTE_INFO, route_info);
+}
+
+int
+isis_route_info_same_attrib (struct isis_route_info *new, 
+                             struct isis_route_info *old)
+{
+  if (new->cost != old->cost)
+    return 0;
+  if (new->depth != old->depth)
+    return 0;
+  
+  return 1;
+}
+
+int
+isis_route_info_same (struct isis_route_info *new, struct isis_route_info *old,
+                      u_char family)
+{
+  struct listnode  *node;
+  struct isis_nexthop *nexthop;
+#ifdef HAVE_IPV6
+  struct isis_nexthop6 *nexthop6;
+#endif /* HAVE_IPV6 */
+  if (!isis_route_info_same_attrib (new, old))
+    return 0;
+  
+  if (family == AF_INET) {
+    for (node = listhead (new->nexthops); node; nextnode (node)) {
+      nexthop = (struct isis_nexthop *) getdata (node);
+      if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex) == 0)
+        return 0;
+    }
+  
+    for (node = listhead (old->nexthops); node; nextnode (node)) {
+      nexthop = (struct isis_nexthop *) getdata (node);
+      if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex) == 0)
+        return 0;
+    }
+  }
+#ifdef HAVE_IPV6
+  else if (family == AF_INET6) {
+    for (node = listhead (new->nexthops6); node; nextnode (node)) {
+      nexthop6 = (struct isis_nexthop6 *) getdata (node);
+      if (nexthop6lookup (old->nexthops6, &nexthop6->ip6, 
+                          nexthop6->ifindex) == 0)
+        return 0;
+    }
+  
+    for (node = listhead (old->nexthops6); node; nextnode (node)) {
+      nexthop6 = (struct isis_nexthop6 *) getdata (node);
+      if (nexthop6lookup (new->nexthops6, &nexthop6->ip6, 
+                          nexthop6->ifindex) == 0)
+        return 0;
+    }
+  }
+#endif /* HAVE_IPV6 */
+
+  return 1;
+}
+
+
+void
+isis_nexthops_merge (struct list *new, struct list *old)
+{
+  struct listnode *node;
+  struct isis_nexthop *nexthop;
+
+  for (node = listhead (new); node; nextnode (node)) {
+    nexthop = (struct isis_nexthop *) getdata (node);
+    if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex))
+      continue;
+    listnode_add (old, nexthop);
+    nexthop->lock++;
+  }
+}
+
+
+#ifdef HAVE_IPV6
+void
+isis_nexthops6_merge (struct list *new, struct list *old)
+{
+  struct listnode *node;
+  struct isis_nexthop6 *nexthop6;
+
+  for (node = listhead (new); node; nextnode (node)) {
+    nexthop6 = (struct isis_nexthop6 *) getdata (node);
+    if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex))
+      continue;
+    listnode_add (old, nexthop6);
+    nexthop6->lock++;
+  }
+}
+#endif /* HAVE_IPV6 */
+
+void
+isis_route_info_merge (struct isis_route_info *new, 
+                       struct isis_route_info *old, u_char family)
+{
+  
+  if (family == AF_INET) 
+    isis_nexthops_merge (new->nexthops, old->nexthops);
+#ifdef HAVE_IPV6
+  else if (family == AF_INET6) 
+    isis_nexthops6_merge (new->nexthops6, old->nexthops6);
+#endif /* HAVE_IPV6 */
+    
+  return;
+}
+
+
+int
+isis_route_info_prefer_new (struct isis_route_info *new, 
+                            struct isis_route_info *old)
+{
+  
+  if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE))
+    return 1;
+
+  if (new->cost < old->cost)
+    return 1;
+  
+  return 0;
+}
+
+
+struct isis_route_info *
+isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
+                   struct list *adjacencies, struct isis_area *area)
+{
+  struct route_node *route_node;
+  struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
+  u_char buff[BUFSIZ];
+  u_char family;
+  
+  family = prefix->family;
+  /* for debugs */
+  prefix2str (prefix, buff, BUFSIZ);
+  
+  rinfo_new = isis_route_info_new (cost, depth, family, adjacencies);
+  if (!rinfo_new) {
+    zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",
+	      area->area_tag);
+    return NULL;
+  }
+  
+  if (family == AF_INET)
+    route_node = route_node_get (area->route_table, prefix);  
+#ifdef HAVE_IPV6
+  else if (family == AF_INET6)
+    route_node = route_node_get (area->route_table6, prefix);  
+#endif /* HAVE_IPV6 */
+  else 
+    return NULL;
+  rinfo_old = route_node->info;  
+  if (!rinfo_old) {
+    if (isis->debugs & DEBUG_RTE_EVENTS)
+      zlog_info ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
+    SET_FLAG(rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE);
+    route_node->info = rinfo_new;
+    return rinfo_new;
+  }
+  
+  if (isis->debugs & DEBUG_RTE_EVENTS)
+    zlog_info ("ISIS-Rte (%s) route already exists: %s", area->area_tag, buff);
+  
+  if (isis_route_info_same (rinfo_new, rinfo_old, family)) {
+    if (isis->debugs & DEBUG_RTE_EVENTS)
+      zlog_info ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, buff);
+    isis_route_info_delete (rinfo_new);
+    route_info = rinfo_old;
+  } else if (isis_route_info_same_attrib (rinfo_new, rinfo_old)) {
+    /* merge the nexthop lists */
+    if (isis->debugs & DEBUG_RTE_EVENTS)
+        zlog_info ("ISIS-Rte (%s) route changed (same attribs): %s", 
+                   area->area_tag, buff);
+#ifdef EXTREME_DEBUG
+    zlog_info ("Old nexthops");
+    nexthops6_print (rinfo_old->nexthops6);
+    zlog_info ("New nexthops");
+    nexthops6_print (rinfo_new->nexthops6);
+#endif /* EXTREME_DEBUG */
+    isis_route_info_merge (rinfo_new, rinfo_old, family);
+    isis_route_info_delete (rinfo_new);
+    route_info = rinfo_old;
+  } else {
+    if (isis_route_info_prefer_new (rinfo_new, rinfo_old)) {
+      if (isis->debugs & DEBUG_RTE_EVENTS)
+        zlog_info ("ISIS-Rte (%s) route changed: %s", area->area_tag, buff);
+      isis_route_info_delete (rinfo_old);
+      route_info = rinfo_new;
+    } else {
+      if (isis->debugs & DEBUG_RTE_EVENTS)
+        zlog_info ("ISIS-Rte (%s) route rejected: %s", area->area_tag, buff);
+      isis_route_info_delete (rinfo_new);
+      route_info = rinfo_old;
+    }
+  }
+  
+  SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
+  route_node->info = route_info;
+  
+  return route_info;
+}
+
+void
+isis_route_delete (struct prefix *prefix, struct route_table *table)
+{
+  struct route_node *rode;
+  struct isis_route_info *rinfo;
+  char buff[BUFSIZ];
+
+  /* for log */
+  prefix2str (prefix, buff, BUFSIZ);
+
+
+  rode = route_node_get (table, prefix);
+  rinfo = rode->info;
+
+  if (rinfo == NULL) {
+    if (isis->debugs & DEBUG_RTE_EVENTS)
+      zlog_info ("ISIS-Rte: tried to delete non-existant route %s", buff);
+    return;
+  }
+
+  if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC)) {
+    UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
+    if (isis->debugs & DEBUG_RTE_EVENTS)
+      zlog_info ("ISIS-Rte: route delete  %s", buff);
+    isis_zebra_route_update (prefix, rinfo);
+  }
+  isis_route_info_delete (rinfo);
+  rode->info = NULL;
+  
+  return;
+}
+
+int
+isis_route_validate (struct thread *thread)
+{
+  struct isis_area *area;
+  struct route_table *table;
+  struct route_node *rode;
+  struct isis_route_info *rinfo;
+  u_char buff[BUFSIZ];
+#ifdef HAVE_IPV6
+  int v6done = 0;
+#endif
+  area = THREAD_ARG (thread);
+  table = area->route_table;
+#ifdef HAVE_IPV6
+ again:
+#endif
+  for (rode = route_top (table); rode; rode = route_next (rode)) {
+    if (rode->info == NULL)
+      continue;
+    rinfo = rode->info;
+    
+    if (isis->debugs & DEBUG_RTE_EVENTS) {
+      prefix2str (&rode->p, buff, BUFSIZ);
+      zlog_info ("ISIS-Rte (%s): route validate: %s %s %s",
+                 area->area_tag,
+                 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?
+                  "sync'ed": "nosync"),
+                 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
+                  "active": "inactive"), buff);
+    }
+    
+    isis_zebra_route_update (&rode->p, rinfo);
+    if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
+      isis_route_delete (&rode->p, area->route_table);
+  }
+#ifdef HAVE_IPV6
+  if (v6done)
+    return ISIS_OK;
+  table = area->route_table6;
+  v6done = 1;
+  goto again;
+#endif
+
+  return ISIS_OK;
+}
diff --git a/isisd/isis_route.h b/isisd/isis_route.h
new file mode 100644
index 0000000..7137948
--- /dev/null
+++ b/isisd/isis_route.h
@@ -0,0 +1,61 @@
+/*
+ * IS-IS Rout(e)ing protocol               - isis_route.h
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ *                                         based on ../ospf6d/ospf6_route.[ch]
+ *                                         by Yasuhiro Ohara
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef _ZEBRA_ISIS_ROUTE_H
+#define _ZEBRA_ISIS_ROUTE_H
+
+#ifdef HAVE_IPV6
+struct isis_nexthop6 {
+  unsigned int ifindex;
+  struct in6_addr ip6;
+  unsigned int lock;
+};
+#endif /* HAVE_IPV6 */
+
+struct isis_nexthop {
+  unsigned int ifindex;
+  struct in_addr ip;
+  unsigned int lock;
+};
+
+struct isis_route_info {
+#define ISIS_ROUTE_FLAG_ZEBRA_SYNC 0x01
+#define ISIS_ROUTE_FLAG_ACTIVE     0x02
+  u_char flag; 
+  u_int32_t cost;
+  u_int32_t depth;
+  struct list *nexthops;
+#ifdef HAVE_IPV6
+  struct list *nexthops6;
+#endif /* HAVE_IPV6 */
+};
+
+struct isis_route_info *isis_route_create (struct prefix *prefix, 
+                                           u_int32_t cost, u_int32_t depth,
+                                           struct list *adjacencies,
+                                           struct isis_area *area);
+
+int isis_route_validate (struct thread *thread);
+
+#endif /* _ZEBRA_ISIS_ROUTE_H */
diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c
new file mode 100644
index 0000000..4df983d
--- /dev/null
+++ b/isisd/isis_routemap.c
@@ -0,0 +1,100 @@
+/*
+ * IS-IS Rout(e)ing protocol               - isis_routemap.c
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "thread.h"
+#include "linklist.h"
+#include "vty.h"
+#include "log.h"
+#include "memory.h"
+#include "prefix.h"
+#include "hash.h"
+#include "if.h"
+#include "table.h"
+#include "routemap.h"
+
+#include "isis_constants.h"
+#include "isis_common.h"
+#include "dict.h"
+#include "isisd.h"
+#include "isis_misc.h"
+#include "isis_adjacency.h"
+#include "isis_circuit.h"
+#include "isis_tlv.h"
+#include "isis_pdu.h"
+#include "isis_lsp.h"
+#include "isis_spf.h"
+#include "isis_route.h"
+#include "isis_zebra.h"
+
+extern struct isis *isis;
+
+void
+isis_route_map_upd()
+{
+  int i = 0;
+  
+  if (!isis)
+    return;
+  
+  for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+    if (isis->rmap[i].name)
+      isis->rmap[i].map =  isis->rmap[i].map = 
+        route_map_lookup_by_name (isis->rmap[i].name);
+    else
+      isis->rmap[i].map = NULL;
+  }
+  /* FIXME: do the address family sub-mode AF_INET6 here ? */
+}
+
+void
+isis_route_map_event(route_map_event_t event, char *name)
+{
+  int type;
+
+  if (!isis)
+    return;
+
+  for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+    if (isis->rmap[type].name &&  isis->rmap[type].map && 
+        !strcmp (isis->rmap[type].name, name)) {
+      isis_distribute_list_update (type);
+    }
+  }  
+}
+
+
+void
+isis_route_map_init (void)
+{
+  route_map_init ();
+  route_map_init_vty ();
+  
+  route_map_add_hook (isis_route_map_upd);
+  route_map_delete_hook (isis_route_map_upd);
+  route_map_event_hook (isis_route_map_event);
+
+}
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
new file mode 100644
index 0000000..d694981
--- /dev/null
+++ b/isisd/isis_spf.c
@@ -0,0 +1,1293 @@
+/*
+ * IS-IS Rout(e)ing protocol                  - isis_spf.c
+ *                                              The SPT algorithm
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "thread.h"
+#include "linklist.h"
+#include "vty.h"
+#include "log.h"
+#include "command.h"
+#include "memory.h"
+#include "prefix.h"
+#include "hash.h"
+#include "if.h"
+#include "table.h"
+
+#include "isis_constants.h"
+#include "isis_common.h"
+#include "dict.h"
+#include "isisd.h"
+#include "isis_misc.h"
+#include "isis_adjacency.h"
+#include "isis_circuit.h"
+#include "isis_tlv.h"
+#include "isis_pdu.h"
+#include "isis_lsp.h"
+#include "isis_dynhn.h"
+#include "isis_spf.h"
+#include "isis_route.h"
+#include "isis_csm.h"
+
+extern struct isis *isis;
+extern struct thread_master *master;
+extern struct host host;
+
+int isis_run_spf_l1 (struct thread *thread);
+int isis_run_spf_l2 (struct thread *thread);
+
+/* performace issue ???? */
+void
+union_adjlist( struct list *target, struct list *source )
+{
+  struct isis_adjacency *adj, *adj2;
+  struct listnode *node, *node2;
+  
+  zlog_info ("Union adjlist!");
+  for (node = listhead (source); node; nextnode (node)) {
+    adj = getdata (node);
+    
+    /* lookup adjacency in the source list */
+    for (node2 = listhead (target); node2; nextnode (node2)) {
+      adj2 = getdata(node2);
+      if (adj == adj2) break;
+    }
+    
+    if (!node2) listnode_add (target, adj);
+  }
+}
+
+
+/* 7.2.7 */
+void      
+remove_excess_adjs (struct list *adjs)
+{
+  struct listnode *node, *excess = NULL;
+  struct isis_adjacency *adj, *candidate = NULL;
+  int comp;
+
+  for (node = listhead (adjs); node; nextnode (node)) {
+    if (excess == NULL) 
+      excess = node;
+    candidate = getdata (excess);
+    adj = getdata (node);
+    if (candidate->sys_type < adj->sys_type) {
+      excess = node;
+      candidate = adj;
+      continue;
+    } 
+    if (candidate->sys_type > adj->sys_type)
+      continue;
+    
+    comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN);
+    if (comp > 0) {
+      excess = node;
+      candidate = adj;
+      continue;
+    }
+    if (comp < 0)
+      continue;
+    
+    if (candidate->circuit->circuit_id > adj->circuit->circuit_id) {
+      excess = node;
+      candidate = adj;
+      continue;
+    }
+
+    if (candidate->circuit->circuit_id < adj->circuit->circuit_id)
+      continue;
+    
+    comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN);
+    if (comp > 0) {
+      excess = node;
+      candidate = adj;
+      continue;
+    }
+  }
+  
+  list_delete_node (adjs, excess);
+
+  return;
+}
+
+const char *
+vtype2string (enum vertextype vtype)
+{
+  switch (vtype) {
+  case  VTYPE_PSEUDO_IS:
+    return "pseudo_IS";
+    break;
+  case VTYPE_NONPSEUDO_IS:
+    return "IS";
+    break;
+  case VTYPE_ES:
+    return "ES";
+    break;
+  case VTYPE_IPREACH_INTERNAL:
+    return "IP internal";
+    break;
+  case VTYPE_IPREACH_EXTERNAL:
+    return "IP external";
+    break;
+#ifdef HAVE_IPV6
+  case VTYPE_IP6REACH_INTERNAL:
+    return "IP6 internal";
+    break;
+  case VTYPE_IP6REACH_EXTERNAL:
+    return "IP6 external";
+    break;
+#endif /* HAVE_IPV6 */ 
+  default:
+    return "UNKNOWN";
+  }
+  return NULL; /* Not reached */
+}
+
+char *
+vid2string (struct isis_vertex *vertex, u_char *buff)
+{
+  switch (vertex->type) {
+  case  VTYPE_PSEUDO_IS:
+    return rawlspid_print (vertex->N.id);
+    break;
+  case VTYPE_NONPSEUDO_IS:
+  case VTYPE_ES:
+    return sysid_print (vertex->N.id);
+    break;
+  case VTYPE_IPREACH_INTERNAL:
+  case VTYPE_IPREACH_EXTERNAL:
+#ifdef HAVE_IPV6
+  case VTYPE_IP6REACH_INTERNAL:
+  case VTYPE_IP6REACH_EXTERNAL:
+#endif /* HAVE_IPV6 */ 
+    prefix2str ((struct prefix *)&vertex->N.prefix, buff, BUFSIZ);
+    break;
+  default:
+    return "UNKNOWN";
+  }
+  
+  return buff;
+}
+
+struct isis_spftree *
+isis_spftree_new ()
+{
+  struct isis_spftree *tree;
+
+  tree = XMALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree));
+  if (tree == NULL) {
+    zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!");
+    return NULL;
+  } 
+  memset (tree, 0, sizeof (struct isis_spftree));
+
+  tree->tents = list_new ();
+  tree->paths  = list_new ();
+  return tree;
+}
+
+void
+isis_vertex_del (struct isis_vertex *vertex)
+{
+  
+  list_delete (vertex->Adj_N);
+
+  XFREE (MTYPE_ISIS_VERTEX, vertex);
+  
+  return;
+}
+
+void
+isis_spftree_del (struct isis_spftree *spftree)
+{
+
+  spftree->tents->del = (void *)isis_vertex_del;
+  list_delete (spftree->tents);
+  
+  spftree->paths->del = (void *)isis_vertex_del;
+  list_delete (spftree->paths);
+
+  XFREE (MTYPE_ISIS_SPFTREE, spftree);
+
+  return;
+}
+
+void 
+spftree_area_init (struct isis_area *area)
+{
+
+  if ((area->is_type & IS_LEVEL_1) && area->spftree[0] == NULL) {
+    area->spftree[0] = isis_spftree_new ();
+#ifdef HAVE_IPV6
+    area->spftree6[0] = isis_spftree_new ();
+#endif
+
+    /*    thread_add_timer (master, isis_run_spf_l1, area, 
+          isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
+  }
+  
+  if ((area->is_type & IS_LEVEL_2) && area->spftree[1] == NULL) {
+    area->spftree[1] = isis_spftree_new ();
+#ifdef HAVE_IPV6
+    area->spftree6[1] = isis_spftree_new ();
+#endif
+    /*    thread_add_timer (master, isis_run_spf_l2, area, 
+          isis_jitter (PERIODIC_SPF_INTERVAL, 10)); */
+  }
+
+  return;
+}
+
+struct isis_vertex *
+isis_vertex_new (void *id, enum vertextype vtype)
+{
+  struct isis_vertex *vertex;
+
+  vertex = XMALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex));
+  if (vertex == NULL) {
+    zlog_err ("isis_vertex_new Out of memory!");
+    return NULL;
+  } 
+  
+  memset (vertex, 0, sizeof (struct isis_vertex));
+  vertex->type = vtype;
+  switch (vtype) {
+  case VTYPE_ES:
+  case VTYPE_NONPSEUDO_IS:
+    memcpy (vertex->N.id, (u_char *)id, ISIS_SYS_ID_LEN);
+    break;
+  case VTYPE_PSEUDO_IS:
+    memcpy (vertex->N.id, (u_char *)id, ISIS_SYS_ID_LEN + 1);
+    break;
+  case VTYPE_IPREACH_INTERNAL:
+  case VTYPE_IPREACH_EXTERNAL:
+#ifdef HAVE_IPV6
+  case VTYPE_IP6REACH_INTERNAL:
+  case VTYPE_IP6REACH_EXTERNAL:
+#endif /* HAVE_IPV6 */ 
+    memcpy (&vertex->N.prefix, (struct prefix *)id, 
+            sizeof (struct prefix));
+    break;
+  default:
+    zlog_err ("WTF!");
+  }
+
+  vertex->Adj_N = list_new ();
+  
+  return vertex;
+}
+
+/*
+ * Add this IS to the root of SPT
+ */
+void
+isis_spf_add_self (struct isis_spftree *spftree, struct isis_area *area,
+                   int level)
+{
+  struct isis_vertex *vertex;
+  struct isis_lsp *lsp;
+  u_char lspid[ISIS_SYS_ID_LEN + 2];
+#ifdef EXTREME_DEBUG
+  u_char buff[BUFSIZ];
+#endif /* EXTREME_DEBUG */
+  memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN);
+  LSP_PSEUDO_ID(lspid) = 0;
+  LSP_FRAGMENT(lspid) = 0;
+  
+  lsp = lsp_search (lspid, area->lspdb[level - 1]);
+  
+  if (lsp == NULL)
+    zlog_warn ("ISIS-Spf: could not find own l%d LSP!", level);
+  
+  vertex = isis_vertex_new (isis->sysid, VTYPE_NONPSEUDO_IS);
+  vertex->lsp = lsp;
+
+  listnode_add (spftree->paths, vertex);
+
+#ifdef EXTREME_DEBUG
+  zlog_info ("ISIS-Spf: added this IS  %s %s depth %d dist %d to PATHS",
+             vtype2string(vertex->type), vid2string(vertex, buff),
+             vertex->depth, vertex->d_N);
+#endif /* EXTREME_DEBUG */
+
+  return;
+}
+
+struct isis_vertex *
+isis_find_vertex (struct list *list, void *id, enum vertextype vtype) 
+{
+  struct listnode *node;
+  struct isis_vertex *vertex;
+  struct prefix *p1, *p2;
+
+  for (node = listhead (list); node; nextnode (node)) {
+    vertex = getdata (node);
+    if (vertex->type != vtype)
+      continue;
+    switch (vtype) {
+    case VTYPE_ES:
+    case VTYPE_NONPSEUDO_IS:
+      if (memcmp ((u_char *)id, vertex->N.id, ISIS_SYS_ID_LEN) == 0)
+        return vertex;
+      break;
+    case VTYPE_PSEUDO_IS:
+      if (memcmp ((u_char *)id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0)
+        return vertex;
+      break;
+    case VTYPE_IPREACH_INTERNAL:
+    case VTYPE_IPREACH_EXTERNAL:
+#ifdef HAVE_IPV6
+    case VTYPE_IP6REACH_INTERNAL:
+    case VTYPE_IP6REACH_EXTERNAL:
+#endif /* HAVE_IPV6 */
+      p1 = (struct prefix *)id;
+      p2 = (struct prefix *)&vertex->N.id;
+      if (p1->family == p2->family && p1->prefixlen == p2->prefixlen &&
+          memcmp (&p1->u.prefix, &p2->u.prefix, PSIZE (p1->prefixlen)) == 0)
+        return vertex;
+      break;
+    }
+  }
+
+  return NULL;
+}
+
+
+
+/*
+ * Add a vertex to TENT sorted by cost and by vertextype on tie break situation
+ */
+struct isis_vertex *
+isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, 
+                   void *id, struct isis_adjacency *adj, u_int16_t cost,
+                   int depth, int family)
+{
+  struct isis_vertex *vertex, *v;
+  struct listnode *node;
+#ifdef EXTREME_DEBUG 
+  u_char buff[BUFSIZ];
+#endif
+
+  vertex = isis_vertex_new (id, vtype);
+  vertex->d_N = cost;
+  vertex->depth = depth;
+  
+  if (adj)
+    listnode_add (vertex->Adj_N, adj);
+#ifdef EXTREME_DEBUG 
+  zlog_info ("ISIS-Spf: add to TENT  %s %s depth %d dist %d",
+             vtype2string(vertex->type), vid2string(vertex, buff),
+             vertex->depth, vertex->d_N);
+#endif /* EXTREME_DEBUG */
+  listnode_add (spftree->tents, vertex); 
+  if (list_isempty (spftree->tents)) {
+    listnode_add (spftree->tents, vertex); 
+    return vertex;
+  }
+  for (node = listhead (spftree->tents); node; nextnode (node)) {
+    v = getdata (node);
+    if (v->d_N > vertex->d_N) {
+      list_add_node_prev (spftree->tents, node, vertex);
+      break;
+    } else if (v->d_N == vertex->d_N) {
+      /*  Tie break, add according to type */
+      while (v  && v->d_N == vertex->d_N && v->type > vertex->type) {
+        if (v->type > vertex->type) {
+          break;
+        }
+        nextnode (node);
+        (node) ? (v = getdata (node)) : (v = NULL);
+      }
+      list_add_node_prev (spftree->tents, node, vertex);
+      break; 
+    } else  if (node->next == NULL) {
+      list_add_node_next (spftree->tents, node, vertex);
+      break;
+    }
+  }
+  return vertex;
+}
+
+struct isis_vertex *
+isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype, 
+                    void *id, struct isis_adjacency *adj, u_int16_t cost,
+                    int family)
+{
+  struct isis_vertex *vertex;
+ 
+  vertex = isis_find_vertex (spftree->tents, id, vtype); 
+  
+  if (vertex) {
+    /* C.2.5   c) */
+    if (vertex->d_N == cost) {
+      if (adj)
+        listnode_add (vertex->Adj_N, adj);
+      /*       d) */
+      if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
+	remove_excess_adjs (vertex->Adj_N);
+    }
+    /*         f) */
+    else if (vertex->d_N > cost) {
+      listnode_delete (spftree->tents, vertex);
+      goto add2tent;
+    }
+    /*       e) do nothing */
+    return vertex;
+  }
+
+ add2tent:
+  return isis_spf_add2tent (spftree, vtype, id, adj, cost, 1, family);
+}
+
+void
+process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id, 
+           u_int16_t dist, u_int16_t depth, struct isis_adjacency *adj,  
+           int family) 
+{
+  struct isis_vertex *vertex;
+#ifdef EXTREME_DEBUG
+  u_char buff[255];
+#endif
+
+  /* C.2.6 b)    */
+  if (dist > MAX_PATH_METRIC)
+    return;
+  /*       c)    */
+  vertex = isis_find_vertex (spftree->paths, id, vtype);
+  if (vertex) {
+#ifdef EXTREME_DEBUG
+    zlog_info ("ISIS-Spf: process_N  %s %s dist %d already found from PATH",
+	       vtype2string(vtype), vid2string(vertex, buff), dist);
+#endif /* EXTREME_DEBUG */
+    assert (dist >= vertex->d_N);
+    return;
+  }
+
+  vertex = isis_find_vertex (spftree->tents, id, vtype);
+  /*       d)    */ 
+  if (vertex) {
+    /*        1) */
+#ifdef EXTREME_DEBUG
+    zlog_info ("ISIS-Spf: process_N  %s %s dist %d",
+	       vtype2string(vtype), vid2string(vertex, buff), dist);
+#endif /* EXTREME_DEBUG */
+    if (vertex->d_N == dist) {
+      if (adj)
+        listnode_add (vertex->Adj_N, adj);
+      /*      2) */
+      if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
+        remove_excess_adjs (vertex->Adj_N);
+      /*      3) */
+      return;
+    } else if (vertex->d_N < dist) {
+      return;
+      /*      4) */
+    } else {
+      listnode_delete (spftree->tents, vertex);
+    }
+  }
+  
+  isis_spf_add2tent (spftree, vtype, id, adj, dist, depth, family);
+  return;
+}
+
+/*
+ * C.2.6 Step 1
+ */
+int
+isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, 
+                      uint16_t cost, uint16_t depth, int family)
+{
+  struct listnode *node, *fragnode = NULL;
+  u_int16_t dist;
+  struct is_neigh *is_neigh;
+  struct ipv4_reachability *ipreach;
+  enum vertextype vtype;
+  struct prefix prefix;
+#ifdef HAVE_IPV6
+  struct ipv6_reachability *ip6reach;
+#endif /* HAVE_IPV6 */
+  
+
+  if (!lsp->adj)
+    return ISIS_WARNING;
+  if (lsp->tlv_data.nlpids == NULL || 
+      !speaks (lsp->tlv_data.nlpids, family))
+    return ISIS_OK;
+
+ lspfragloop:
+  if (lsp->lsp_header->seq_num == 0) {
+    zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num"
+	       " - do not process");
+    return ISIS_WARNING;
+  }
+
+  if (!ISIS_MASK_LSP_OL_BIT(lsp->lsp_header->lsp_bits)) {
+    if (lsp->tlv_data.is_neighs) {
+      for (node = listhead (lsp->tlv_data.is_neighs); node; nextnode (node)) {
+        is_neigh = getdata (node);
+        /* C.2.6 a) */       
+	/* Two way connectivity */
+	if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
+	  continue;
+        dist = cost + is_neigh->metrics.metric_default;
+        vtype = LSP_PSEUDO_ID(is_neigh->neigh_id) ? VTYPE_PSEUDO_IS 
+                                                  : VTYPE_NONPSEUDO_IS;
+        process_N (spftree, vtype, (void *)is_neigh->neigh_id, dist, depth+1, 
+                   lsp->adj, family);
+      }
+    }
+    if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) {
+      prefix.family = AF_INET;
+      for (node = listhead (lsp->tlv_data.ipv4_int_reachs); node; 
+           nextnode (node)) {
+        ipreach = getdata (node);
+        dist = cost + ipreach->metrics.metric_default;
+        vtype = VTYPE_IPREACH_INTERNAL;
+        prefix.u.prefix4 = ipreach->prefix;
+        prefix.prefixlen = ip_masklen (ipreach->mask);
+        process_N (spftree, vtype, (void *)&prefix, dist, depth + 1,
+                   lsp->adj, family);
+      }
+    }
+    
+    if (family == AF_INET && lsp->tlv_data.ipv4_ext_reachs) {
+      prefix.family = AF_INET;
+      for (node = listhead (lsp->tlv_data.ipv4_ext_reachs); node; 
+           nextnode (node)) {
+        ipreach = getdata (node);
+        dist = cost + ipreach->metrics.metric_default;
+        vtype = VTYPE_IPREACH_EXTERNAL;
+        prefix.u.prefix4 = ipreach->prefix;
+        prefix.prefixlen = ip_masklen (ipreach->mask);
+        process_N (spftree, vtype, (void *)&prefix, dist, depth + 1,
+                   lsp->adj, family);
+      }
+    }
+#ifdef HAVE_IPV6
+    if (family == AF_INET6 && lsp->tlv_data.ipv6_reachs) {
+      prefix.family = AF_INET6;
+      for (node = listhead (lsp->tlv_data.ipv6_reachs); node; 
+           nextnode (node)) {
+        ip6reach = getdata (node);
+        dist = cost + ip6reach->metric;
+        vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ? 
+          VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL;
+        prefix.prefixlen = ip6reach->prefix_len;
+        memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix, 
+                PSIZE(ip6reach->prefix_len));
+        process_N (spftree, vtype, (void *)&prefix, dist, depth + 1,
+                   lsp->adj, family);
+      }
+    }
+#endif /* HAVE_IPV6 */
+  }
+  
+  if (fragnode == NULL)
+    fragnode = listhead (lsp->lspu.frags);
+  else 
+    fragnode = nextnode (fragnode);
+
+  if (fragnode) {
+    lsp = getdata (fragnode);
+    goto lspfragloop;
+  }
+  
+  return ISIS_OK;
+}
+
+int
+isis_spf_process_pseudo_lsp (struct isis_spftree *spftree,struct isis_lsp *lsp,
+                             uint16_t cost, uint16_t depth, int family)
+{
+  struct listnode *node, *fragnode = NULL;
+  struct is_neigh *is_neigh;
+  enum vertextype vtype;
+  
+ pseudofragloop:
+  
+  if (lsp->lsp_header->seq_num == 0) {
+    zlog_warn ("isis_spf_process_pseudo_lsp(): lsp with 0 seq_num"
+	       " - do not process");
+    return ISIS_WARNING;
+  }
+    
+  for (node = (lsp->tlv_data.is_neighs ? 
+               listhead (lsp->tlv_data.is_neighs) : NULL); 
+       node; nextnode (node)) {
+    is_neigh = getdata (node);
+    vtype = LSP_PSEUDO_ID(is_neigh->neigh_id) ? VTYPE_PSEUDO_IS 
+                                              : VTYPE_NONPSEUDO_IS;
+    /* Two way connectivity */
+    if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN))
+      continue;
+    if (isis_find_vertex (spftree->tents, (void *)is_neigh->neigh_id, vtype) 
+	== NULL &&
+        isis_find_vertex (spftree->paths, (void *)is_neigh->neigh_id, vtype)
+        == NULL) {
+        /* C.2.5 i) */
+        isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj, 
+                           cost, depth, family);
+    }
+  }
+  
+  if (fragnode == NULL)
+    fragnode = listhead (lsp->lspu.frags);
+  else 
+    fragnode = nextnode (fragnode);
+
+  if (fragnode) {
+    lsp = getdata (fragnode);
+    goto pseudofragloop;
+  }
+
+  
+  return ISIS_OK;
+}
+      
+int
+isis_spf_preload_tent (struct isis_spftree *spftree, 
+                       struct isis_area *area, int level, int family)
+{
+  struct isis_vertex *vertex;
+  struct isis_circuit *circuit;
+  struct listnode *cnode, *anode, *ipnode;
+  struct isis_adjacency *adj;
+  struct isis_lsp *lsp;
+  struct list *adj_list;
+  struct list *adjdb;
+  struct prefix_ipv4 *ipv4;
+  struct prefix prefix;
+  int retval = ISIS_OK;
+  u_char lsp_id[ISIS_SYS_ID_LEN + 2];
+#ifdef HAVE_IPV6
+  struct prefix_ipv6 *ipv6;
+#endif /* HAVE_IPV6 */
+  
+  for (cnode = listhead (area->circuit_list); cnode; nextnode (cnode)) {
+    circuit = getdata (cnode);
+    if (circuit->state != C_STATE_UP)
+      continue;
+    if (!(circuit->circuit_is_type & level))
+      continue;
+    if (family == AF_INET && !circuit->ip_router)
+      continue;
+#ifdef HAVE_IPV6
+    if (family == AF_INET6 && !circuit->ipv6_router)
+      continue;
+#endif /* HAVE_IPV6 */
+    /* 
+     * Add IP(v6) addresses of this circuit
+     */
+    if (family == AF_INET) {
+      prefix.family = AF_INET;
+      for (ipnode = (circuit->ip_addrs ? listhead (circuit->ip_addrs) : NULL); 
+           ipnode; nextnode (ipnode)) {
+        ipv4 = getdata (ipnode);
+        prefix.u.prefix4 = ipv4->prefix;
+        prefix.prefixlen = ipv4->prefixlen;
+        isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix, NULL, 0,
+                            family);
+      }
+    }
+#ifdef HAVE_IPV6
+    if (family == AF_INET6) {
+      prefix.family = AF_INET6;
+      for (ipnode = (circuit->ipv6_non_link ? listhead 
+                     (circuit->ipv6_non_link) : NULL); ipnode; 
+           nextnode (ipnode)) {
+        ipv6 = getdata (ipnode);
+        prefix.prefixlen = ipv6->prefixlen;
+        prefix.u.prefix6 = ipv6->prefix;
+        isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL, 
+                            &prefix, NULL, 0, family);
+      }
+    }
+#endif /* HAVE_IPV6 */
+    if (circuit->circ_type == CIRCUIT_T_BROADCAST ) {
+      /*
+       * Add the adjacencies
+       */
+      adj_list = list_new ();
+      adjdb = circuit->u.bc.adjdb[level - 1];
+      isis_adj_build_up_list (adjdb, adj_list);
+      if (listcount (adj_list) == 0) {
+        list_delete (adj_list);
+        zlog_warn ("ISIS-Spf: no L%d adjacencies on circuit %s",
+                   level, circuit->interface->name);
+	continue;
+      }
+      anode = listhead (adj_list);
+      while (anode) {
+        adj = getdata (anode);
+        if (!speaks (&adj->nlpids, family))
+          continue;
+        switch (adj->sys_type) {
+        case ISIS_SYSTYPE_ES:
+          isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, 
+                              circuit->metrics[level - 1].metric_default,
+                              family);
+        break;
+        case ISIS_SYSTYPE_IS:
+        case ISIS_SYSTYPE_L1_IS:
+        case ISIS_SYSTYPE_L2_IS:
+          vertex = 
+            isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, 
+                                adj->sysid, adj,
+                                circuit->metrics[level - 1].metric_default,
+                                family);
+          memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
+          LSP_PSEUDO_ID(lsp_id) = 0;
+          LSP_FRAGMENT(lsp_id) = 0;
+          lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
+          if (!lsp)
+            zlog_warn ("No lsp found for IS adjacency");
+          /*          else {
+	    isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family);
+            } */
+          break;
+        case ISIS_SYSTYPE_UNKNOWN:
+        default:
+          zlog_warn ("isis_spf_preload_tent unknow adj type");
+        }
+        anode = nextnode (anode); 
+      }
+      list_delete (adj_list);
+      /*
+       * Add the pseudonode 
+       */
+      if (level == 1)
+        memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1);
+      else
+        memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1);
+      lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
+      adj = isis_adj_lookup (lsp_id,  adjdb);
+      /* if no adj, we are the dis or error */
+      if (!adj && !circuit->u.bc.is_dr[level - 1]) {
+        zlog_warn ("ISIS-Spf: No adjacency found for DR");
+      }
+      if (lsp ==  NULL || lsp->lsp_header->rem_lifetime == 0) {
+        zlog_warn ("ISIS-Spf: No lsp found for DR");
+      } else {
+        isis_spf_process_pseudo_lsp 
+          (spftree, lsp, circuit->metrics[level - 1].metric_default, 0,
+           family);
+        
+      }
+    } else if (circuit->circ_type == CIRCUIT_T_P2P ) {
+      adj = circuit->u.p2p.neighbor;
+      if (!adj)
+	continue;
+      switch (adj->sys_type) {
+      case ISIS_SYSTYPE_ES:
+        isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, 
+                            circuit->metrics[level - 1].metric_default,
+                            family);
+        break;
+      case ISIS_SYSTYPE_IS:
+      case ISIS_SYSTYPE_L1_IS:
+      case ISIS_SYSTYPE_L2_IS:
+        if (speaks (&adj->nlpids, family))
+          isis_spf_add_local (spftree, VTYPE_NONPSEUDO_IS, adj->sysid, adj,
+                              circuit->metrics[level - 1].metric_default,
+                              family);
+        break;
+      case ISIS_SYSTYPE_UNKNOWN:
+      default:
+        zlog_warn ("isis_spf_preload_tent unknow adj type");
+        break;
+      }
+    } else {
+      zlog_warn ("isis_spf_preload_tent unsupported media");
+      retval = ISIS_WARNING;
+    }
+    
+  }
+
+  return retval;
+}
+
+/*
+ * The parent(s) for vertex is set when added to TENT list
+ * now we just put the child pointer(s) in place
+ */
+void
+add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
+              struct isis_area *area)
+{
+
+#ifdef EXTREME_DEBUG
+  u_char buff[BUFSIZ];
+#endif /* EXTREME_DEBUG */
+  listnode_add (spftree->paths, vertex);
+
+#ifdef EXTREME_DEBUG  
+  zlog_info ("ISIS-Spf: added  %s %s depth %d dist %d to PATHS",
+             vtype2string(vertex->type), vid2string(vertex, buff),
+             vertex->depth, vertex->d_N);
+#endif /* EXTREME_DEBUG */  
+  if (vertex->type > VTYPE_ES) {
+    if (listcount(vertex->Adj_N) > 0)
+      isis_route_create ((struct prefix *)&vertex->N.prefix,
+                         vertex->d_N, vertex->depth, vertex->Adj_N, area);
+    else if (isis->debugs & DEBUG_SPF_EVENTS)
+      zlog_info ("ISIS-Spf: no adjacencies do not install route");
+  }
+  
+  return;
+}
+
+
+void
+init_spt (struct isis_spftree *spftree)
+{
+  spftree->tents->del = spftree->paths->del = (void *)isis_vertex_del;
+  list_delete_all_node (spftree->tents);
+  list_delete_all_node (spftree->paths);
+  spftree->tents->del = spftree->paths->del = NULL;
+  
+  return;
+}
+
+int
+isis_run_spf (struct isis_area *area, int level, int family)
+{
+  int retval = ISIS_OK;
+  struct listnode *node;
+  struct isis_vertex *vertex;
+  struct isis_spftree *spftree = NULL; 
+  u_char lsp_id[ISIS_SYS_ID_LEN + 2];
+  struct isis_lsp *lsp;
+  
+  if (family == AF_INET)
+    spftree = area->spftree[level - 1];
+#ifdef HAVE_IPV6
+  else if (family == AF_INET6)
+    spftree = area->spftree6[level - 1];
+#endif
+  
+  assert (spftree);
+
+  /*
+   * C.2.5 Step 0
+   */
+  init_spt (spftree);
+  /*              a) */
+  isis_spf_add_self (spftree, area, level);
+  /*              b) */
+  retval = isis_spf_preload_tent (spftree, area, level, family);
+  
+  /*
+   * C.2.7 Step 2
+   */
+  if (listcount (spftree->tents) == 0) {
+    zlog_warn ("ISIS-Spf: TENT is empty");
+    spftree->lastrun = time (NULL);
+    return retval;
+  }
+
+  while (listcount (spftree->tents) > 0) {
+    node = listhead (spftree->tents);
+    vertex = getdata (node);
+    /* Remove from tent list */
+    list_delete_node (spftree->tents, node);
+    if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
+      continue;
+    add_to_paths (spftree, vertex, area);
+    if (vertex->type == VTYPE_PSEUDO_IS || 
+        vertex->type == VTYPE_NONPSEUDO_IS) {
+      memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
+      LSP_FRAGMENT(lsp_id) = 0;
+      lsp = lsp_search (lsp_id, area->lspdb[level - 1]);
+      if (lsp) {
+	if (LSP_PSEUDO_ID (lsp_id)) {
+          isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N, 
+                                       vertex->depth, family);
+        
+        } else {
+	  isis_spf_process_lsp (spftree, lsp, vertex->d_N, vertex->depth, 
+                                family);
+	}
+      } else {
+        zlog_warn ("ISIS-Spf: No LSP found for %s", rawlspid_print (lsp_id));
+      }
+    }
+  }
+  
+  thread_add_event (master, isis_route_validate, area, 0);
+  spftree->lastrun = time (NULL);
+  spftree->pending = 0;
+  
+  if (level == 1)
+    spftree->t_spf_periodic =  thread_add_timer (master, 
+						 isis_run_spf_l1, area, 
+						 isis_jitter 
+						 (PERIODIC_SPF_INTERVAL, 10));
+  else 
+    spftree->t_spf_periodic =  thread_add_timer (master, 
+						 isis_run_spf_l2, area, 
+						 isis_jitter 
+						 (PERIODIC_SPF_INTERVAL, 10));
+
+  return retval;
+}
+
+int
+isis_run_spf_l1 (struct thread *thread)
+{
+  struct isis_area *area;
+  int retval = ISIS_OK;
+
+  area = THREAD_ARG(thread);
+  assert (area);
+
+  if (!(area->is_type & IS_LEVEL_1)) {
+    if (isis->debugs & DEBUG_SPF_EVENTS) {
+      zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
+    }
+    return ISIS_WARNING;
+  }
+
+  if (isis->debugs & DEBUG_SPF_EVENTS) {
+    zlog_info ("ISIS-Spf (%s) L1 SPF needed, periodic SPF",
+               area->area_tag);
+  }
+  
+  if (area->ip_circuits)
+    retval = isis_run_spf (area, 1, AF_INET);
+#ifdef HAVE_IPV6
+  if (area->ipv6_circuits)
+    retval = isis_run_spf (area, 1, AF_INET6);
+#endif
+  return retval;
+}
+
+int
+isis_run_spf_l2 (struct thread *thread)
+{
+  struct isis_area *area;
+  int retval = ISIS_OK;
+
+  area = THREAD_ARG(thread);
+  assert (area);
+  
+  if (!(area->is_type & IS_LEVEL_2)) {
+    if (isis->debugs & DEBUG_SPF_EVENTS) {
+      zlog_warn ("ISIS-SPF (%s) area does not share level", area->area_tag);
+    }
+    return ISIS_WARNING;
+  }
+  
+  if (isis->debugs & DEBUG_SPF_EVENTS) {
+    zlog_info ("ISIS-Spf (%s) L2 SPF needed, periodic SPF",
+               area->area_tag);
+  }
+
+  if (area->ip_circuits)
+    retval = isis_run_spf (area, 2, AF_INET);
+#ifdef HAVE_IPV6
+  if (area->ipv6_circuits)
+    retval = isis_run_spf (area, 2, AF_INET6);
+#endif
+
+  return retval;
+}
+
+int 
+isis_spf_schedule (struct isis_area *area, int level)
+{
+  int retval = ISIS_OK;
+  struct isis_spftree *spftree = area->spftree[level - 1];
+  time_t diff, now = time (NULL);
+
+  if (spftree->pending)
+    return retval;
+
+  diff = now - spftree->lastrun; 
+
+  /* FIXME: let's wait a minute before doing the SPF */
+  if (now - isis->uptime < 60 || isis->uptime == 0) {
+    if (level == 1)
+      thread_add_timer (master, isis_run_spf_l1, area, 
+                        60);
+    else
+      thread_add_timer (master, isis_run_spf_l2, area, 
+                        60);
+
+    spftree->pending = 1;
+    return retval;
+  }
+  if (spftree->t_spf_periodic)
+    thread_cancel (spftree->t_spf_periodic);
+
+  if (diff < MINIMUM_SPF_INTERVAL) {
+    if (level == 1)
+      thread_add_timer (master, isis_run_spf_l1, area, 
+                        MINIMUM_SPF_INTERVAL - diff);
+    else
+      thread_add_timer (master, isis_run_spf_l2, area, 
+                        MINIMUM_SPF_INTERVAL - diff);
+
+    spftree->pending = 1;
+  } else {
+    spftree->pending = 0;
+    retval = isis_run_spf (area, level, AF_INET);
+  }
+
+  return retval;
+}
+
+#ifdef HAVE_IPV6
+int 
+isis_spf_schedule6 (struct isis_area *area, int level)
+{
+  int retval = ISIS_OK;
+  struct isis_spftree *spftree = area->spftree6[level - 1];
+  time_t diff, now = time (NULL);
+
+  if (spftree->pending)
+    return retval;
+
+  diff = now - spftree->lastrun; 
+  
+  if (spftree->t_spf_periodic)
+    thread_cancel (spftree->t_spf_periodic);
+  
+  /* FIXME: let's wait a minute before doing the SPF */
+  if (now - isis->uptime < 60 || isis->uptime == 0) {
+    if (level == 1)
+      thread_add_timer (master, isis_run_spf_l1, area, 
+                        60);
+    else
+      thread_add_timer (master, isis_run_spf_l2, area, 
+                        60);
+
+    spftree->pending = 1;
+    return retval;
+  }
+
+
+  if (diff < MINIMUM_SPF_INTERVAL) {
+    if (level == 1)
+      thread_add_timer (master, isis_run_spf_l1, area, 
+                        MINIMUM_SPF_INTERVAL - diff);
+    else
+      thread_add_timer (master, isis_run_spf_l2, area, 
+                        MINIMUM_SPF_INTERVAL - diff);
+
+    spftree->pending = 1;
+  } else {
+    spftree->pending = 0;
+    retval = isis_run_spf (area, level, AF_INET6);
+  }
+
+  return retval;
+}
+
+#endif
+
+void
+isis_print_paths (struct vty *vty, struct list *paths)
+{
+  struct listnode *node, *anode;
+  struct isis_vertex *vertex;
+  struct isis_dynhn *dyn, *nh_dyn = NULL;
+  struct isis_adjacency *adj;
+#ifdef EXTREME_DEBUG
+  u_char buff[255];
+#endif 
+
+  vty_out (vty, "System Id            Metric     Next-Hop"
+           "             Interface   SNPA%s", VTY_NEWLINE);
+  for (node = listhead (paths); node; nextnode (node)) {
+    vertex = getdata (node);
+    if (vertex->type != VTYPE_NONPSEUDO_IS)
+      continue;
+    if (memcmp (vertex->N.id, isis->sysid, ISIS_SYS_ID_LEN) == 0) {
+      vty_out (vty, "%s             --%s", host.name, VTY_NEWLINE);
+    } else {
+      dyn = dynhn_find_by_id ((u_char *)vertex->N.id);
+      anode = listhead (vertex->Adj_N);
+      adj = getdata (anode);
+      if (adj) {
+        nh_dyn = dynhn_find_by_id (adj->sysid);
+        vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s", 
+                 (dyn != NULL) ? dyn->name.name : 
+                 (u_char *)rawlspid_print ((u_char *)vertex->N.id),
+                 vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name : 
+                 (u_char *)rawlspid_print (adj->sysid), 
+                 adj->circuit->interface->name,
+                 snpa_print (adj->snpa), VTY_NEWLINE);
+      } else {
+        vty_out (vty, "%s              %u %s", dyn ? dyn->name.name : 
+                 (u_char *)rawlspid_print (vertex->N.id), 
+                 vertex->d_N, VTY_NEWLINE);
+      }
+        
+    }
+#if 0
+    vty_out (vty, "%s %s %u %s", vtype2string(vertex->type), 
+             vid2string(vertex, buff), vertex->d_N, VTY_NEWLINE);
+#endif
+  }
+
+  
+}
+
+DEFUN (show_isis_topology,
+       show_isis_topology_cmd,
+       "show isis topology",
+       SHOW_STR
+       "IS-IS information\n"
+       "IS-IS paths to Intermediate Systems\n")
+{
+  struct listnode *node;
+  struct isis_area *area;
+  int level;
+  
+  if (!isis->area_list || isis->area_list->count == 0)
+    return CMD_SUCCESS;
+
+  for (node = listhead (isis->area_list); node; nextnode (node)) {
+    area = getdata (node);
+
+    vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
+             VTY_NEWLINE);
+    
+    for (level=0; level < ISIS_LEVELS; level++) {
+      if (area->ip_circuits > 0 && area->spftree[level] 
+          && area->spftree[level]->paths->count > 0) {
+        vty_out (vty, "IS-IS paths to level-%d routers that speak IP%s", 
+                 level+1, VTY_NEWLINE);
+        isis_print_paths (vty, area->spftree[level]->paths);
+      }
+#ifdef HAVE_IPV6
+      if (area->ipv6_circuits > 0 && area->spftree6[level] 
+          && area->spftree6[level]->paths->count > 0) {
+        vty_out (vty, "IS-IS paths to level-%d routers that speak IPv6%s", 
+                 level+1, VTY_NEWLINE);
+        isis_print_paths (vty, area->spftree6[level]->paths);
+      }
+#endif /* HAVE_IPV6 */
+    }
+  }
+
+  return CMD_SUCCESS;
+} 
+
+
+DEFUN (show_isis_topology_l1,
+       show_isis_topology_l1_cmd,
+       "show isis topology level-1",
+       SHOW_STR
+       "IS-IS information\n"
+       "IS-IS paths to Intermediate Systems\n"
+       "Paths to all level-1 routers in the area\n")
+{
+  struct listnode *node;
+  struct isis_area *area;
+  
+  if (!isis->area_list || isis->area_list->count == 0)
+    return CMD_SUCCESS;
+
+  for (node = listhead (isis->area_list); node; nextnode (node)) {
+    area = getdata (node);
+
+    vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
+             VTY_NEWLINE);
+    
+    if (area->ip_circuits > 0 && area->spftree[0] 
+        && area->spftree[0]->paths->count > 0) {
+      vty_out (vty, "IS-IS paths to level-1 routers that speak IP%s", 
+               VTY_NEWLINE);
+      isis_print_paths (vty, area->spftree[0]->paths);
+    }
+#ifdef HAVE_IPV6
+      if (area->ipv6_circuits > 0 && area->spftree6[0] 
+          && area->spftree6[0]->paths->count > 0) {
+        vty_out (vty, "IS-IS paths to level-1 routers that speak IPv6%s", 
+                 VTY_NEWLINE);
+        isis_print_paths (vty, area->spftree6[0]->paths);
+      }
+#endif /* HAVE_IPV6 */
+    }
+
+
+  return CMD_SUCCESS;
+} 
+
+DEFUN (show_isis_topology_l2,
+       show_isis_topology_l2_cmd,
+       "show isis topology level-2",
+       SHOW_STR
+       "IS-IS information\n"
+       "IS-IS paths to Intermediate Systems\n"
+       "Paths to all level-2 routers in the domain\n")
+{
+  struct listnode *node;
+  struct isis_area *area;
+  
+  if (!isis->area_list || isis->area_list->count == 0)
+    return CMD_SUCCESS;
+
+  for (node = listhead (isis->area_list); node; nextnode (node)) {
+    area = getdata (node);
+
+    vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
+             VTY_NEWLINE);
+    
+    if (area->ip_circuits > 0 && area->spftree[1] 
+        && area->spftree[1]->paths->count > 0) {
+      vty_out (vty, "IS-IS paths to level-2 routers that speak IP%s", 
+               VTY_NEWLINE);
+      isis_print_paths (vty, area->spftree[1]->paths);
+    }
+#ifdef HAVE_IPV6
+      if (area->ipv6_circuits > 0 && area->spftree6[1] 
+          && area->spftree6[1]->paths->count > 0) {
+        vty_out (vty, "IS-IS paths to level-2 routers that speak IPv6%s", 
+                 VTY_NEWLINE);
+        isis_print_paths (vty, area->spftree6[1]->paths);
+      }
+#endif /* HAVE_IPV6 */
+    }
+
+
+  return CMD_SUCCESS;
+} 
+
+
+void
+isis_spf_cmds_init ()
+{
+  install_element (VIEW_NODE, &show_isis_topology_cmd);
+  install_element (VIEW_NODE, &show_isis_topology_l1_cmd);
+  install_element (VIEW_NODE, &show_isis_topology_l2_cmd);
+
+  install_element (ENABLE_NODE, &show_isis_topology_cmd);
+  install_element (ENABLE_NODE, &show_isis_topology_l1_cmd);
+  install_element (ENABLE_NODE, &show_isis_topology_l2_cmd);
+}
diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h
new file mode 100644
index 0000000..59e4b6b
--- /dev/null
+++ b/isisd/isis_spf.h
@@ -0,0 +1,85 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_spf.h
+ *                             IS-IS Shortest Path First algorithm  
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_SPF_H
+#define _ZEBRA_ISIS_SPF_H
+
+enum vertextype {
+  VTYPE_PSEUDO_IS = 1,
+  VTYPE_NONPSEUDO_IS,
+  VTYPE_ES,
+  VTYPE_IPREACH_INTERNAL,
+  VTYPE_IPREACH_EXTERNAL
+#ifdef HAVE_IPV6
+  , 
+  VTYPE_IP6REACH_INTERNAL,
+  VTYPE_IP6REACH_EXTERNAL
+#endif /* HAVE_IPV6 */ 
+};
+
+/*
+ * Triple <N, d(N), {Adj(N)}> 
+ */
+struct isis_vertex
+{
+  enum vertextype type;
+
+  union {
+    u_char id [ISIS_SYS_ID_LEN + 1];
+    struct prefix prefix;
+  } N;
+  
+  struct isis_lsp *lsp;
+  u_int32_t d_N;   /* d(N) Distance from this IS      */
+  u_int16_t depth; /* The depth in the imaginary tree */
+
+  struct list *Adj_N; /* {Adj(N)}  */
+}; 
+
+
+struct isis_spftree
+{
+  struct thread *t_spf_periodic;  /* periodic spf threads  */
+  time_t                lastrun;  /* for scheduling */
+  int                   pending;  /* already scheduled */
+  struct list            *paths;  /* the SPT */
+  struct list            *tents;  /* TENT */
+
+  u_int32_t             timerun;  /* statistics */
+};
+
+void spftree_area_init (struct isis_area *area);
+int isis_spf_schedule (struct isis_area *area, int level);
+void isis_spf_cmds_init (void);
+#ifdef HAVE_IPV6
+int isis_spf_schedule6 (struct isis_area *area, int level);
+#endif
+#endif /* _ZEBRA_ISIS_SPF_H */
+
+
+
+
+
+
+
+
diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c
new file mode 100644
index 0000000..b51cee9
--- /dev/null
+++ b/isisd/isis_tlv.c
@@ -0,0 +1,1014 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_tlv.c
+ *                             IS-IS TLV related routines
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "log.h"
+#include "linklist.h"
+#include "stream.h"
+#include "memory.h"
+#include "prefix.h"
+#include "vty.h"
+#include "if.h"
+
+#include "isisd/dict.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_dynhn.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_lsp.h"
+
+extern struct isis *isis;
+
+void
+free_tlv (void *val)
+{
+    XFREE (MTYPE_ISIS_TLV, val);
+    
+    return;
+}
+
+/*
+ * Called after parsing of a PDU. There shouldn't be any tlv's left, so this
+ * is only a caution to avoid memory leaks
+ */
+void 
+free_tlvs (struct tlvs *tlvs)
+{
+  if (tlvs->area_addrs) {
+    list_delete (tlvs->area_addrs);
+  }
+  if (tlvs->is_neighs) {
+    list_delete (tlvs->is_neighs);
+  }
+  if (tlvs->te_is_neighs) {
+    list_delete (tlvs->te_is_neighs);
+  }
+  if (tlvs->es_neighs) {
+    list_delete (tlvs->es_neighs);
+  }
+  if (tlvs->lsp_entries) {
+    list_delete (tlvs->lsp_entries);
+  }  
+  if (tlvs->lan_neighs) {
+    list_delete (tlvs->lan_neighs);
+  }
+  if (tlvs->prefix_neighs) {
+    list_delete (tlvs->prefix_neighs);
+  }
+  if (tlvs->ipv4_addrs) {
+    list_delete (tlvs->ipv4_addrs);
+  }
+  if (tlvs->ipv4_int_reachs) {
+    list_delete (tlvs->ipv4_int_reachs);
+  }
+  if (tlvs->ipv4_ext_reachs) {
+    list_delete (tlvs->ipv4_ext_reachs);
+  }
+  if (tlvs->te_ipv4_reachs) {
+    list_delete (tlvs->te_ipv4_reachs);
+  }
+#ifdef HAVE_IPV6
+  if (tlvs->ipv6_addrs) {
+    list_delete (tlvs->ipv6_addrs);
+  }
+  if (tlvs->ipv6_reachs) {
+    list_delete (tlvs->ipv6_reachs);
+  }
+#endif /* HAVE_IPV6 */
+  return;
+}
+
+/*
+ * Parses the tlvs found in the variant length part of the PDU.
+ * Caller tells with flags in "expected" which TLV's it is interested in.
+ */
+int 
+parse_tlvs (char *areatag, u_char *stream, int size, u_int32_t *expected, 
+	    u_int32_t *found, struct tlvs *tlvs)
+{
+  u_char                          type, length;
+  struct lan_neigh                    *lan_nei;
+  struct area_addr                  *area_addr;
+  struct is_neigh                      *is_nei;
+  struct te_is_neigh                *te_is_nei;
+  struct es_neigh                      *es_nei;
+  struct lsp_entry                  *lsp_entry;
+  struct in_addr                    *ipv4_addr;
+  struct ipv4_reachability         *ipv4_reach;
+  struct te_ipv4_reachability   *te_ipv4_reach;
+#ifdef HAVE_IPV6
+  struct in6_addr                   *ipv6_addr;
+  struct ipv6_reachability         *ipv6_reach;
+  int                            prefix_octets;
+#endif /* HAVE_IPV6 */
+  u_char                               virtual;
+  int              value_len, retval = ISIS_OK;
+  u_char                   *pnt = stream;
+
+  *found = 0;
+  memset (tlvs, 0, sizeof (struct tlvs));
+  
+  while (pnt < stream + size - 2) {
+    type = *pnt;
+    length = *(pnt+1);
+    pnt += 2;
+    value_len = 0;
+    if ( pnt + length > stream + size ) {
+      zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet "
+		 "boundaries", areatag, type, length);
+      retval = ISIS_WARNING;
+      break;
+    }
+    switch (type) {
+    case AREA_ADDRESSES:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        Address Length                         | 
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                         Area Address                          | 
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_AREA_ADDRS;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("TLV Area Adresses len %d", length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_AREA_ADDRS) {
+        while (length > value_len) {
+          area_addr = (struct area_addr*)pnt;
+          value_len += area_addr->addr_len + 1;
+          pnt +=  area_addr->addr_len + 1;
+          if (!tlvs->area_addrs) tlvs->area_addrs = list_new ();
+          listnode_add (tlvs->area_addrs, area_addr);
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case IS_NEIGHBOURS:
+      *found |= TLVFLAG_IS_NEIGHS;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): IS Neighbours length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (TLVFLAG_IS_NEIGHS & *expected) {
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        Virtual Flag                           | 
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       */
+        virtual = *pnt; /* FIXME: what is the use for this? */
+        pnt++;
+        value_len ++;
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   0   |  I/E  |               Default Metric                  | 
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Delay Metric                    |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Expense Metric                  |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Error Metric                    |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        Neighbour ID                           |
+       * +---------------------------------------------------------------+
+       * :                                                               :
+       */
+        while (length > value_len) {
+          is_nei = (struct is_neigh*)pnt;
+          value_len += 4 + ISIS_SYS_ID_LEN + 1;
+          pnt += 4 + ISIS_SYS_ID_LEN + 1;
+          if (!tlvs->is_neighs) tlvs->is_neighs = list_new ();
+          listnode_add (tlvs->is_neighs, is_nei);
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case TE_IS_NEIGHBOURS:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        Neighbour ID                           | 7
+       * +---------------------------------------------------------------+
+       * |                        TE Metric                              | 3
+       * +---------------------------------------------------------------+
+       * |                        SubTLVs Length                         | 1
+       * +---------------------------------------------------------------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_TE_IS_NEIGHS;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): Extended IS Neighbours length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (TLVFLAG_TE_IS_NEIGHS & *expected) {
+        while (length > value_len) {
+          te_is_nei = (struct te_is_neigh*)pnt;
+          value_len += 11;
+          pnt += 11;
+          /* FIXME - subtlvs are handled here, for now we skip */
+          value_len += te_is_nei->sub_tlvs_length;
+          pnt += te_is_nei->sub_tlvs_length;
+
+
+          if (!tlvs->te_is_neighs) tlvs->te_is_neighs = list_new ();
+          listnode_add (tlvs->te_is_neighs, te_is_nei);
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case ES_NEIGHBOURS: 
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   0   |  I/E  |               Default Metric                  | 
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Delay Metric                    |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Expense Metric                  |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Error Metric                    |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        Neighbour ID                           |
+       * +---------------------------------------------------------------+
+       * |                        Neighbour ID                           |
+       * +---------------------------------------------------------------+
+       * :                                                               :
+       */
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): ES Neighbours length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      *found |= TLVFLAG_ES_NEIGHS;
+      if (*expected & TLVFLAG_ES_NEIGHS) {
+        es_nei = (struct es_neigh*)pnt;
+        value_len += 4;
+        pnt += 4;
+        while (length > value_len) {
+        /* FIXME FIXME FIXME - add to the list */
+	/*          sys_id->id = pnt;*/
+          value_len += ISIS_SYS_ID_LEN;
+          pnt += ISIS_SYS_ID_LEN;
+        /*  if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid;*/
+        }
+        if (!tlvs->es_neighs) tlvs->es_neighs = list_new ();
+        listnode_add (tlvs->es_neighs, es_nei);
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case LAN_NEIGHBOURS:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        LAN Address                            | 
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_LAN_NEIGHS;
+      #ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): LAN Neigbours length %d",
+		 areatag,
+		 length);
+      #endif /* EXTREME_TLV_DEBUG */
+      if (TLVFLAG_LAN_NEIGHS & *expected) {
+        while (length > value_len) {
+          lan_nei = (struct lan_neigh*)pnt;
+          if (!tlvs->lan_neighs) tlvs->lan_neighs = list_new ();
+          listnode_add (tlvs->lan_neighs, lan_nei);
+          value_len += ETH_ALEN;
+          pnt += ETH_ALEN;
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case PADDING:
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("TLV padding %d", length);
+#endif /* EXTREME_TLV_DEBUG */
+      pnt += length;
+      break;
+
+    case LSP_ENTRIES:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                     Remaining Lifetime                        | 2
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                         LSP ID                                | id+2
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                   LSP Sequence Number                         | 4
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        Checksum                               | 2
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       */
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("LSP Entries length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      *found |= TLVFLAG_LSP_ENTRIES;
+      if (TLVFLAG_LSP_ENTRIES & *expected) {
+        while (length > value_len) {
+          lsp_entry = (struct lsp_entry*)pnt;
+          value_len += 10 + ISIS_SYS_ID_LEN;
+          pnt +=  10 + ISIS_SYS_ID_LEN;
+          if (!tlvs->lsp_entries) tlvs->lsp_entries = list_new ();
+          listnode_add (tlvs->lsp_entries, lsp_entry);
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case CHECKSUM:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                   16 bit fletcher CHECKSUM                    |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_CHECKSUM;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): Checksum length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_CHECKSUM) {
+        tlvs->checksum = (struct checksum*)pnt;
+      }
+      pnt += length;
+      break;
+
+    case PROTOCOLS_SUPPORTED:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                       NLPID                                   |
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_NLPID;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): Protocols Supported length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_NLPID) {
+        tlvs->nlpids = (struct nlpids*)(pnt-1);
+      }
+      pnt += length;
+      break;
+
+    case IPV4_ADDR:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * +                 IP version 4 address                          + 4
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_IPV4_ADDR;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): IPv4 Address length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_IPV4_ADDR) {
+        while (length > value_len) {
+          ipv4_addr = (struct in_addr*)pnt;
+	  zlog_info ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag, 
+		     inet_ntoa (*ipv4_addr), pnt);
+          if (!tlvs->ipv4_addrs) tlvs->ipv4_addrs = list_new();
+          listnode_add (tlvs->ipv4_addrs, ipv4_addr);
+          value_len += 4;
+          pnt += 4;
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case AUTH_INFO:
+      *found |= TLVFLAG_AUTH_INFO;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): IS-IS Authentication Information",
+		 areatag);
+#endif
+      if (*expected & TLVFLAG_AUTH_INFO) {
+	tlvs->auth_info.type = *pnt;
+	pnt++;
+	memcpy (tlvs->auth_info.passwd, pnt, length - 1);
+	pnt += length - 1;
+      }
+      else {
+	pnt += length;
+      }
+      break;
+
+    case DYNAMIC_HOSTNAME:
+      *found |= TLVFLAG_DYN_HOSTNAME;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): Dynamic Hostname length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_DYN_HOSTNAME) {
+	/* the length is also included in the pointed struct */
+        tlvs->hostname = (struct hostname*)(pnt - 1); 
+      }
+      pnt += length;
+      break;
+
+    case TE_ROUTER_ID:
+      /* +---------------------------------------------------------------+
+       * +                         Router ID                             + 4
+       * +---------------------------------------------------------------+
+       */
+      *found |= TLVFLAG_TE_ROUTER_ID;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): TE Router ID %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_TE_ROUTER_ID) {
+        tlvs->router_id = (struct te_router_id*)(pnt);
+      }
+      pnt += length;
+      break;
+
+    case IPV4_INT_REACHABILITY:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   0   |  I/E  |               Default Metric                  | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Delay Metric                    | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Expense Metric                  | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Error Metric                    | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        ip address                             | 4
+       * +---------------------------------------------------------------+
+       * |                        address mask                           | 4
+       * +---------------------------------------------------------------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_IPV4_INT_REACHABILITY;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): IPv4 internal Reachability length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_IPV4_INT_REACHABILITY) {
+        while (length > value_len) {
+          ipv4_reach = (struct ipv4_reachability*)pnt;
+          if (!tlvs->ipv4_int_reachs) tlvs->ipv4_int_reachs = list_new();
+          listnode_add (tlvs->ipv4_int_reachs, ipv4_reach);
+          value_len += 12;
+          pnt += 12;
+        }
+      }
+      else {
+        pnt += length;
+      }
+      break;
+
+    case IPV4_EXT_REACHABILITY:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   0   |  I/E  |               Default Metric                  | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Delay Metric                    | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Expense Metric                  | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |   S   |  I/E  |               Error Metric                    | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        ip address                             | 4
+       * +---------------------------------------------------------------+
+       * |                        address mask                           | 4
+       * +---------------------------------------------------------------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_TE_IPV4_REACHABILITY;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): IPv4 external Reachability length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) {
+        while (length > value_len) {
+          ipv4_reach = (struct ipv4_reachability*)pnt;
+          if (!tlvs->ipv4_ext_reachs) tlvs->ipv4_ext_reachs = list_new();
+          listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach);
+          value_len += 12;
+          pnt += 12;
+        }
+      }
+      else {
+        pnt += length;
+      }
+      break;
+
+    case TE_IPV4_REACHABILITY:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        TE Metric                              | 4
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |  U/D  | sTLV? |               Prefix Mask Len                 | 1
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                           Prefix                              | 0-4
+       * +---------------------------------------------------------------+
+       * |                         sub tlvs                              |
+       * +---------------------------------------------------------------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_TE_IPV4_REACHABILITY;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): IPv4 extended Reachability length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) {
+        while (length > value_len) {
+          te_ipv4_reach = (struct te_ipv4_reachability*)pnt;
+          if (!tlvs->te_ipv4_reachs) tlvs->te_ipv4_reachs = list_new();
+          listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach);
+          /* this trickery is permitable since no subtlvs are defined */
+          value_len += 5 + ((te_ipv4_reach->control & 0x3F) ? 
+                           ((((te_ipv4_reach->control & 0x3F)-1)>>3)+1) : 0);
+          pnt +=  5 + ((te_ipv4_reach->control & 0x3F) ? 
+                      ((((te_ipv4_reach->control & 0x3F)-1)>>3)+1) : 0);
+        }
+      }
+      else {
+        pnt += length;
+      }
+      break;
+
+#ifdef  HAVE_IPV6
+    case IPV6_ADDR:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * +                 IP version 6 address                          + 16
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * :                                                               :
+       */
+      *found |= TLVFLAG_IPV6_ADDR;
+#ifdef EXTREME_TLV_DEBUG
+      zlog_info ("ISIS-TLV (%s): IPv6 Address length %d",
+		 areatag,
+		 length);
+#endif /* EXTREME_TLV_DEBUG */
+      if (*expected & TLVFLAG_IPV6_ADDR) {
+        while (length > value_len) {
+          ipv6_addr = (struct in6_addr*)pnt;
+          if (!tlvs->ipv6_addrs) tlvs->ipv6_addrs = list_new();
+          listnode_add (tlvs->ipv6_addrs, ipv6_addr);
+          value_len += 16;
+          pnt += 16;
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+
+    case IPV6_REACHABILITY:
+      /* +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                 Default Metric                                | 4 
+       * +-------+-------+-------+-------+-------+-------+-------+-------+
+       * |                        Control Informantion                   |
+       * +---------------------------------------------------------------+
+       * |                        IPv6 Prefix Length                     |--+
+       * +---------------------------------------------------------------+  |
+       * |                        IPv6 Prefix                            |<-+
+       * +---------------------------------------------------------------+
+       */
+      *found |= TLVFLAG_IPV6_REACHABILITY;
+      if (*expected & TLVFLAG_IPV6_REACHABILITY) {
+        while (length > value_len) {
+          ipv6_reach = (struct ipv6_reachability*)pnt;
+          prefix_octets = ((ipv6_reach->prefix_len + 7) / 8);
+          value_len += prefix_octets + 6;
+          pnt +=  prefix_octets + 6;
+          /* FIXME: sub-tlvs */
+          if (!tlvs->ipv6_reachs) tlvs->ipv6_reachs = list_new();
+          listnode_add (tlvs->ipv6_reachs, ipv6_reach);
+        }
+      } else {
+        pnt += length;
+      }
+      break;
+#endif /* HAVE_IPV6 */
+
+    case WAY3_HELLO:
+      /* +---------------------------------------------------------------+
+       * |                  Adjacency state                              | 1
+       * +---------------------------------------------------------------+
+       * |                  Extended Local Circuit ID                    | 4
+       * +---------------------------------------------------------------+
+       * |                  Neighbor System ID (If known)                | 0-8
+       *                                      (probably 6)
+       * +---------------------------------------------------------------+
+       * |                  Neighbor Local Circuit ID (If known)         | 4
+       * +---------------------------------------------------------------+
+       */
+      *found |= TLVFLAG_3WAY_HELLO;
+      if (*expected & TLVFLAG_3WAY_HELLO) {
+        while (length > value_len) {
+        /* FIXME: make this work */
+/*           Adjacency State (one octet):
+              0 = Up
+              1 = Initializing
+              2 = Down
+            Extended Local Circuit ID (four octets)
+            Neighbor System ID if known (zero to eight octets)
+            Neighbor Extended Local Circuit ID (four octets, if Neighbor
+              System ID is present) */
+          pnt += length;
+        }
+      } else {
+        pnt += length;
+      }
+
+      break;
+
+    default:
+      zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d",
+		 areatag,
+		 type,
+		 length);
+
+      retval = ISIS_WARNING;
+      pnt += length;
+      break;
+    }
+  }
+  
+  return retval;
+}
+
+int
+add_tlv (u_char tag, u_char len, u_char *value, struct stream *stream)
+{
+
+  if (STREAM_SIZE (stream) - stream_get_putp (stream)  < len + 2) {
+    zlog_warn ("No room for TLV of type %d", tag);
+    return ISIS_WARNING;
+  }
+
+  stream_putc (stream, tag);  /* TAG */
+  stream_putc (stream, len);  /* LENGTH */
+  stream_put (stream, value, (int)len); /* VALUE */
+
+#ifdef EXTREME_DEBUG
+  zlog_info ("Added TLV %d len %d", tag, len);
+#endif /* EXTREME DEBUG */
+  return ISIS_OK;
+}
+
+
+int
+tlv_add_area_addrs (struct list *area_addrs, struct stream *stream) 
+{
+  struct listnode *node;
+  struct area_addr *area_addr;
+
+  u_char value [255];
+  u_char *pos = value;
+  
+  for (node = listhead (area_addrs); node; nextnode (node)) { 
+    area_addr = getdata (node);
+    if (pos - value + area_addr->addr_len > 255)
+      goto err;
+    *pos = area_addr->addr_len;
+    pos ++;
+    memcpy (pos, area_addr->area_addr, (int)area_addr->addr_len);
+    pos += area_addr->addr_len;
+  }
+  
+  return add_tlv (AREA_ADDRESSES, pos - value, value, stream);
+
+ err:
+  zlog_warn ("tlv_add_area_addrs(): TLV longer than 255");
+  return ISIS_WARNING;
+}
+
+int tlv_add_is_neighs (struct list *is_neighs, struct stream *stream)
+{
+  struct listnode *node;
+  struct is_neigh *is_neigh;
+  u_char value [255];
+  u_char *pos = value;
+  int retval;
+
+  *pos =  0; /*is_neigh->virtual; */
+  pos ++;
+
+  for (node = listhead (is_neighs); node; nextnode (node)) { 
+    is_neigh = getdata (node);
+    if (pos - value + IS_NEIGHBOURS_LEN > 255) {
+      retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
+      if (retval != ISIS_OK)
+	return retval;
+      pos = value;
+    }
+    *pos = is_neigh->metrics.metric_default;
+    pos ++;    
+    *pos = is_neigh->metrics.metric_delay;
+    pos ++;    
+    *pos = is_neigh->metrics.metric_expense;
+    pos ++;    
+    *pos = is_neigh->metrics.metric_error;
+    pos ++;
+    memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1);
+    pos += ISIS_SYS_ID_LEN + 1;
+  }
+
+  return add_tlv (IS_NEIGHBOURS, pos - value, value, stream);
+}
+
+
+int
+tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream)
+{
+  struct listnode *node;
+  u_char *snpa;
+  u_char value [255];
+  u_char *pos = value;
+  int retval;
+
+  for (node = listhead (lan_neighs); node; nextnode (node)) { 
+    snpa = getdata (node);
+    if (pos - value + ETH_ALEN > 255) {
+      retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
+      if (retval != ISIS_OK)
+	return retval;
+      pos = value;
+    }
+    memcpy (pos, snpa, ETH_ALEN);
+    pos += ETH_ALEN;
+  }
+
+  return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream);
+}
+
+
+/*
+  u_char value[255];
+  u_char *pos = value;
+
+  if (circuit->ip_router) {                             
+    *pos =  (u_char)NLPID_IP;
+    pos ++;
+  }
+  if (circuit->ipv6_router) {                         
+    *pos = (u_char)NLPID_IPV6;
+    pos ++;
+  }
+*/
+
+int
+tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream)
+{
+  
+  return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, 
+                  nlpids->nlpids, stream); 
+}
+
+int tlv_add_authinfo  (char auth_type, char auth_len, char *auth_value,
+		       struct stream *stream)
+{
+  u_char value[255];
+  u_char *pos = value;
+  pos++;
+  memcpy (pos, auth_value, auth_len);
+
+  return add_tlv (AUTH_INFO, auth_len + 1, value, stream);
+}
+
+int
+tlv_add_checksum (struct checksum *checksum, struct stream *stream)
+{
+  u_char value[255];
+  u_char *pos = value;  
+  return add_tlv (CHECKSUM, pos - value, 
+                  value, stream); 
+}
+
+int
+tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream)
+{
+  struct listnode *node;
+  struct prefix_ipv4 *ipv4;
+  u_char value[255];
+  u_char *pos = value;
+  int retval;
+
+  for (node = listhead (ip_addrs); node; nextnode (node)) { 
+    ipv4 = getdata (node);
+    if (pos - value + IPV4_MAX_BYTELEN > 255) {
+      retval = add_tlv (IPV4_ADDR, pos - value, value, stream);
+      if (retval != ISIS_OK)
+	return retval;
+      pos = value;
+    }
+    *(u_int32_t*)pos = ipv4->prefix.s_addr;
+    pos += IPV4_MAX_BYTELEN;
+  }
+  
+  return add_tlv (IPV4_ADDR, pos - value, value, stream);
+}
+
+int
+tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream)
+{
+  return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name, stream);
+}
+
+int 
+tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
+{
+  struct listnode *node;
+  struct isis_lsp *lsp;
+  u_char value [255];
+  u_char *pos = value;
+  int retval;
+
+  for (node = listhead (lsps); node; nextnode (node)) { 
+    lsp = getdata (node);
+    if (pos - value + LSP_ENTRIES_LEN > 255) {
+      retval = add_tlv (LSP_ENTRIES, pos - value, value, stream);
+      if (retval != ISIS_OK)
+	return retval;
+      pos = value;
+    }
+    *((u_int16_t*)pos) = lsp->lsp_header->rem_lifetime;
+    pos += 2;
+    memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
+    pos += ISIS_SYS_ID_LEN + 2;
+    *((u_int32_t*)pos) = lsp->lsp_header->seq_num;
+    pos += 4;    
+    *((u_int16_t*)pos) = lsp->lsp_header->checksum;
+    pos += 2;
+  }
+  
+  return add_tlv (LSP_ENTRIES, pos - value, value, stream);
+}
+
+int 
+tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
+{
+  struct listnode *node;
+  struct ipv4_reachability *reach;
+  u_char value [255];
+  u_char *pos = value;
+  int retval;
+
+  for (node = listhead (ipv4_reachs); node; nextnode (node)) { 
+    reach = getdata (node);
+    if (pos - value + IPV4_REACH_LEN > 255) {
+      retval = add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
+      if (retval != ISIS_OK)
+	return retval;
+      pos = value;
+    }
+    *pos = reach->metrics.metric_default;
+    pos ++;    
+    *pos = reach->metrics.metric_delay;
+    pos ++;    
+    *pos = reach->metrics.metric_expense;
+    pos ++;    
+    *pos = reach->metrics.metric_error;
+    pos ++;
+   *(u_int32_t*)pos = reach->prefix.s_addr;
+    pos += IPV4_MAX_BYTELEN;
+   *(u_int32_t*)pos = reach->mask.s_addr;
+    pos += IPV4_MAX_BYTELEN;
+  }    
+  
+  
+  return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
+}
+
+#ifdef HAVE_IPV6 
+int
+tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream)
+{
+  struct listnode *node;
+  struct prefix_ipv6 *ipv6;
+  u_char value[255];
+  u_char *pos = value;
+  int retval;
+  
+  for (node = listhead (ipv6_addrs); node; nextnode (node)) { 
+    ipv6 = getdata (node);
+    if (pos - value + IPV6_MAX_BYTELEN > 255) {
+      retval = add_tlv (IPV6_ADDR, pos - value, value, stream);
+      if (retval != ISIS_OK)
+	return retval;
+      pos = value;
+    }
+    memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN);
+    pos += IPV6_MAX_BYTELEN;
+  }
+  
+  return add_tlv (IPV6_ADDR, pos - value, value, stream);
+}
+
+int
+tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream)
+{
+  struct listnode *node;
+  struct ipv6_reachability *ip6reach;
+  u_char value[255];
+  u_char *pos = value;
+  int retval, prefix_octets;
+ 
+  for (node = listhead (ipv6_reachs); node; nextnode (node)) { 
+    ip6reach = getdata (node);
+    if (pos - value + IPV6_MAX_BYTELEN + 6 > 255) {
+      retval = add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
+      if (retval != ISIS_OK)
+	return retval;
+      pos = value;
+    }
+    *(uint32_t*)pos = ip6reach->metric;
+    pos += 4;
+    *pos = ip6reach->control_info;
+    pos++;
+    prefix_octets = ((ip6reach->prefix_len + 7) / 8);
+    *pos = ip6reach->prefix_len;
+    pos++;
+    memcpy (pos, ip6reach->prefix, prefix_octets);
+    pos += prefix_octets;
+  }
+  
+  return add_tlv (IPV6_REACHABILITY, pos - value, value, stream);
+}
+#endif /* HAVE_IPV6 */
+
+int
+tlv_add_padding (struct stream *stream)
+{
+  unsigned long putp, endp;
+  int  fullpads, i, left;
+  
+  /*
+   * How many times can we add full padding ?
+   */
+  fullpads = (STREAM_SIZE(stream) - stream_get_endp (stream)) / 257;
+  for (i = 0; i < fullpads; i ++) {
+    if (!stream_putc (stream, (u_char)PADDING)) /* TAG */
+      goto err;
+    if (!stream_putc (stream, (u_char)255))     /* LENGHT */
+      goto err;
+    endp = stream_get_endp (stream);
+    putp = stream_get_putp (stream);
+    if (putp != endp)
+      zlog_warn ("tvl_add_padding endp %ld while putp %ld", endp, putp);
+    stream_set_putp (stream, putp + 255);       /* VALUE */
+    stream->endp = stream->putp;
+  }
+  
+  left = STREAM_SIZE(stream) - stream_get_putp (stream);
+  
+  if (left < 2)
+    return ISIS_OK;
+  
+  if (left == 2) {
+    stream_putc (stream, PADDING);
+    stream_putc (stream, 0);
+    return ISIS_OK;
+  }
+  
+  stream_putc (stream, PADDING);
+  stream_putc (stream, left - 2);
+  stream_set_putp (stream, stream_get_putp (stream) + left - 2);
+  stream->endp = stream->putp;
+
+  return ISIS_OK;
+
+ err:
+  zlog_warn ("tlv_add_padding(): no room for tlv");
+  return ISIS_WARNING;
+}
diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h
new file mode 100644
index 0000000..79c0c46
--- /dev/null
+++ b/isisd/isis_tlv.h
@@ -0,0 +1,268 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_tlv.h
+ *                             IS-IS TLV related routines
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_ISIS_TLV_H
+#define _ZEBRA_ISIS_TLV_H
+
+/*
+ * Structures found in TLV's.
+ * this header is fully complient with
+ * draft-ietf-isis-wg-tlv-codepoints-02.txt
+ 1.  TLV Codepoints reserved
+     ____________________________________________________
+     Name                 Value   IIH   LSP  SNP   Status
+     ____________________________________________________
+
+     Area Addresses            1  y     y    n  ISO 10589
+     IIS Neighbors             2  n     y    n  ISO 10589
+     ES Neighbors              3  n     y    n  ISO 10589
+     Part. DIS                 4  n     y    n  ISO 10589
+     Prefix Neighbors          5  n     y    n  ISO 10589
+     IIS Neighbors             6  y     n    n  ISO 10589
+     Padding                   8  y     n    n  ISO 10589
+     LSP Entries               9  n     n    y  ISO 10589
+     Authentication           10  y     y    y  ISO 10589
+     Opt. Checksum            12  y     n    y  IETF-draft
+     LSPBufferSize            14  n     y    n  ISO 10589 Rev 2 Draft
+     TE IIS Neigh.            22  n     y    n  IETF-draft
+     DECnet Phase IV          42  y     n    n  DEC (ancient)
+     IP Int. Reach           128  n     y    n  RFC 1195
+     Prot. Supported         129  y     y    n  RFC 1195
+     IP Ext. Address         130  n     y    n  RFC 1195
+     IDRPI                   131  n     y    y  RFC 1195
+     IP Intf. Address        132  y     y    n  RFC 1195
+     Illegal                 133  n     n    n  RFC 1195 (not used)
+     Router ID               134  n     y    n  IETF-draft
+     TE IP. Reach            135  n     y    n  IETF-draft
+     Dynamic Name            137  n     y    n  RFC 2763
+     Nortel Proprietary      176  n     y    n
+     Nortel Proprietary      177  n     y    n
+     Restart TLV             211  y     n    n  IETF-draft
+     MT-ISN                  222  n     y    n  IETF-draft
+     M-Topologies            229  y     y    n  IETF-draft
+     IPv6 Intf. Addr.        232  y     y    n  IETF-draft
+     MT IP. Reach            235  n     y    n  IETF-draft
+     IPv6 IP. Reach          236  n     y    n  IETF-draft
+     MT IPv6 IP. Reach       237  n     y    n  IETF-draft
+     P2P Adjacency State     240  y     n    n  IETF-draft
+
+ */
+
+#define AREA_ADDRESSES            1
+#define IS_NEIGHBOURS             2
+#define ES_NEIGHBOURS             3
+#define PARTITION_DESIG_LEVEL2_IS 4
+#define PREFIX_NEIGHBOURS         5
+#define LAN_NEIGHBOURS            6
+#define PADDING                   8
+#define LSP_ENTRIES               9
+#define AUTH_INFO                 10
+#define CHECKSUM                  12
+#define TE_IS_NEIGHBOURS          22
+#define IPV4_INT_REACHABILITY     128
+#define IPV4_EXT_REACHABILITY     130
+#define PROTOCOLS_SUPPORTED       129
+#define IDRP_INFO                 131
+#define IPV4_ADDR                 132
+#define TE_ROUTER_ID              134
+#define TE_IPV4_REACHABILITY      135
+#define DYNAMIC_HOSTNAME          137
+#define IPV6_REACHABILITY         236
+#define IPV6_ADDR                 232
+#define WAY3_HELLO                240
+
+#define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5)
+#define LAN_NEIGHBOURS_LEN 6
+#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */
+#define IPV4_REACH_LEN 12
+#define IPV6_REACH_LEN 22
+
+/* struct for neighbor */
+struct is_neigh{
+  struct metric                        metrics;
+  u_char         neigh_id[ISIS_SYS_ID_LEN + 1];
+};
+
+/* struct for te is neighbor */
+struct te_is_neigh{
+  u_char         neigh_id[ISIS_SYS_ID_LEN + 1];
+  u_char                          te_metric[3];
+  u_char                       sub_tlvs_length;
+};
+
+/* struct for es neighbors */
+struct es_neigh{
+  struct metric                        metrics;
+  /* approximate position of first, we use the
+   * length ((uchar*)metric-1) to know all     */
+  u_char       first_es_neigh[ISIS_SYS_ID_LEN]; 
+                                                 
+};
+
+struct partition_desig_level2_is{
+  struct list                 *isis_system_ids;
+};
+
+/* struct for lan neighbors */
+struct lan_neigh{
+  u_char             LAN_addr[6];
+};
+
+/* struct for LSP entry */
+struct lsp_entry {
+  u_int16_t                  rem_lifetime;
+  u_char      lsp_id[ISIS_SYS_ID_LEN + 2];
+  u_int32_t                       seq_num;
+  u_int16_t                      checksum;
+} __attribute__((packed));
+
+/* struct for checksum */
+struct checksum {
+  u_int16_t checksum;
+};
+
+/* ipv4 reachability */
+struct ipv4_reachability {
+  struct metric metrics;
+  struct in_addr prefix;
+  struct in_addr   mask;
+};
+
+/* te router id */
+struct te_router_id {
+  struct in_addr     id;
+};
+
+/* te ipv4 reachability */
+struct te_ipv4_reachability {
+  u_int32_t    te_metric;
+  u_char         control;
+  u_char    prefix_start; /* since this is variable length by nature it only */
+};			  /* points to an approximate location */ 
+
+
+
+struct idrp_info {
+  u_char len;
+  u_char *value;
+};
+
+#ifdef HAVE_IPV6
+struct ipv6_reachability {
+  u_int32_t          metric;
+  u_char             control_info; 
+  u_char             prefix_len;
+  u_char             prefix[16];
+};
+#endif /* HAVE_IPV6 */
+
+/* bits in control_info */
+#define CTRL_INFO_DIRECTION    0x80
+#define DIRECTION_UP           0
+#define DIRECTION_DOWN         1
+#define CTRL_INFO_DISTRIBUTION 0x40
+#define DISTRIBUTION_INTERNAL  0
+#define DISTRIBUTION_EXTERNAL  1
+#define CTRL_INFO_SUBTLVS      0x20
+
+/*
+ * Pointer to each tlv type, filled by parse_tlvs()
+ */
+struct tlvs {
+  struct list                           *area_addrs;
+  struct list                            *is_neighs;
+  struct list                         *te_is_neighs;
+  struct list                            *es_neighs;
+  struct list                          *lsp_entries;
+  struct list                        *prefix_neighs;
+  struct list                           *lan_neighs;
+  struct checksum                         *checksum;
+  struct nlpids                             *nlpids;
+  struct list                           *ipv4_addrs;
+  struct list                      *ipv4_int_reachs;
+  struct list                      *ipv4_ext_reachs;
+  struct list                       *te_ipv4_reachs;
+  struct hostname                         *hostname;
+  struct te_router_id                    *router_id;
+#ifdef HAVE_IPV6
+  struct list                           *ipv6_addrs;
+  struct list                          *ipv6_reachs;
+#endif
+  struct isis_passwd                      auth_info;
+};
+
+/*
+ * Own definitions - used to bitmask found and expected
+ */
+
+#define TLVFLAG_AREA_ADDRS                (1<<0)
+#define TLVFLAG_IS_NEIGHS                 (1<<1)
+#define TLVFLAG_ES_NEIGHS                 (1<<2)
+#define TLVFLAG_PARTITION_DESIG_LEVEL2_IS (1<<3)
+#define TLVFLAG_PREFIX_NEIGHS             (1<<4)
+#define TLVFLAG_LAN_NEIGHS                (1<<5)
+#define TLVFLAG_LSP_ENTRIES               (1<<6)
+#define TLVFLAG_PADDING                   (1<<7)
+#define TLVFLAG_AUTH_INFO                 (1<<8)
+#define TLVFLAG_IPV4_INT_REACHABILITY     (1<<9)
+#define TLVFLAG_NLPID                     (1<<10)
+#define TLVFLAG_IPV4_EXT_REACHABILITY     (1<<11)
+#define TLVFLAG_IPV4_ADDR                 (1<<12)
+#define TLVFLAG_DYN_HOSTNAME              (1<<13)
+#define TLVFLAG_IPV6_ADDR                 (1<<14)
+#define TLVFLAG_IPV6_REACHABILITY         (1<<15)
+#define TLVFLAG_TE_IS_NEIGHS              (1<<16)
+#define TLVFLAG_TE_IPV4_REACHABILITY      (1<<17)
+#define TLVFLAG_3WAY_HELLO                (1<<18)
+#define TLVFLAG_TE_ROUTER_ID              (1<<19)
+#define TLVFLAG_CHECKSUM                  (1<<20)
+
+void init_tlvs  (struct tlvs *tlvs, uint32_t expected);
+void free_tlvs  (struct tlvs *tlvs);
+int  parse_tlvs (char *areatag, u_char *stream, int size, u_int32_t *expected, 
+                 u_int32_t *found, struct tlvs *tlvs);
+void free_tlv   (void *val);
+
+int tlv_add_area_addrs       (struct list *area_addrs, struct stream *stream);
+int tlv_add_is_neighs        (struct list *is_neighs, struct stream *stream);
+int tlv_add_lan_neighs       (struct list *lan_neighs, struct stream *stream);
+int tlv_add_nlpid            (struct nlpids *nlpids, struct stream *stream);
+int tlv_add_checksum         (struct checksum *checksum, 
+			      struct stream *stream);
+int tlv_add_authinfo         (char auth_type, char authlen, char *auth_value,
+			      struct stream *stream);
+int tlv_add_ip_addrs         (struct list *ip_addrs, struct stream *stream);
+int tlv_add_dynamic_hostname (struct hostname *hostname,struct stream *stream);
+int tlv_add_lsp_entries      (struct list *lsps, struct stream *stream);
+int tlv_add_ipv4_reachs      (struct list *ipv4_reachs, struct stream *stream);
+#ifdef HAVE_IPV6
+int tlv_add_ipv6_addrs       (struct list *ipv6_addrs, struct stream *stream);
+int tlv_add_ipv6_reachs      (struct list *ipv6_reachs, struct stream *stream);
+#endif /* HAVE_IPV6 */
+
+int tlv_add_padding          (struct stream *stream);
+
+#endif /* _ZEBRA_ISIS_TLV_H */
+
+
+
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
new file mode 100644
index 0000000..d9179f9
--- /dev/null
+++ b/isisd/isis_zebra.c
@@ -0,0 +1,592 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_zebra.c   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "thread.h"
+#include "command.h"
+#include "memory.h"
+#include "log.h"
+#include "if.h"
+#include "network.h"
+#include "prefix.h"
+#include "zclient.h"
+#include "stream.h"
+#include "linklist.h"
+
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_csm.h"
+#include "isisd/isis_route.h"
+#include "isisd/isis_zebra.h"
+
+struct zclient *zclient = NULL;
+
+extern struct thread_master *master;
+
+int 
+isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct interface *ifp;
+
+  ifp = zebra_interface_add_read (zclient->ibuf);
+  
+
+  zlog_info ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
+	     ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+  
+  if (if_is_up (ifp))
+    isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
+  
+  return 0;
+}
+
+int
+isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct interface *ifp;
+  struct stream *s;
+
+  s = zclient->ibuf;
+  ifp = zebra_interface_state_read (s);
+  
+  if (!ifp)
+    return 0;
+
+  if (if_is_up (ifp))
+    zlog_warn ("Zebra: got delete of %s, but interface is still up",
+               ifp->name);
+
+  zlog_info ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
+	     ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+
+  if_delete (ifp);
+  
+  isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), 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
+isis_zebra_if_state_up (int command, struct zclient *zclient, 
+			zebra_size_t length)
+{
+  struct interface *ifp;
+  
+  ifp = zebra_interface_if_lookup (zclient->ibuf);
+    
+  if (!ifp)
+    return 0;
+  
+  if (if_is_up (ifp)) {
+    zebra_interface_if_set_value (zclient->ibuf, ifp);
+    isis_circuit_update_params (circuit_scan_by_ifp (ifp), ifp);
+    return 0;
+  }
+  
+  zebra_interface_if_set_value (zclient->ibuf, ifp);
+  isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
+  
+  return 0;
+}
+
+
+int
+isis_zebra_if_state_down (int command, struct zclient *zclient, 
+			  zebra_size_t length)
+{
+  struct interface *ifp;
+  
+  ifp = zebra_interface_if_lookup (zclient->ibuf);
+  
+  if (ifp == NULL)
+    return 0;
+  
+  if (if_is_up (ifp)) {
+    zebra_interface_if_set_value (zclient->ibuf, ifp);
+    isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
+  }
+  
+  return 0;
+}
+
+int
+isis_zebra_if_address_add (int command, struct zclient *zclient, 
+                           zebra_size_t length)
+{
+  struct connected *c;
+  struct prefix *p;
+  u_char buf[BUFSIZ];
+
+  c = zebra_interface_address_add_read (zclient->ibuf);
+  
+  if (c == NULL)
+    return 0;
+  
+  p = c->address;
+  
+  prefix2str (p, buf, BUFSIZ);
+#ifdef EXTREME_DEBUG
+  if (p->family == AF_INET) 
+    zlog_info ("connected IP address %s", buf);
+#ifdef HAVE_IPV6
+  if (p->family == AF_INET6)
+    zlog_info ("connected IPv6 address %s", buf);
+#endif /* HAVE_IPV6 */
+#endif /* EXTREME_DEBUG */
+  isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp),  c);
+
+  return 0;
+}
+
+int
+isis_zebra_if_address_del (int command, struct zclient *client, 
+                           zebra_size_t length)
+{
+  struct connected *c;
+  struct interface *ifp;
+
+  c = zebra_interface_address_delete_read (zclient->ibuf);
+  
+  if (c == NULL)
+    return 0;
+  
+  ifp = c->ifp;
+  
+  connected_free (c);
+  
+  isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
+  
+  return 0;
+}
+
+void
+isis_zebra_route_add_ipv4 (struct prefix *prefix, 
+                           struct isis_route_info *route_info)
+{
+  u_char message, flags;
+  int psize;
+  struct stream *stream;
+  struct isis_nexthop *nexthop;
+  struct listnode *node;
+
+  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+    return;
+
+  if (zclient->redist[ZEBRA_ROUTE_ISIS]) {
+    message = 0;
+    flags = 0;
+    
+    SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
+    SET_FLAG (message, ZAPI_MESSAGE_METRIC);
+    SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
+    
+    stream = zclient->obuf;
+    stream_reset (stream);
+    /* Length place holder. */
+    stream_putw (stream, 0);
+    /* command */
+    stream_putc (stream, ZEBRA_IPV4_ROUTE_ADD);
+    /* type */
+    stream_putc (stream, ZEBRA_ROUTE_ISIS);
+    /* flags */
+    stream_putc (stream, flags);
+    /* message */
+    stream_putc (stream, message);
+    /* prefix information */
+    psize = PSIZE (prefix->prefixlen);
+    stream_putc (stream, prefix->prefixlen);
+    stream_write (stream, (u_char *)&prefix->u.prefix4, psize);      
+
+    stream_putc (stream, listcount (route_info->nexthops));
+    
+    /* Nexthop, ifindex, distance and metric information */
+    for (node = listhead (route_info->nexthops); node; nextnode (node)) {
+      nexthop = getdata (node);
+      /* FIXME: can it be ? */
+      if (nexthop->ip.s_addr != INADDR_ANY) {
+        stream_putc (stream, ZEBRA_NEXTHOP_IPV4);
+        stream_put_in_addr (stream, &nexthop->ip);
+      } else {
+        stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX);
+        stream_putl (stream, nexthop->ifindex);
+      }
+    }
+    if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
+      stream_putc (stream, route_info->depth);
+    if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
+      stream_putl (stream, route_info->cost);
+    
+    stream_putw_at (stream, 0, stream_get_endp (stream));
+    writen (zclient->sock, stream->data, stream_get_endp (stream));
+  }
+}
+
+void
+isis_zebra_route_del_ipv4 (struct prefix *prefix, 
+                           struct isis_route_info *route_info)
+{
+  struct zapi_ipv4 api;
+  struct prefix_ipv4 prefix4;
+  
+  if (zclient->redist[ZEBRA_ROUTE_ISIS]) {
+    api.type = ZEBRA_ROUTE_ISIS;
+    api.flags = 0;
+    api.message = 0;
+    prefix4.family = AF_INET;
+    prefix4.prefixlen = prefix->prefixlen;
+    prefix4.prefix = prefix->u.prefix4;
+    zapi_ipv4_delete (zclient, &prefix4, &api);
+  }
+  
+  return;
+}
+
+#ifdef HAVE_IPV6
+void
+isis_zebra_route_add_ipv6 (struct prefix *prefix,
+                           struct isis_route_info *route_info)
+{
+  struct zapi_ipv6 api;
+  struct in6_addr **nexthop_list;
+  unsigned int *ifindex_list;
+  struct isis_nexthop6 *nexthop6;
+  int i, size;
+  struct listnode *node;
+  struct prefix_ipv6 prefix6;
+
+  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+    return;
+  
+  api.type = ZEBRA_ROUTE_ISIS;
+  api.flags = 0;
+  api.message = 0;
+  SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+  SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
+  SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+  api.metric = route_info->cost;
+#if 0
+  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
+  api.distance = route_info->depth;
+#endif
+  api.nexthop_num = listcount (route_info->nexthops6);
+  api.ifindex_num = listcount (route_info->nexthops6);
+  
+  /* allocate memory for nexthop_list */
+  size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
+  nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
+  if (!nexthop_list) {
+    zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
+    return;
+  }
+  
+  /* allocate memory for ifindex_list */
+  size = sizeof (unsigned int) * listcount (route_info->nexthops6);
+  ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
+  if (!ifindex_list) {
+    zlog_err ("isis_zebra_add_route_ipv6: out of memory!");
+    XFREE (MTYPE_ISIS_TMP, nexthop_list);
+    return;
+  }
+  
+  /* for each nexthop */
+  i = 0;
+  for (node = listhead (route_info->nexthops6); node; nextnode (node)) {
+    nexthop6 = getdata (node);
+    
+    if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
+        !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6)) {
+      api.nexthop_num--;
+      api.ifindex_num--;
+      continue;
+    }
+    
+    nexthop_list[i] = &nexthop6->ip6;
+    ifindex_list[i] = nexthop6->ifindex;
+    i++;
+  }
+  
+  api.nexthop = nexthop_list;
+  api.ifindex = ifindex_list;
+  
+  if (api.nexthop_num && api.ifindex_num) {
+    prefix6.family = AF_INET6;
+    prefix6.prefixlen = prefix->prefixlen;
+    memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
+    zapi_ipv6_add (zclient, &prefix6, &api);
+    SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
+  }
+  
+  XFREE (MTYPE_ISIS_TMP, nexthop_list);
+  XFREE (MTYPE_ISIS_TMP, ifindex_list);
+  
+  return;
+}
+
+void
+isis_zebra_route_del_ipv6 (struct prefix *prefix, 
+                           struct isis_route_info *route_info)
+{
+  struct zapi_ipv6 api;
+  struct in6_addr **nexthop_list;
+  unsigned int *ifindex_list;
+  struct isis_nexthop6 *nexthop6;
+  int i, size;
+  struct listnode *node;
+  struct prefix_ipv6 prefix6;
+
+  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+    return;
+  
+  api.type = ZEBRA_ROUTE_ISIS;
+  api.flags = 0;
+  api.message = 0;
+  SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+  SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
+  api.nexthop_num = listcount (route_info->nexthops6);
+  api.ifindex_num = listcount (route_info->nexthops6);
+  
+  /* allocate memory for nexthop_list */
+  size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6);
+  nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size);
+  if (!nexthop_list) {
+    zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
+    return;
+  }
+  
+  /* allocate memory for ifindex_list */
+  size = sizeof (unsigned int) * listcount (route_info->nexthops6);
+  ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size);
+  if (!ifindex_list) {
+    zlog_err ("isis_zebra_route_del_ipv6: out of memory!");
+    XFREE (MTYPE_ISIS_TMP, nexthop_list);
+    return;
+  }
+  
+  /* for each nexthop */
+  i = 0;
+  for (node = listhead (route_info->nexthops6); node; nextnode (node)) {
+    nexthop6 = getdata (node);
+    
+    if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
+        !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6)) {
+      api.nexthop_num--;
+      api.ifindex_num--;
+      continue;
+    }
+    
+    nexthop_list[i] = &nexthop6->ip6;
+    ifindex_list[i] = nexthop6->ifindex;
+    i++;
+  }
+  
+  api.nexthop = nexthop_list;
+  api.ifindex = ifindex_list;
+  
+  if (api.nexthop_num && api.ifindex_num) {
+    prefix6.family = AF_INET6;
+    prefix6.prefixlen = prefix->prefixlen;
+    memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
+    zapi_ipv6_delete (zclient, &prefix6, &api);
+    UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
+  }
+  
+  XFREE (MTYPE_ISIS_TMP, nexthop_list);
+  XFREE (MTYPE_ISIS_TMP, ifindex_list);  
+}
+
+
+#endif /* HAVE_IPV6 */
+
+
+
+void
+isis_zebra_route_update (struct prefix *prefix,
+                         struct isis_route_info *route_info)
+{
+  if (zclient->sock < 0)
+    return;
+
+  if (!zclient->redist[ZEBRA_ROUTE_ISIS])
+    return;
+
+  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
+    if (prefix->family == AF_INET)
+      isis_zebra_route_add_ipv4 (prefix, route_info);
+#ifdef HAVE_IPV6
+    else if (prefix->family == AF_INET6)
+      isis_zebra_route_add_ipv6 (prefix, route_info);
+#endif /* HAVE_IPV6 */
+  } else { 
+    if (prefix->family == AF_INET)
+      isis_zebra_route_del_ipv4 (prefix, route_info);
+#ifdef HAVE_IPV6
+    else if (prefix->family == AF_INET6)
+      isis_zebra_route_del_ipv6 (prefix, route_info);
+#endif /* HAVE_IPV6 */
+  }
+  return;
+}
+
+
+int
+isis_zebra_read_ipv4 (int command, struct zclient *zclient, 
+		      zebra_size_t length)
+{
+  struct stream *stream;
+  struct zapi_ipv4 api;
+  struct prefix_ipv4 p;
+  unsigned long ifindex;
+  struct in_addr nexthop;
+
+  stream = zclient->ibuf;
+  memset (&p, 0, sizeof (struct prefix_ipv4));
+  ifindex = 0;
+
+  api.type    = stream_getc (stream);
+  api.flags   = stream_getc (stream);
+  api.message = stream_getc (stream);
+
+  p.family = AF_INET;
+  p.prefixlen = stream_getc (stream);
+  stream_get (&p.prefix, stream, PSIZE (p.prefixlen));
+  
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
+      api.nexthop_num = stream_getc (stream);
+      nexthop.s_addr = stream_get_ipv4 (stream);
+  }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
+    api.ifindex_num = stream_getc (stream);
+    ifindex = stream_getl (stream);
+  }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+    api.distance = stream_getc (stream);
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+    api.metric = stream_getl (stream);
+  else
+    api.metric = 0;
+  
+  if (command == ZEBRA_IPV4_ROUTE_ADD) {
+    zlog_info ("IPv4 Route add from Z");
+  }
+
+  return 0;
+}
+
+
+int 
+isis_zebra_read_ipv6 (int command, struct zclient *zclient, 
+		      zebra_size_t length)
+{
+
+  return 0;
+}
+
+#define ISIS_TYPE_IS_REDISTRIBUTED(T) \
+T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
+
+int
+isis_distribute_list_update (int routetype)
+{
+  return 0;
+}
+
+int
+isis_redistribute_default_set(int routetype, int metric_type, int metric_value)
+{
+  return 0;
+}
+
+
+void
+isis_zebra_init ()
+{
+  
+  zclient = zclient_new ();
+  zclient_init (zclient, ZEBRA_ROUTE_ISIS);
+  zclient->interface_add = isis_zebra_if_add;
+  zclient->interface_delete = isis_zebra_if_del;
+  zclient->interface_up = isis_zebra_if_state_up;
+  zclient->interface_down = isis_zebra_if_state_down;
+  zclient->interface_address_add = isis_zebra_if_address_add;
+  zclient->interface_address_delete = isis_zebra_if_address_del;
+  zclient->ipv4_route_add = isis_zebra_read_ipv4;
+  zclient->ipv4_route_delete = isis_zebra_read_ipv4;
+#ifdef HAVE_IPV6
+  zclient->ipv6_route_add = isis_zebra_read_ipv6;
+  zclient->ipv6_route_delete = isis_zebra_read_ipv6;
+#endif /* HAVE_IPV6 */
+
+  return;
+}
+
+void
+isis_zebra_finish ()
+{
+
+  zclient_stop (zclient);
+  zclient_free (zclient);
+  zclient = (struct zclient *) NULL;
+
+  return;
+}
+
+
+
+
+
+
+
diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h
new file mode 100644
index 0000000..fabf720
--- /dev/null
+++ b/isisd/isis_zebra.h
@@ -0,0 +1,33 @@
+/*
+ * IS-IS Rout(e)ing protocol - isis_zebra.h   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef _ZEBRA_ISIS_ZEBRA_H
+#define _ZEBRA_ISIS_ZEBRA_H
+
+extern struct zclient *zclient;
+
+void isis_zebra_init (void);
+void isis_zebra_finish (void);
+void isis_zebra_route_update (struct prefix *prefix, 
+                              struct isis_route_info *route_info);
+int isis_distribute_list_update (int routetype);
+
+#endif /* _ZEBRA_ISIS_ZEBRA_H */
diff --git a/isisd/isisd.c b/isisd/isisd.c
new file mode 100644
index 0000000..8794a12
--- /dev/null
+++ b/isisd/isisd.c
@@ -0,0 +1,1989 @@
+/*
+ * IS-IS Rout(e)ing protocol - isisd.c
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <string.h>
+#include <zebra.h>
+#include <net/ethernet.h>
+
+#include "thread.h"
+#include "vty.h"
+#include "command.h"
+#include "log.h"
+#include "memory.h"
+#include "linklist.h"
+#include "if.h"
+#include "hash.h"
+#include "stream.h"
+#include "prefix.h"
+#include "table.h"
+
+#include "isisd/dict.h"
+#include "isisd/include-netbsd/iso.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_dynhn.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_spf.h"
+#include "isisd/isis_route.h"
+#include "isisd/isis_zebra.h"
+#include "isisd/isis_events.h"
+
+#ifdef TOPOLOGY_GENERATE
+#include "spgrid.h"
+u_char DEFAULT_TOPOLOGY_BASEIS[6] = {0xFE, 0xED, 0xFE, 0xED, 0x00, 0x00};
+#endif /* TOPOLOGY_GENERATE */
+
+
+struct isis *isis = NULL;
+struct thread_master *master;
+
+
+void
+isis_new (unsigned long process_id)
+{
+  
+  isis = XMALLOC (MTYPE_ISIS, sizeof(struct isis));
+  bzero (isis, sizeof (struct isis));
+  /*
+   * Default values
+   */
+  isis->max_area_addrs = 3;
+
+  isis->process_id = process_id;
+  isis->area_list = list_new ();
+  isis->init_circ_list = list_new ();
+  isis->uptime = time (NULL);
+  isis->nexthops = list_new ();
+#ifdef HAVE_IPV6
+  isis->nexthops6 = list_new ();
+#endif /* HAVE_IPV6 */
+  /*
+   * uncomment the next line for full debugs
+   */
+   /* isis->debugs = 0xFFFF; */  
+}
+
+struct isis_area *
+isis_area_create ()
+{
+
+  struct isis_area *area;
+  
+  area = XMALLOC (MTYPE_ISIS_AREA, sizeof (struct isis_area));
+  memset (area, 0, sizeof (struct isis_area));
+
+  /*
+   * The first instance is level-1-2 rest are level-1, unless otherwise
+   * configured
+   */
+  if (listcount (isis->area_list) > 0)
+    area->is_type = IS_LEVEL_1;
+  else
+    area->is_type = IS_LEVEL_1_AND_2;
+  /*
+   * intialize the databases
+   */
+  area->lspdb[0] = lsp_db_init ();
+  area->lspdb[1] = lsp_db_init ();
+  
+  spftree_area_init (area);
+  area->route_table = route_table_init ();
+#ifdef HAVE_IPV6
+  area->route_table6 = route_table_init ();
+#endif /* HAVE_IPV6 */
+  area->circuit_list = list_new ();
+  area->area_addrs = list_new ();
+  area->t_tick = thread_add_timer (master, lsp_tick, area, 1);
+  area->flags.maxindex = -1;
+  /*
+   * Default values
+   */
+  area->max_lsp_lifetime[0] = MAX_AGE; /* 1200 */
+  area->max_lsp_lifetime[1] = MAX_AGE; /* 1200 */
+  area->lsp_gen_interval[0] = LSP_GEN_INTERVAL_DEFAULT;
+  area->lsp_gen_interval[1] = LSP_GEN_INTERVAL_DEFAULT;
+  area->lsp_refresh[0] = MAX_LSP_GEN_INTERVAL; /* 900 */
+  area->lsp_refresh[1] = MAX_LSP_GEN_INTERVAL; /* 900 */
+  area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
+  area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
+  area->dynhostname = 1;
+  area->lsp_frag_threshold = 90;
+#ifdef TOPOLOGY_GENERATE
+  memcpy (area->topology_baseis, DEFAULT_TOPOLOGY_BASEIS, ISIS_SYS_ID_LEN);
+#endif /* TOPOLOGY_GENERATE */
+
+  /* FIXME: Think of a better way... */
+  area->min_bcast_mtu = 1497;
+
+  return area;
+}
+
+struct isis_area *
+isis_area_lookup (char *area_tag)
+{
+  struct isis_area *area;
+  struct listnode *node;
+  
+  LIST_LOOP (isis->area_list, area, node)
+    if ((area->area_tag == NULL && area_tag == NULL) ||
+	(area->area_tag && area_tag && strcmp (area->area_tag, area_tag) == 0))
+      return area;
+  
+  return NULL;
+}
+
+int 
+isis_area_get (struct vty *vty, char *area_tag)
+{
+
+  struct isis_area *area;
+  
+  area = isis_area_lookup (area_tag);
+  
+  if (area) {
+    vty->node = ISIS_NODE;
+    vty->index = area;
+    return CMD_SUCCESS;
+  }
+  
+  area = isis_area_create ();
+  area->area_tag = strdup (area_tag);
+  listnode_add (isis->area_list, area);
+  
+  zlog_info ("new IS-IS area instance %s", area->area_tag);
+
+  vty->node = ISIS_NODE;
+  vty->index = area;
+  
+  return CMD_SUCCESS;
+}
+
+int
+isis_area_destroy (struct vty *vty, char *area_tag)
+{
+  
+  struct isis_area *area;
+  struct listnode *node;
+  struct isis_circuit *circuit;
+
+  area = isis_area_lookup (area_tag);
+  
+  if (area == NULL) {
+    vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  if (area->circuit_list) {
+    node = listhead (area->circuit_list);
+    while (node) {
+      circuit = getdata (node);
+      nextnode (node);
+      isis_circuit_del (circuit);
+    }
+    list_delete (area->circuit_list);
+  }
+  listnode_delete (isis->area_list, area);
+  if (area->t_tick)
+    thread_cancel (area->t_tick); 
+  if (area->t_remove_aged)
+    thread_cancel (area->t_remove_aged);
+  if (area->t_lsp_refresh[0])
+    thread_cancel (area->t_lsp_refresh[0]);
+  if (area->t_lsp_refresh[1])
+    thread_cancel (area->t_lsp_refresh[1]);
+
+  XFREE (MTYPE_ISIS_AREA, area);
+  
+  return CMD_SUCCESS;
+}
+
+int 
+area_net_title (struct vty *vty , char *net_title)
+{
+  
+  struct isis_area *area;
+  struct area_addr *addr;
+  struct area_addr *addrp;
+  struct listnode *node;
+
+  u_char buff[255];
+  area = vty->index;
+
+  if (!area) {
+    vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  /* We check that we are not over the maximal number of addresses */
+  if (listcount (area->area_addrs) >= isis->max_area_addrs) {
+    vty_out (vty, "Maximum of area addresses (%d) already reached %s",
+	     isis->max_area_addrs, VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  addr = XMALLOC (MTYPE_ISIS_AREA_ADDR, sizeof (struct area_addr));
+  addr->addr_len = dotformat2buff (buff, net_title);
+  memcpy (addr->area_addr, buff, addr->addr_len);
+#ifdef EXTREME_DEBUG
+  zlog_info ("added area address %s for area %s (address length %d)", 
+	     net_title, area->area_tag, addr->addr_len);
+#endif /* EXTREME_DEBUG */
+  if (addr->addr_len < 8 || addr->addr_len > 20) {
+    zlog_warn ("area address must be at least 8..20 octets long (%d)",
+	       addr->addr_len);
+    XFREE (MTYPE_ISIS_AREA_ADDR, addr);
+    return CMD_WARNING;
+  }
+
+  if (isis->sysid_set == 0) {
+    /*
+     * First area address - get the SystemID for this router
+     */
+    memcpy (isis->sysid, GETSYSID(addr, ISIS_SYS_ID_LEN), ISIS_SYS_ID_LEN);
+    isis->sysid_set = 1;
+    zlog_info ("Router has SystemID %s", sysid_print (isis->sysid));
+  } else {
+    /*
+     * Check that the SystemID portions match
+     */
+    if (memcmp (isis->sysid, GETSYSID(addr, ISIS_SYS_ID_LEN),
+		 ISIS_SYS_ID_LEN)) {
+      vty_out (vty, "System ID must not change when defining additional area"
+               " addresses%s", VTY_NEWLINE);
+      XFREE (MTYPE_ISIS_AREA_ADDR, addr);
+      return CMD_WARNING;
+    }
+
+    /* now we see that we don't already have this address */
+    LIST_LOOP (area->area_addrs, addrp, node) {
+      if ((addrp->addr_len+ ISIS_SYS_ID_LEN + 1) == (addr->addr_len)) {
+         if (!memcmp (addrp->area_addr, addr->area_addr,addr->addr_len)) {
+          XFREE (MTYPE_ISIS_AREA_ADDR, addr);
+          return CMD_SUCCESS; /* silent fail */
+        }
+      }
+    }
+
+  }
+  /*
+   * Forget the systemID part of the address
+   */
+  addr->addr_len -= (ISIS_SYS_ID_LEN + 1);
+  listnode_add (area->area_addrs, addr);
+
+  /* only now we can safely generate our LSPs for this area */
+  if (listcount(area->area_addrs) > 0) {
+    lsp_l1_generate (area);
+    lsp_l2_generate (area);
+  }
+
+  return CMD_SUCCESS;
+}
+
+int
+area_clear_net_title (struct vty *vty, char *net_title)
+{
+  struct isis_area *area;
+  struct area_addr  addr, *addrp = NULL;
+  struct listnode *node;
+  u_char buff[255];
+
+  area = vty->index;
+  if (!area) {
+    vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  addr.addr_len = dotformat2buff (buff, net_title);
+  if (addr.addr_len < 8 || addr.addr_len > 20) {
+    vty_out (vty, "Unsupported area address length %d, should be 8...20 %s", 
+	     addr.addr_len, VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  memcpy(addr.area_addr, buff, (int)addr.addr_len); 
+  
+  LIST_LOOP (area->area_addrs, addrp, node)
+    if (addrp->addr_len == addr.addr_len &&
+	!memcmp (addrp->area_addr, addr.area_addr, addr.addr_len))
+      break;
+  
+  if (!addrp) {
+    vty_out (vty, "No area address %s for area %s %s", net_title, 
+	     area->area_tag, VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  listnode_delete (area->area_addrs, addrp);
+  
+  return CMD_SUCCESS;
+}
+
+
+/*
+ * 'show clns neighbors' command
+ */
+
+int
+show_clns_neigh (struct vty *vty, char detail) 
+{
+  struct listnode *node_area, *node_circ;
+  struct isis_area *area;
+  struct isis_circuit *circuit;
+  struct list *db;
+  int i;
+
+  if (!isis) {
+    vty_out (vty, "IS-IS Routing Process not enabled%s", VTY_NEWLINE);
+    return CMD_SUCCESS;
+  }
+
+  for (node_area = listhead (isis->area_list); node_area;
+       nextnode (node_area)) {
+    area = getdata (node_area);
+    vty_out (vty, "Area %s:%s", area->area_tag, VTY_NEWLINE);
+
+    if (detail==ISIS_UI_LEVEL_BRIEF)
+      vty_out (vty, "  System Id           Interface   L  State        "
+               "Holdtime SNPA%s", VTY_NEWLINE);
+
+    for (node_circ = listhead (area->circuit_list); node_circ;
+         nextnode (node_circ)) {
+      circuit = getdata (node_circ);      
+      if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+        for (i = 0; i < 2; i++) {
+          db = circuit->u.bc.adjdb[i];
+          if (db && db->count) {
+            if (detail == ISIS_UI_LEVEL_BRIEF)
+              isis_adjdb_iterate (db, (void (*) (struct isis_adjacency *, 
+                                                 void *))
+                                  isis_adj_print_vty, vty);	  
+            if (detail == ISIS_UI_LEVEL_DETAIL)
+              isis_adjdb_iterate (db, (void (*) (struct isis_adjacency *, 
+                                                 void *))
+                                  isis_adj_print_vty_detail, vty);	  
+            if (detail == ISIS_UI_LEVEL_EXTENSIVE)
+              isis_adjdb_iterate (db, (void (*) (struct isis_adjacency *, 
+                                                  void *))
+                                   isis_adj_print_vty_extensive, vty);	  
+          }
+        }
+      } else if (circuit->circ_type == CIRCUIT_T_P2P && 
+                 circuit->u.p2p.neighbor) {
+        if (detail==ISIS_UI_LEVEL_BRIEF)
+	  isis_adj_p2p_print_vty (circuit->u.p2p.neighbor, vty);
+	if (detail==ISIS_UI_LEVEL_DETAIL)
+          isis_adj_p2p_print_vty_detail (circuit->u.p2p.neighbor, vty);
+        if (detail==ISIS_UI_LEVEL_EXTENSIVE)
+          isis_adj_p2p_print_vty_extensive (circuit->u.p2p.neighbor, vty);
+      }     
+    }
+  }
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_clns_neighbors,
+       show_clns_neighbors_cmd,
+       "show clns neighbors",
+       SHOW_STR
+       "clns network information\n"
+       "CLNS neighbor adjacencies\n")
+{
+  return show_clns_neigh(vty, ISIS_UI_LEVEL_BRIEF);
+}
+
+ALIAS (show_clns_neighbors,
+       show_isis_neighbors_cmd,
+       "show isis neighbors",
+       SHOW_STR
+       "IS-IS network information\n"
+       "IS-IS neighbor adjacencies\n")
+
+DEFUN (show_clns_neighbors_detail,
+       show_clns_neighbors_detail_cmd,
+       "show clns neighbors detail",
+       SHOW_STR
+       "clns network information\n"
+       "CLNS neighbor adjacencies\n"
+       "show detailed information\n")
+{
+  return show_clns_neigh(vty, ISIS_UI_LEVEL_DETAIL);
+}
+
+ALIAS (show_clns_neighbors_detail,
+       show_isis_neighbors_detail_cmd,
+       "show isis neighbors detail",
+       SHOW_STR
+       "IS-IS network information\n"
+       "IS-IS neighbor adjacencies\n"
+       "show detailed information\n")
+
+/*
+ * 'isis debug', 'show debugging'
+ */
+
+void
+print_debug (struct vty *vty, int flags, int onoff)
+{
+  char onoffs[4];
+  if (onoff)
+    strcpy (onoffs,"on");
+  else
+    strcpy (onoffs,"off");
+
+  if (flags & DEBUG_ADJ_PACKETS)
+    vty_out (vty,"IS-IS Adjacency related packets debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_CHECKSUM_ERRORS)
+    vty_out (vty,"IS-IS checksum errors debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_LOCAL_UPDATES)
+    vty_out (vty,"IS-IS local updates debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_PROTOCOL_ERRORS)
+    vty_out (vty,"IS-IS protocol errors debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_SNP_PACKETS)
+    vty_out (vty,"IS-IS CSNP/PSNP packets debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_SPF_EVENTS)
+    vty_out (vty,"IS-IS SPF events debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_SPF_STATS)
+    vty_out (vty,"IS-IS SPF Timing and Statistics Data debugging is %s%s", 
+             onoffs, VTY_NEWLINE);
+  if (flags & DEBUG_SPF_TRIGGERS)
+    vty_out (vty,"IS-IS SPF triggering events debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_UPDATE_PACKETS)
+    vty_out (vty,"IS-IS Update related packet debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_RTE_EVENTS)
+    vty_out (vty,"IS-IS Route related debuggin is %s%s", onoffs, 
+             VTY_NEWLINE);
+  if (flags & DEBUG_EVENTS)
+    vty_out (vty,"IS-IS Event debugging is %s%s", onoffs, 
+             VTY_NEWLINE);
+
+}
+
+DEFUN (show_debugging,
+       show_debugging_cmd,
+       "show debugging",
+       SHOW_STR
+       "State of each debugging option\n")
+{
+  vty_out (vty,"IS-IS:%s", VTY_NEWLINE);
+  print_debug (vty, isis->debugs, 1);
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_isis_adj,
+       debug_isis_adj_cmd,
+       "debug isis adj-packets",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Adjacency related packets\n"
+       )
+{
+  isis->debugs |= DEBUG_ADJ_PACKETS;
+  print_debug (vty,DEBUG_ADJ_PACKETS,1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_adj,
+       no_debug_isis_adj_cmd,
+       "no debug isis adj-packets",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Adjacency related packets\n"
+       )
+{
+
+  isis->debugs &= ~DEBUG_ADJ_PACKETS;
+  print_debug (vty, DEBUG_ADJ_PACKETS, 0);
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (debug_isis_csum,
+       debug_isis_csum_cmd,
+       "debug isis checksum-errors",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS LSP checksum errors\n"
+       )
+{
+  isis->debugs |= DEBUG_CHECKSUM_ERRORS;
+  print_debug (vty, DEBUG_CHECKSUM_ERRORS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_csum,
+       no_debug_isis_csum_cmd,
+       "no debug isis checksum-errors",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS LSP checksum errors\n"
+       )
+{
+  isis->debugs &= ~DEBUG_CHECKSUM_ERRORS;
+  print_debug (vty, DEBUG_CHECKSUM_ERRORS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_isis_lupd,
+       debug_isis_lupd_cmd,
+       "debug isis local-updates",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS local update packets\n"
+       )
+{
+  isis->debugs |= DEBUG_LOCAL_UPDATES;
+  print_debug (vty, DEBUG_LOCAL_UPDATES, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_lupd,
+       no_debug_isis_lupd_cmd,
+       "no debug isis local-updates",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS local update packets\n"
+       )
+{
+  isis->debugs &= ~DEBUG_LOCAL_UPDATES;
+  print_debug (vty, DEBUG_LOCAL_UPDATES , 0);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_isis_err,
+       debug_isis_err_cmd,
+       "debug isis protocol-errors",  
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS LSP protocol errors\n"
+       )
+{
+  isis->debugs |= DEBUG_PROTOCOL_ERRORS;
+  print_debug (vty, DEBUG_PROTOCOL_ERRORS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_err,
+       no_debug_isis_err_cmd,
+       "no debug isis protocol-errors",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS LSP protocol errors\n"
+       )
+{
+  isis->debugs &= ~DEBUG_PROTOCOL_ERRORS;
+  print_debug (vty, DEBUG_PROTOCOL_ERRORS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_isis_snp,
+       debug_isis_snp_cmd,
+       "debug isis snp-packets",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS CSNP/PSNP packets\n"
+       )
+{
+  isis->debugs |= DEBUG_SNP_PACKETS;
+  print_debug (vty, DEBUG_SNP_PACKETS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_snp,
+       no_debug_isis_snp_cmd,
+       "no debug isis snp-packets",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS CSNP/PSNP packets\n"
+       )
+{
+  isis->debugs &= ~DEBUG_SNP_PACKETS ;
+  print_debug (vty, DEBUG_SNP_PACKETS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+
+
+DEFUN (debug_isis_upd,
+       debug_isis_upd_cmd,
+       "debug isis update-packets",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Update related packets\n"
+       )
+{
+  isis->debugs |= DEBUG_UPDATE_PACKETS;
+  print_debug (vty, DEBUG_UPDATE_PACKETS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_upd,
+       no_debug_isis_upd_cmd,
+       "no debug isis update-packets",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Update related packets\n"
+       )
+{
+  isis->debugs &= ~DEBUG_UPDATE_PACKETS;
+  print_debug (vty, DEBUG_UPDATE_PACKETS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (debug_isis_spfevents,
+       debug_isis_spfevents_cmd,
+       "debug isis spf-events",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Shortest Path First Events\n"
+       )
+{
+  isis->debugs |= DEBUG_SPF_EVENTS;
+  print_debug (vty, DEBUG_SPF_EVENTS , 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_spfevents,
+       no_debug_isis_spfevents_cmd,
+       "no debug isis spf-events",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Shortest Path First Events\n"
+       )
+{
+  isis->debugs &= ~DEBUG_SPF_EVENTS;
+  print_debug (vty, DEBUG_SPF_EVENTS , 0);
+  
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (debug_isis_spfstats,
+       debug_isis_spfstats_cmd,
+       "debug isis spf-statistics ",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS SPF Timing and Statistic Data\n"
+       )
+{
+  isis->debugs |= DEBUG_SPF_STATS;
+  print_debug (vty, DEBUG_SPF_STATS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_spfstats,
+       no_debug_isis_spfstats_cmd,
+       "no debug isis spf-statistics",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS SPF Timing and Statistic Data\n"
+       )
+{
+  isis->debugs &= ~DEBUG_SPF_STATS;
+  print_debug (vty, DEBUG_SPF_STATS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_isis_spftrigg,
+       debug_isis_spftrigg_cmd,
+       "debug isis spf-triggers",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS SPF triggering events\n"
+       )
+{
+  isis->debugs |= DEBUG_SPF_TRIGGERS;
+  print_debug (vty, DEBUG_SPF_TRIGGERS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_spftrigg,
+       no_debug_isis_spftrigg_cmd,
+       "no debug isis spf-triggers",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS SPF triggering events\n"
+       )
+{
+  isis->debugs &= ~DEBUG_SPF_TRIGGERS;
+  print_debug (vty, DEBUG_SPF_TRIGGERS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_isis_rtevents,
+       debug_isis_rtevents_cmd,
+       "debug isis route-events",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Route related events\n"
+       )
+{
+  isis->debugs |= DEBUG_RTE_EVENTS;
+  print_debug (vty, DEBUG_RTE_EVENTS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_rtevents,
+       no_debug_isis_rtevents_cmd,
+       "no debug isis route-events",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Route related events\n"
+       )
+{
+  isis->debugs &= ~DEBUG_RTE_EVENTS;
+  print_debug (vty, DEBUG_RTE_EVENTS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_isis_events,
+       debug_isis_events_cmd,
+       "debug isis events",
+       DEBUG_STR
+       "IS-IS information\n"
+       "IS-IS  Events\n"
+       )
+{
+  isis->debugs |= DEBUG_EVENTS;
+  print_debug (vty, DEBUG_EVENTS, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_events,
+       no_debug_isis_events_cmd,
+       "no debug isis events",
+       UNDEBUG_STR
+       "IS-IS information\n"
+       "IS-IS Events\n"
+       )
+{
+  isis->debugs &= ~DEBUG_EVENTS;
+  print_debug (vty, DEBUG_EVENTS, 0);
+  
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (show_hostname,
+       show_hostname_cmd,
+       "show isis hostname",
+       SHOW_STR
+       "IS-IS information\n"
+       "IS-IS Dynamic hostname mapping\n")
+{
+  dynhn_print_all (vty);
+  
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (show_database,
+       show_database_cmd,
+       "show isis database",
+       SHOW_STR
+       "IS-IS information\n"
+       "IS-IS link state database\n")
+{
+  struct listnode *node;
+  struct isis_area *area;
+  int level,lsp_count;
+
+  if (isis->area_list->count == 0)
+    return CMD_SUCCESS;
+  
+  for (node = listhead (isis->area_list); node; nextnode (node)) {
+    area = getdata (node);
+    vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
+             VTY_NEWLINE);
+    for (level=0;level<ISIS_LEVELS;level++) {
+      if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0) {
+        vty_out (vty,"IS-IS Level-%d link-state database:%s", level+1, 
+                 VTY_NEWLINE);
+
+        lsp_count = lsp_print_all (vty, area->lspdb[level],
+				   ISIS_UI_LEVEL_BRIEF,
+				   area->dynhostname);
+
+	vty_out (vty,"%s    %u LSPs%s%s",
+		 VTY_NEWLINE,
+		 lsp_count,
+		 VTY_NEWLINE,
+		 VTY_NEWLINE);
+      }
+    }
+  }
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (show_database_detail,
+       show_database_detail_cmd,
+       "show isis database detail",
+       SHOW_STR
+       "IS-IS information\n"
+       "IS-IS link state database\n")
+{
+  struct listnode *node;
+  struct isis_area *area;
+  int level, lsp_count;
+
+  if (isis->area_list->count == 0)
+    return CMD_SUCCESS;
+
+  for (node = listhead (isis->area_list); node; nextnode (node)) {
+    area = getdata (node);
+    vty_out (vty, "Area %s:%s", area->area_tag ? area->area_tag : "null",
+             VTY_NEWLINE);
+    for (level=0;level<ISIS_LEVELS;level++) {
+      if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0) {
+        vty_out (vty,"IS-IS Level-%d Link State Database:%s", level+1, 
+                 VTY_NEWLINE);
+
+        lsp_count = lsp_print_all (vty, area->lspdb[level],
+				   ISIS_UI_LEVEL_DETAIL,
+				   area->dynhostname);
+
+	vty_out (vty,"%s    %u LSPs%s%s",
+		 VTY_NEWLINE,
+		 lsp_count,
+		 VTY_NEWLINE,
+		 VTY_NEWLINE);
+      }
+    }
+  }
+
+  return CMD_SUCCESS;
+}
+
+/* 
+ * 'router isis' command 
+ */
+DEFUN (router_isis,
+       router_isis_cmd,
+       "router isis WORD",
+        ROUTER_STR
+       "ISO IS-IS\n"
+       "ISO Routing area tag")
+{
+
+  return isis_area_get (vty, argv[0]);
+  
+}
+
+/* 
+ *'no router isis' command 
+ */
+DEFUN (no_router_isis,
+       no_router_isis_cmd,
+       "no router isis WORD",
+       "no\n"
+       ROUTER_STR
+       "ISO IS-IS\n"
+       "ISO Routing area tag")
+
+{
+  return isis_area_destroy (vty, argv[0]);
+}
+
+/*
+ * 'net' command
+ */
+DEFUN (net,
+       net_cmd,
+       "net WORD",
+       "A Network Entity Title for this process (OSI only)\n"
+       "XX.XXXX. ... .XXX.XX  Network entity title (NET)\n" )
+{
+  return area_net_title (vty, argv[0]);
+}
+
+
+/*
+ * 'no net' command
+ */
+DEFUN (no_net,
+       no_net_cmd,
+       "no net WORD",
+       NO_STR
+       "A Network Entity Title for this process (OSI only)\n"
+       "XX.XXXX. ... .XXX.XX  Network entity title (NET)\n" )
+{
+  return area_clear_net_title (vty, argv[0]);
+}
+
+DEFUN (area_passwd,
+       area_passwd_cmd,
+       "area-password WORD",
+       "Configure the authentication password for an area\n"
+       "Area password\n" )
+{
+  struct isis_area *area;
+  int len;
+
+  area = vty->index;
+
+  if (!area) {
+    vty_out (vty, "Cant find IS-IS instance%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  len = strlen (argv[0]);
+  if (len > 254) {
+    vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  area->area_passwd.len = (u_char)len;
+  area->area_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
+  strncpy (area->area_passwd.passwd, argv[0], 255);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_area_passwd,
+       no_area_passwd_cmd,
+       "no area-password",
+       NO_STR
+       "Configure the authentication password for an area\n")
+{
+  struct isis_area *area;
+  
+  area = vty->index;
+
+  if (!area) {
+    vty_out (vty, "Cant find IS-IS instance%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  memset (&area->area_passwd, 0, sizeof (struct isis_passwd));
+
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (domain_passwd,
+       domain_passwd_cmd,
+       "domain-password WORD",
+       "Set the authentication password for a routing domain\n"
+       "Routing domain password\n" )
+{
+  struct isis_area *area;
+  int len;
+
+  area = vty->index;
+
+  if (!area) {
+    vty_out (vty, "Cant find IS-IS instance%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+    
+  len = strlen (argv[0]);
+  if (len > 254) {
+    vty_out (vty, "Too long area password (>254)%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  area->domain_passwd.len = (u_char)len;
+  area->domain_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
+  strncpy (area->domain_passwd.passwd, argv[0], 255);
+  
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (no_domain_passwd,
+       no_domain_passwd_cmd,
+       "no domain-password WORD",
+       NO_STR
+       "Set the authentication password for a routing domain\n")
+{
+  struct isis_area *area;
+  
+  area = vty->index;
+
+  if (!area) {
+    vty_out (vty, "Cant find IS-IS instance%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+  
+  memset (&area->domain_passwd, 0, sizeof (struct isis_passwd));
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (is_type,
+       is_type_cmd,
+       "is-type (level-1|level-1-2|level-2-only)",
+       "IS Level for this routing process (OSI only)\n"
+       "Act as a station router only\n"
+       "Act as both a station router and an area router\n"
+       "Act as an area router only\n")
+{
+  struct isis_area *area;
+  int type;
+
+  area = vty->index;
+
+  if (!area) {
+    vty_out (vty, "Cant find IS-IS instance%s", VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  type = string2circuit_t (argv[0]); 
+  if (!type) {
+    vty_out (vty, "Unknown IS level %s", VTY_NEWLINE);
+    return CMD_SUCCESS;
+  }
+
+  isis_event_system_type_change (area, type);
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_is_type,
+       no_is_type_cmd,
+       "no is-type (level-1|level-1-2|level-2-only)",
+       NO_STR
+       "IS Level for this routing process (OSI only)\n"
+       "Act as a station router only\n"
+       "Act as both a station router and an area router\n"
+       "Act as an area router only\n")
+{
+  
+  struct isis_area *area;
+  int type;
+
+  area = vty->index;
+  assert (area);
+  
+  /*
+   * Put the is-type back to default. Which is level-1-2 on first
+   * circuit for the area level-1 for the rest
+   */
+  if (getdata (listhead (isis->area_list)) == area ) 
+    type = IS_LEVEL_1_AND_2;
+  else
+    type = IS_LEVEL_1;
+
+  isis_event_system_type_change (area, type);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (lsp_gen_interval,
+       lsp_gen_interval_cmd,
+       "lsp-gen-interval <1-120>",
+       "Minimum interval between regenerating same LSP\n"
+       "Minimum interval in seconds\n")
+{
+  struct isis_area *area;
+  uint16_t interval;
+
+  area = vty->index;
+  assert (area);
+  
+  interval = atoi (argv[0]);
+  area->lsp_gen_interval[0] = interval;
+  area->lsp_gen_interval[1] = interval;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_lsp_gen_interval,
+       no_lsp_gen_interval_cmd,
+       "no lsp-gen-interval",
+       NO_STR
+       "Minimum interval between regenerating same LSP\n"
+       )
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  
+  area->lsp_gen_interval[0] = LSP_GEN_INTERVAL_DEFAULT;
+  area->lsp_gen_interval[1] = LSP_GEN_INTERVAL_DEFAULT;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_lsp_gen_interval,
+       no_lsp_gen_interval_arg_cmd,
+       "no lsp-gen-interval <1-120>",
+       NO_STR
+       "Minimum interval between regenerating same LSP\n"
+       "Minimum interval in seconds\n"
+       )
+
+DEFUN (lsp_gen_interval_l1,
+       lsp_gen_interval_l1_cmd,
+       "lsp-gen-interval level-1 <1-120>",
+       "Minimum interval between regenerating same LSP\n"
+       "Set interval for level 1 only\n"
+       "Minimum interval in seconds\n"
+       )
+{
+  struct isis_area *area;
+  uint16_t interval;
+
+  area = vty->index;
+  assert (area);
+  
+  interval = atoi (argv[0]);
+  area->lsp_gen_interval[0] = interval;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_lsp_gen_interval_l1,
+       no_lsp_gen_interval_l1_cmd,
+       "no lsp-gen-interval level-1",
+       NO_STR
+       "Minimum interval between regenerating same LSP\n"
+       "Set interval for level 1 only\n"
+
+       )
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  
+  area->lsp_gen_interval[0] = LSP_GEN_INTERVAL_DEFAULT;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_lsp_gen_interval_l1,
+       no_lsp_gen_interval_l1_arg_cmd,
+       "no lsp-gen-interval level-1 <1-120>",
+       NO_STR
+       "Minimum interval between regenerating same LSP\n"
+       "Set interval for level 1 only\n"
+       "Minimum interval in seconds\n"
+       )
+
+
+DEFUN (lsp_gen_interval_l2,
+       lsp_gen_interval_l2_cmd,
+       "lsp-gen-interval level-2 <1-120>",
+       "Minimum interval between regenerating same LSP\n"
+       "Set interval for level 2 only\n"
+       "Minimum interval in seconds\n"
+       )
+{
+  struct isis_area *area;
+  int interval;
+
+  area = vty->index;
+  assert (area);
+  
+  interval = atoi (argv[0]);
+  area->lsp_gen_interval[1] = interval;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_lsp_gen_interval_l2,
+       no_lsp_gen_interval_l2_cmd,
+       "no lsp-gen-interval level-2",
+       NO_STR
+       "Minimum interval between regenerating same LSP\n"
+       "Set interval for level 2 only\n"
+       )
+{
+  struct isis_area *area;
+  int interval;
+
+  area = vty->index;
+  assert (area);
+  
+  interval = atoi (argv[0]);
+  area->lsp_gen_interval[1] = LSP_GEN_INTERVAL_DEFAULT;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_lsp_gen_interval_l2,
+       no_lsp_gen_interval_l2_arg_cmd,
+       "no lsp-gen-interval level-2 <1-120>",
+       NO_STR
+       "Minimum interval between regenerating same LSP\n"
+       "Set interval for level 2 only\n"
+       "Minimum interval in seconds\n"
+       )
+     
+
+DEFUN (metric_style,
+       metric_style_cmd,
+       "metric-style (narrow|wide)",
+       "Use old-style (ISO 10589) or new-style packet formats\n"
+       "Use old style of TLVs with narrow metric\n"
+       "Use new style of TLVs to carry wider metric\n")
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  if (!strcmp(argv[0],"wide"))
+    area->newmetric = 1;
+  else
+    area->newmetric = 0;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_metric_style,
+       no_metric_style_cmd,
+       "no metric-style (narrow|wide)",
+       NO_STR
+       "Use old-style (ISO 10589) or new-style packet formats\n"
+       "Use old style of TLVs with narrow metric\n"
+       "Use new style of TLVs to carry wider metric\n")
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+
+  if (!strcmp(argv[0],"wide"))
+    area->newmetric = 0;
+  else
+    area->newmetric = 1;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (dynamic_hostname,
+       dynamic_hostname_cmd,
+       "hostname dynamic",
+       "Dynamic hostname for IS-IS\n"
+       "Dynamic hostname\n") 
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  
+  area->dynhostname = 1;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_dynamic_hostname,
+       no_dynamic_hostname_cmd,
+       "no hostname dynamic",
+       NO_STR
+       "Dynamic hostname for IS-IS\n"
+       "Dynamic hostname\n") 
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  
+  area->dynhostname = 0;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (spf_interval,
+       spf_interval_cmd,
+       "spf-interval <1-120>",
+       "Minimum interval between SPF calculations"
+       "Minimum interval between consecutive SPFs in seconds\n")
+{
+  struct isis_area *area;
+  u_int16_t interval;
+  
+  area = vty->index;
+  interval = atoi (argv[0]);
+  area->min_spf_interval[0] = interval;
+  area->min_spf_interval[1] = interval;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_spf_interval,
+       no_spf_interval_cmd,
+       "no spf-interval",
+       NO_STR
+       "Minimum interval between SPF calculations\n"
+       )
+{
+  struct isis_area *area;
+  
+  area = vty->index;
+
+  area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
+  area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_spf_interval,
+       no_spf_interval_arg_cmd,
+       "no spf-interval <1-120>",
+       NO_STR
+       "Minimum interval between SPF calculations\n"
+       "Minimum interval between consecutive SPFs in seconds\n"
+       )
+
+DEFUN (spf_interval_l1,
+       spf_interval_l1_cmd,
+       "spf-interval level-1 <1-120>",
+       "Minimum interval between SPF calculations\n"
+       "Set interval for level 1 only\n"
+       "Minimum interval between consecutive SPFs in seconds\n")
+{
+  struct isis_area *area;
+  u_int16_t interval;
+  
+  area = vty->index;
+  interval = atoi (argv[0]);
+  area->min_spf_interval[0] = interval;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_spf_interval_l1,
+       no_spf_interval_l1_cmd,
+       "no spf-interval level-1",
+       NO_STR
+       "Minimum interval between SPF calculations\n"
+       "Set interval for level 1 only\n")
+{
+  struct isis_area *area;
+  
+  area = vty->index;
+
+  area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_spf_interval,
+       no_spf_interval_l1_arg_cmd,
+       "no spf-interval level-1 <1-120>",
+       NO_STR
+       "Minimum interval between SPF calculations\n"
+       "Set interval for level 1 only\n"
+       "Minimum interval between consecutive SPFs in seconds\n")
+
+DEFUN (spf_interval_l2,
+       spf_interval_l2_cmd,
+       "spf-interval level-2 <1-120>",
+       "Minimum interval between SPF calculations\n"
+       "Set interval for level 2 only\n"
+       "Minimum interval between consecutive SPFs in seconds\n")
+{
+  struct isis_area *area;
+  u_int16_t interval;
+  
+  area = vty->index;
+  interval = atoi (argv[0]);
+  area->min_spf_interval[1] = interval;
+  
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_spf_interval_l2,
+       no_spf_interval_l2_cmd,
+       "no spf-interval level-2",
+       NO_STR
+       "Minimum interval between SPF calculations\n"
+       "Set interval for level 2 only\n")
+{
+  struct isis_area *area;
+  
+  area = vty->index;
+
+  area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
+  
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_spf_interval,
+       no_spf_interval_l2_arg_cmd,
+       "no spf-interval level-2 <1-120>",
+       NO_STR
+       "Minimum interval between SPF calculations\n"
+       "Set interval for level 2 only\n"
+       "Minimum interval between consecutive SPFs in seconds\n")
+
+
+#ifdef TOPOLOGY_GENERATE
+DEFUN (topology_generate_grid,
+       topology_generate_grid_cmd,
+       "topology generate grid <1-100> <1-100> <1-65000> [param] [param] "
+       "[param]",
+       "Topology for IS-IS\n"
+       "Topology for IS-IS\n"
+       "Topology grid for IS-IS\n"
+       "X parameter of the grid\n"
+       "Y parameter of the grid\n"
+       "Random seed\n"
+       "Optional param 1\n"
+       "Optional param 2\n"
+       "Optional param 3\n"
+       "Topology\n")
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+
+  if (!spgrid_check_params (vty, argc, argv)) {
+    if (area->topology)
+      list_delete (area->topology);
+    area->topology = list_new();
+    memcpy(area->top_params,vty->buf,200);
+    gen_spgrid_topology (vty, area->topology);
+    remove_topology_lsps (area);
+    generate_topology_lsps (area);
+  }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_isis_topology,
+       show_isis_topology_cmd,
+       "show isis topology",
+       SHOW_STR
+       "clns network information\n"
+       "CLNS neighbor adjacencies\n")
+{
+  struct isis_area *area;
+  struct listnode *node;
+  struct listnode *node2;
+  struct arc *arc;
+  LIST_LOOP (isis->area_list, area, node) {
+    if (area->topology) {
+      vty_out (vty, "Topology for isis area:%s%s",area->area_tag, VTY_NEWLINE);
+      LIST_LOOP (area->topology, arc, node2) {
+        vty_out (vty, "a  %ld   %ld   %ld%s",arc->from_node, arc->to_node, 
+		 arc->distance, VTY_NEWLINE);
+      }
+    }
+  }
+  return CMD_SUCCESS;
+}
+
+/*
+ * 'topology base-is' command
+ */
+DEFUN (topology_baseis ,
+       topology_baseis_cmd,
+       "topology base-is WORD",
+       "Topology for IS-IS\n"
+       "Topology for IS-IS\n"
+       "A Network IS Base for this topology"
+       "XX.XXXX.XXXX.XX Network entity title (NET)\n" )
+{
+  struct isis_area *area;
+  u_char buff[ISIS_SYS_ID_LEN];
+
+  area = vty->index;
+  assert (area);
+
+  if (sysid2buff (buff, argv[0])) {
+    sysid2buff (area->topology_baseis, argv[0]);
+  }
+  
+  return CMD_SUCCESS;
+}
+
+/*
+ * 'no net' command
+ */
+DEFUN (no_topology_baseis,
+       no_topology_baseis_cmd,
+       "no topology base-is WORD",
+       NO_STR
+       "A Network Entity Title for this process (OSI only)"
+       "XX.XXXX. ... .XXX.XX  Network entity title (NET)\n" )
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+
+  memcpy(area->topology_baseis, DEFAULT_TOPOLOGY_BASEIS, ISIS_SYS_ID_LEN);
+  return CMD_SUCCESS;
+}
+
+#endif /* TOPOLOGY_GENERATE */
+
+DEFUN (lsp_lifetime,
+       lsp_lifetime_cmd,
+       "lsp-lifetime <380-65535>",
+       "Maximum LSP lifetime\n"
+       "LSP lifetime in seconds\n"
+       )
+{
+  struct isis_area *area;
+  uint16_t interval;
+
+  area = vty->index;
+  assert (area);
+  
+  interval = atoi (argv[0]);
+
+  if (interval < ISIS_MIN_LSP_LIFETIME) {
+    vty_out (vty, "LSP lifetime (%us) below %us%s",
+	     interval,
+	     ISIS_MIN_LSP_LIFETIME,
+	     VTY_NEWLINE);
+
+    return CMD_WARNING;
+  }
+
+
+  area->max_lsp_lifetime[0] = interval;
+  area->max_lsp_lifetime[1] = interval;
+  area->lsp_refresh[0] = interval-300;
+  area->lsp_refresh[1] = interval-300;
+
+  if (area->t_lsp_refresh[0]) {
+    thread_cancel (area->t_lsp_refresh[0]);
+    thread_execute (master, lsp_refresh_l1, area, 0);
+  }
+
+  if (area->t_lsp_refresh[1]) {
+    thread_cancel (area->t_lsp_refresh[1]);
+    thread_execute (master, lsp_refresh_l2, area, 0);
+  }
+
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_lsp_lifetime,
+       no_lsp_lifetime_cmd,
+       "no lsp-lifetime",
+       NO_STR
+       "LSP lifetime in seconds\n"
+       )
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  
+  area->max_lsp_lifetime[0] = MAX_AGE;          /* 1200s */
+  area->max_lsp_lifetime[1] = MAX_AGE;          /* 1200s */ 
+  area->lsp_refresh[0] = MAX_LSP_GEN_INTERVAL;  /*  900s */
+  area->lsp_refresh[1] = MAX_LSP_GEN_INTERVAL;  /*  900s */
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_lsp_lifetime,
+       no_lsp_lifetime_arg_cmd,
+       "no lsp-lifetime <380-65535>",
+       NO_STR
+       "Maximum LSP lifetime\n"
+       "LSP lifetime in seconds\n"
+       )
+
+DEFUN (lsp_lifetime_l1,
+       lsp_lifetime_l1_cmd,
+       "lsp-lifetime level-1 <380-65535>",
+       "Maximum LSP lifetime for Level 1 only\n"
+       "LSP lifetime for Level 1 only in seconds\n"
+       )
+{
+  struct isis_area *area;
+  uint16_t interval;
+
+  area = vty->index;
+  assert (area);
+  
+  interval = atoi (argv[0]);
+
+  if (interval < ISIS_MIN_LSP_LIFETIME) {
+    vty_out (vty, "Level-1 LSP lifetime (%us) below %us%s",
+	     interval,
+	     ISIS_MIN_LSP_LIFETIME,
+	     VTY_NEWLINE);
+
+    return CMD_WARNING;
+  }
+
+
+  area->max_lsp_lifetime[0] = interval;
+  area->lsp_refresh[0] = interval-300;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_lsp_lifetime_l1,
+       no_lsp_lifetime_l1_cmd,
+       "no lsp-lifetime level-1",
+       NO_STR
+       "LSP lifetime for Level 1 only in seconds\n"
+       )
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  
+  area->max_lsp_lifetime[0] = MAX_AGE;          /* 1200s */ 
+  area->lsp_refresh[0] = MAX_LSP_GEN_INTERVAL;  /*  900s */
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_lsp_lifetime_l1,
+       no_lsp_lifetime_l1_arg_cmd,
+       "no lsp-lifetime level-1 <380-65535>",
+       NO_STR
+       "Maximum LSP lifetime for Level 1 only\n"
+       "LSP lifetime for Level 1 only in seconds\n"
+       )
+
+DEFUN (lsp_lifetime_l2,
+       lsp_lifetime_l2_cmd,
+       "lsp-lifetime level-2 <380-65535>",
+       "Maximum LSP lifetime for Level 2 only\n"
+       "LSP lifetime for Level 2 only in seconds\n"
+       )
+{
+  struct isis_area *area;
+  uint16_t interval;
+
+  area = vty->index;
+  assert (area);
+  
+  interval = atoi (argv[0]);
+
+  if (interval < ISIS_MIN_LSP_LIFETIME) {
+    vty_out (vty, "Level-2 LSP lifetime (%us) below %us%s",
+	     interval,
+	     ISIS_MIN_LSP_LIFETIME,
+	     VTY_NEWLINE);
+
+    return CMD_WARNING;
+  }
+
+
+  area->max_lsp_lifetime[1] = interval;
+  area->lsp_refresh[1] = interval - 300;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_lsp_lifetime_l2,
+       no_lsp_lifetime_l2_cmd,
+       "no lsp-lifetime level-2",
+       NO_STR
+       "LSP lifetime for Level 2 only in seconds\n"
+       )
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  assert (area);
+  
+  area->max_lsp_lifetime[1] = MAX_AGE;          /* 1200s */ 
+  area->lsp_refresh[1] = MAX_LSP_GEN_INTERVAL;  /*  900s */
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_lsp_lifetime_l2,
+       no_lsp_lifetime_l2_arg_cmd,
+       "no lsp-lifetime level-2 <380-65535>",
+       NO_STR
+       "Maximum LSP lifetime for Level 2 only\n"
+       "LSP lifetime for Level 2 only in seconds\n"
+       )
+
+
+
+
+/* IS-IS configuration write function */
+int
+isis_config_write (struct vty *vty)
+{
+  int write = 0;
+  
+  if (isis != NULL) {
+    struct isis_area *area;
+    struct listnode *node;
+    struct listnode *node2;
+
+    LIST_LOOP (isis->area_list, area, node) {
+      /* ISIS - Area name */
+      vty_out (vty, "router isis %s%s",area->area_tag, VTY_NEWLINE);
+      write++;
+      /* ISIS - Net */
+      if (listcount (area->area_addrs) > 0) {
+        struct area_addr *area_addr;
+        LIST_LOOP (area->area_addrs, area_addr, node2) {
+          vty_out (vty, " net %s%s", 
+		   isonet_print (area_addr->area_addr, 
+				 area_addr->addr_len + ISIS_SYS_ID_LEN + 1), 
+		   VTY_NEWLINE);
+          write ++;
+        }
+      }
+      /* ISIS - Dynamic hostname - Defaults to true so only display if false*/
+      if (!area->dynhostname) {
+        vty_out (vty, " no hostname dynamic%s", VTY_NEWLINE);
+        write ++;
+      }
+      /* ISIS - Metric-Style - when true displays wide */
+      if (area->newmetric) {
+        vty_out (vty, " metric-style wide%s", VTY_NEWLINE);
+        write ++;
+      }
+      /* ISIS - Area is-type (level-1-2 is default) */
+      if (area->is_type  == IS_LEVEL_1) {
+        vty_out (vty, " is-type level-1%s", VTY_NEWLINE);
+        write ++;
+      } else {if (area->is_type  == IS_LEVEL_2) {
+        vty_out (vty, " is-type level-2-only%s", VTY_NEWLINE);
+        write ++;
+      }}
+      /* ISIS - Lsp generation interval */
+      if (area->lsp_gen_interval[0] ==  area->lsp_gen_interval[1]) {
+	if (area->lsp_gen_interval[0] != LSP_GEN_INTERVAL_DEFAULT) {
+	  vty_out (vty, " lsp-gen-interval %d%s", area->lsp_gen_interval[0], 
+                   VTY_NEWLINE);
+	  write ++;
+      }} else {
+        if (area->lsp_gen_interval[0] != LSP_GEN_INTERVAL_DEFAULT) {
+          vty_out (vty, " lsp-gen-interval level-1 %d%s", 
+                   area->lsp_gen_interval[0], VTY_NEWLINE);
+          write ++;
+        }
+        if (area->lsp_gen_interval[1] != LSP_GEN_INTERVAL_DEFAULT) {
+          vty_out (vty, " lsp-gen-interval level-2 %d%s", 
+                   area->lsp_gen_interval[1], VTY_NEWLINE);
+          write ++;
+        }
+      }
+      /* ISIS - LSP lifetime */
+      if (area->max_lsp_lifetime[0] == area->max_lsp_lifetime[1]) {
+	if (area->max_lsp_lifetime[0] != MAX_AGE) {
+	vty_out (vty, " lsp-lifetime %u%s", area->max_lsp_lifetime[0], 
+                 VTY_NEWLINE);
+	write ++;
+      }} else {
+	if (area->max_lsp_lifetime[0] != MAX_AGE) {
+	vty_out (vty, " lsp-lifetime level-1 %u%s", area->max_lsp_lifetime[0],
+                 VTY_NEWLINE);
+	write ++;
+	}
+	if (area->max_lsp_lifetime[1] != MAX_AGE) {
+	vty_out (vty, " lsp-lifetime level-2 %u%s", area->max_lsp_lifetime[1],
+                 VTY_NEWLINE);
+	write ++;
+	}
+      }     
+      #ifdef TOPOLOGY_GENERATE
+      /* seems we save the whole command line here */
+      if (area->top_params) {
+        vty_out (vty, " %s%s",area->top_params, VTY_NEWLINE);
+        write ++;
+      }
+
+      if (memcmp(area->topology_baseis, DEFAULT_TOPOLOGY_BASEIS, 
+		 ISIS_SYS_ID_LEN)) {
+        vty_out (vty, " topology base_is %s%s", 
+		 sysid_print (area->topology_baseis), VTY_NEWLINE);
+        write ++;
+      }
+
+      #endif /* TOPOLOGY_GENERATE */
+    }
+  }
+  
+  return write;
+}
+
+struct cmd_node isis_node =
+{
+  ISIS_NODE,
+  "%s(config_router)# ",
+  1
+};
+
+void 
+isis_init ()
+{
+
+  /* Install IS-IS top node */
+  install_node (&isis_node, isis_config_write);
+  
+  install_element (VIEW_NODE, &show_clns_neighbors_cmd);
+  install_element (VIEW_NODE, &show_isis_neighbors_cmd);
+  install_element (VIEW_NODE, &show_clns_neighbors_detail_cmd);
+  install_element (VIEW_NODE, &show_isis_neighbors_detail_cmd);
+
+  install_element (VIEW_NODE, &show_hostname_cmd);
+  install_element (VIEW_NODE, &show_database_cmd);
+  install_element (VIEW_NODE, &show_database_detail_cmd);
+
+  install_element (ENABLE_NODE, &show_clns_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_isis_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_clns_neighbors_detail_cmd);
+  install_element (ENABLE_NODE, &show_isis_neighbors_detail_cmd);
+
+  install_element (ENABLE_NODE, &show_hostname_cmd);
+  install_element (ENABLE_NODE, &show_database_cmd);
+  install_element (ENABLE_NODE, &show_database_detail_cmd);
+  install_element (ENABLE_NODE, &show_debugging_cmd);
+
+  install_element (ENABLE_NODE, &debug_isis_adj_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_adj_cmd);
+  install_element (ENABLE_NODE, &debug_isis_csum_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_csum_cmd);
+  install_element (ENABLE_NODE, &debug_isis_lupd_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_lupd_cmd);
+  install_element (ENABLE_NODE, &debug_isis_err_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_err_cmd);
+  install_element (ENABLE_NODE, &debug_isis_snp_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_snp_cmd);
+  install_element (ENABLE_NODE, &debug_isis_upd_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_upd_cmd);
+  install_element (ENABLE_NODE, &debug_isis_spfevents_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_spfevents_cmd);
+  install_element (ENABLE_NODE, &debug_isis_spfstats_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_spfstats_cmd);
+  install_element (ENABLE_NODE, &debug_isis_spftrigg_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_spftrigg_cmd);
+  install_element (ENABLE_NODE, &debug_isis_rtevents_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_rtevents_cmd);
+  install_element (ENABLE_NODE, &debug_isis_events_cmd);
+  install_element (ENABLE_NODE, &no_debug_isis_events_cmd);
+
+  install_element (CONFIG_NODE, &router_isis_cmd);
+  install_element (CONFIG_NODE, &no_router_isis_cmd);
+
+  install_default (ISIS_NODE);
+
+  install_element (ISIS_NODE, &net_cmd);
+  install_element (ISIS_NODE, &no_net_cmd);
+
+  install_element (ISIS_NODE, &is_type_cmd);
+  install_element (ISIS_NODE, &no_is_type_cmd);
+
+  install_element (ISIS_NODE, &area_passwd_cmd);
+  install_element (ISIS_NODE, &no_area_passwd_cmd);
+
+  install_element (ISIS_NODE, &domain_passwd_cmd);
+  install_element (ISIS_NODE, &no_domain_passwd_cmd);
+
+  install_element (ISIS_NODE, &lsp_gen_interval_cmd);
+  install_element (ISIS_NODE, &no_lsp_gen_interval_cmd);
+  install_element (ISIS_NODE, &no_lsp_gen_interval_arg_cmd);
+  install_element (ISIS_NODE, &lsp_gen_interval_l1_cmd);
+  install_element (ISIS_NODE, &no_lsp_gen_interval_l1_cmd);
+  install_element (ISIS_NODE, &no_lsp_gen_interval_l1_arg_cmd);
+  install_element (ISIS_NODE, &lsp_gen_interval_l2_cmd);
+  install_element (ISIS_NODE, &no_lsp_gen_interval_l2_cmd);
+  install_element (ISIS_NODE, &no_lsp_gen_interval_l2_arg_cmd);
+
+  install_element (ISIS_NODE, &spf_interval_cmd);
+  install_element (ISIS_NODE, &no_spf_interval_cmd);
+  install_element (ISIS_NODE, &no_spf_interval_arg_cmd);
+  install_element (ISIS_NODE, &spf_interval_l1_cmd);
+  install_element (ISIS_NODE, &no_spf_interval_l1_cmd);
+  install_element (ISIS_NODE, &no_spf_interval_l1_arg_cmd);
+  install_element (ISIS_NODE, &spf_interval_l2_cmd);
+  install_element (ISIS_NODE, &no_spf_interval_l2_cmd);
+  install_element (ISIS_NODE, &no_spf_interval_l2_arg_cmd);
+  
+  install_element (ISIS_NODE, &lsp_lifetime_cmd);
+  install_element (ISIS_NODE, &no_lsp_lifetime_cmd);
+  install_element (ISIS_NODE, &no_lsp_lifetime_arg_cmd);
+  install_element (ISIS_NODE, &lsp_lifetime_l1_cmd);
+  install_element (ISIS_NODE, &no_lsp_lifetime_l1_cmd);
+  install_element (ISIS_NODE, &no_lsp_lifetime_l1_arg_cmd);
+  install_element (ISIS_NODE, &lsp_lifetime_l2_cmd);
+  install_element (ISIS_NODE, &no_lsp_lifetime_l2_cmd);
+  install_element (ISIS_NODE, &no_lsp_lifetime_l2_arg_cmd);
+
+  install_element (ISIS_NODE, &dynamic_hostname_cmd);
+  install_element (ISIS_NODE, &no_dynamic_hostname_cmd);
+
+  install_element (ISIS_NODE, &metric_style_cmd);
+  install_element (ISIS_NODE, &no_metric_style_cmd);
+#ifdef TOPOLOGY_GENERATE
+  install_element (ISIS_NODE, &topology_generate_grid_cmd);
+  install_element (ISIS_NODE, &topology_baseis_cmd);
+  install_element (ISIS_NODE, &no_topology_baseis_cmd);
+  install_element (VIEW_NODE, &show_isis_topology_cmd);
+  install_element (ENABLE_NODE, &show_isis_topology_cmd);
+#endif /* TOPOLOGY_GENERATE */
+
+  isis_new(0);
+  isis_circuit_init ();
+  isis_zebra_init ();
+  isis_spf_cmds_init ();
+}
+
+
+
+
+
+
diff --git a/isisd/isisd.conf.sample b/isisd/isisd.conf.sample
new file mode 100644
index 0000000..9e08778
--- /dev/null
+++ b/isisd/isisd.conf.sample
@@ -0,0 +1,39 @@
+! -*- isis -*-
+!
+! ISISd sample configuration file
+!
+!
+!
+hostname isisd 
+password foo
+enable password foo
+!log stdout 
+log file /tmp/isisd.log
+! 
+! 
+! 
+router isis DEAD
+  net 47.0023.0000.0003.0300.0100.0102.0304.0506.00
+!  is-type level-1
+
+!  -- set the lifetime either for level-1, level-2 or both
+!  lsp-lifetime level-1 65535
+!  lsp-lifetime level-2 65535
+!  lsp-lifetime 65535
+
+interface eth0
+ ip router isis DEAD
+ ip address 10.101.43.194
+ isis hello-interval 10000 
+! isis lsp-interval 1000
+
+! -- optional
+! isis circuit-type level-1
+! isis password lallaa level-1 
+! isis metric 1 level-1
+! isis csnp-interval 5 level-1
+! isis retransmit-interval 10
+! isis retransmit-throttle-interval
+! isis hello-multiplier 2 level-1
+!
+! 
diff --git a/isisd/isisd.h b/isisd/isisd.h
new file mode 100644
index 0000000..67bf8d6
--- /dev/null
+++ b/isisd/isisd.h
@@ -0,0 +1,147 @@
+/*
+ * IS-IS Rout(e)ing protocol - isisd.h   
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef ISISD_H
+#define ISISD_H
+
+#define ISISD_VERSION "0.0.7"
+#define ISIS_VTYSH_PATH        "/tmp/.isisd"
+
+/* uncomment if you are a developer in bug hunt */
+/* #define EXTREME_DEBUG  */
+/* #define EXTREME_TLV_DEBUG */
+
+/* If you want topology stuff compiled in */
+/* #define TOPOLOGY_GENERATE */
+
+struct rmap{
+  char *name;
+  struct route_map *map;
+};
+
+struct isis
+{
+  u_long process_id;
+  int sysid_set;
+  u_char sysid[ISIS_SYS_ID_LEN];    /* SystemID for this IS */
+  struct list *area_list;           /* list of IS-IS areas */
+  struct list *init_circ_list;
+  struct list *nexthops;            /* IPv4 next hops from this IS */
+#ifdef HAVE_IPV6
+  struct list  *nexthops6;          /* IPv6 next hops from this IS */
+#endif /* HAVE_IPV6 */
+  u_char max_area_addrs;            /* maximumAreaAdresses */
+  struct area_addr *man_area_addrs; /* manualAreaAddresses */
+  u_int32_t debugs;                 /* bitmap for debug */
+  time_t uptime;                    /* when did we start */
+  
+  /* Redistributed external information. */
+  struct route_table *external_info[ZEBRA_ROUTE_MAX + 1];
+  /* Redistribute metric info. */
+  struct {
+    int type;                   /* Internal or External  */
+    int value;                  /* metric value */
+  } dmetric [ZEBRA_ROUTE_MAX + 1];
+
+  struct {
+    char *name;
+    struct route_map *map;
+  } rmap [ZEBRA_ROUTE_MAX + 1];
+#ifdef HAVE_IPV6
+  struct {
+    struct {
+      char *name;
+      struct route_map *map;
+    } rmap [ZEBRA_ROUTE_MAX + 1];
+  } inet6_afmode;
+#endif
+};
+
+struct isis_area 
+{
+  struct isis *isis;                          /* back pointer */
+  dict_t *lspdb[ISIS_LEVELS];                 /* link-state dbs */
+  struct isis_spftree *spftree[ISIS_LEVELS];  /* The v4 SPTs */
+  struct route_table *route_table;            /* IPv4 routes */
+#ifdef HAVE_IPV6
+  struct isis_spftree *spftree6[ISIS_LEVELS]; /* The v4 SPTs */
+  struct route_table *route_table6;           /* IPv6 routes */
+#endif
+  int min_bcast_mtu;
+  struct list *circuit_list;                  /* IS-IS circuits */
+  struct flags flags;                        
+  struct thread *t_tick;                      /* LSP walker */
+  struct thread *t_remove_aged;              
+  int lsp_regenerate_pending[ISIS_LEVELS];
+  struct thread *t_lsp_refresh[ISIS_LEVELS];
+  
+  /*
+   * Configurables 
+   */
+  struct isis_passwd area_passwd;
+  struct isis_passwd domain_passwd;
+  /* do we support dynamic hostnames?  */
+  char dynhostname;
+  /* do we support new style metrics?  */
+  char newmetric;  
+  /* identifies the routing instance   */
+  char *area_tag;  
+  /* area addresses for this area      */
+  struct list *area_addrs;  
+  u_int16_t max_lsp_lifetime[ISIS_LEVELS];         
+  char is_type;  /* level-1 level-1-2 or level-2-only */
+  u_int16_t lsp_refresh[ISIS_LEVELS];
+  /* minimum time allowed before lsp retransmission */
+  u_int16_t lsp_gen_interval[ISIS_LEVELS];
+  /* min interval between between consequtive SPFs */
+  u_int16_t min_spf_interval[ISIS_LEVELS]; 
+  /* the percentage of LSP mtu size used, before generating a new frag */
+  int lsp_frag_threshold; 
+  int ip_circuits;
+#ifdef HAVE_IPV6
+  int ipv6_circuits;
+#endif /* HAVE_IPV6 */
+  /* Counters */
+  u_int32_t circuit_state_changes;
+#ifdef TOPOLOGY_GENERATE
+  struct list                   *topology;
+  char   topology_baseis[ISIS_SYS_ID_LEN]; /* is for the first is emulated  */
+  char                    top_params[200]; /* FIXME: what is reasonable?    */
+#endif /* TOPOLOGY_GENERATE */
+};
+
+void isis_init(void);
+struct isis_area *isis_area_lookup (char *);
+
+#define DEBUG_ADJ_PACKETS                (1<<0)
+#define DEBUG_CHECKSUM_ERRORS            (1<<1)
+#define DEBUG_LOCAL_UPDATES              (1<<2)
+#define DEBUG_PROTOCOL_ERRORS            (1<<3)
+#define DEBUG_SNP_PACKETS                (1<<4)
+#define DEBUG_UPDATE_PACKETS             (1<<5)
+#define DEBUG_SPF_EVENTS                 (1<<6)
+#define DEBUG_SPF_STATS                  (1<<7)
+#define DEBUG_SPF_TRIGGERS               (1<<8)
+#define DEBUG_RTE_EVENTS                 (1<<9)
+#define DEBUG_EVENTS                     (1<<10)
+
+#endif /* ISISD_H */
diff --git a/isisd/iso_checksum.c b/isisd/iso_checksum.c
new file mode 100644
index 0000000..d0bb8a7
--- /dev/null
+++ b/isisd/iso_checksum.c
@@ -0,0 +1,192 @@
+/*
+ * IS-IS Rout(e)ing protocol - iso_checksum.c
+ *                             ISO checksum related routines
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <zebra.h>
+#include "iso_checksum.h"
+
+/*
+ * Calculations of the OSI checksum.
+ * ISO/IEC 8473 defines the sum as
+ *
+ *     L
+ *  sum  a (mod 255) = 0
+ *     1  i
+ *
+ *     L 
+ *  sum (L-i+1)a (mod 255) = 0
+ *     1        i
+ *
+ */
+
+/*
+ * Verifies that the checksum is correct.
+ * Return 0 on correct and 1 on invalid checksum.
+ * Based on Annex C.4 of ISO/IEC 8473
+ * FIXME: Check for overflow 
+ */
+
+int
+iso_csum_verify (u_char *buffer, int len, uint16_t *csum)
+{ 
+  u_int8_t *p;
+  u_int32_t c0;
+  u_int32_t c1;
+  u_int16_t checksum;
+  int i;
+
+  p = buffer;
+  checksum = 0;
+  c0 = *csum & 0xff00;
+  c1 = *csum & 0x00ff;
+
+  /*
+   * If both are zero return correct
+   */
+  if (c0 == 0 && c1 == 0)
+    return 0;
+
+  /*
+   * If either, but not both are zero return incorrect
+   */
+  if (c0 == 0 || c1 == 0)
+    return 1;
+  
+  /*
+   * Otherwise initialize to zero and calculate...
+   */
+  c0 = 0;
+  c1 = 0;
+
+  for (i = 0; i < len; i++) {
+    c0 = c0 + *(p++);
+    c1 += c0;
+  }
+
+  c0 = c0 % 255;
+  c1 = c1 % 255;
+  
+  if ( c0 == 0 && c1 == 0)
+    return 0;
+
+  return 1;
+}
+
+
+/*
+ * Creates the checksum. *csum points to the position of the checksum in the 
+ * PDU. 
+ * Based on Annex C.4 of ISO/IEC 8473
+ * we will not overflow until about length of 6000,
+ * which is the answer to (255+255n)*n/2 > 2^32
+ * so if we have a length of over 5000 we will return zero (for now)
+ */
+#define FIXED_CODE
+u_int16_t
+iso_csum_create (u_char *buffer, int len, u_int16_t n)
+{
+
+  u_int8_t *p;
+  int x;
+  int y;
+  u_int32_t mul;
+  u_int32_t c0;
+  u_int32_t c1;
+  u_int16_t checksum;
+  u_int16_t  *csum;
+  int i;
+
+  checksum = 0;
+
+  /*
+   * Zero the csum in the packet.
+   */
+  csum = (u_int16_t*)(buffer + n);
+  *(csum) = checksum;
+
+  /* for the limitation of our implementation */
+  if (len > 5000) {
+    return 0;
+  }
+
+  p = buffer;
+  c0 = 0;
+  c1 = 0;
+
+  for (i = 0; i < len; i++) {
+    c0 = c0 + *(p++);
+    c1 += c0;
+  }
+
+  c0 = c0 % 255;
+  c1 = c1 % 255;
+
+  mul = (len - n)*(c0);
+  
+#ifdef FIXED_CODE
+  x = mul - c0 - c1;
+  y = c1 - mul - 1;
+
+  if ( y >= 0 ) y++;
+  if ( x < 0 ) x--;
+
+  x %= 255;
+  y %= 255;
+
+  if (x == 0) x = 255;
+  if (y == 0) y = 255;
+
+  x &= 0x00FF;
+
+  checksum = ((y << 8) | x);
+
+#else
+  x = mul - c0 - c1;
+  x %= 255;
+
+  y = c1 - mul - 1;
+  y %= 255;
+
+  if (x == 0) x = 255;
+  if (y == 0) y = 255;
+
+  checksum = ((y << 8) | x);
+#endif
+  
+  /*
+   * Now we write this to the packet
+   */
+  *(csum) = checksum;
+
+  /* return the checksum for user usage */
+  return checksum;
+}
+
+
+int
+iso_csum_modify (u_char *buffer, int len, uint16_t *csum)
+{
+  
+  return 0;
+}
+
+
diff --git a/isisd/iso_checksum.h b/isisd/iso_checksum.h
new file mode 100644
index 0000000..cf600a8
--- /dev/null
+++ b/isisd/iso_checksum.h
@@ -0,0 +1,29 @@
+/*
+ * IS-IS Rout(e)ing protocol - iso_checksum.c
+ *                             ISO checksum related routines
+ *
+ * Copyright (C) 2001,2002   Sampo Saaristo
+ *                           Tampere University of Technology      
+ *                           Institute of Communications Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef _ZEBRA_ISO_CSUM_H
+#define _ZEBRA_ISO_CSUM_H
+
+int iso_csum_verify (u_char *buffer, int len, uint16_t *csum);
+u_int16_t iso_csum_create (u_char *buffer, int len, u_int16_t n);
+
+#endif /* _ZEBRA_ISO_CSUM_H */
diff --git a/isisd/modified/Makefile.am b/isisd/modified/Makefile.am
new file mode 100644
index 0000000..65ba16b
--- /dev/null
+++ b/isisd/modified/Makefile.am
@@ -0,0 +1,17 @@
+## Process this file with automake to produce Makefile.in.
+
+SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @ISISD@ \
+	@VTYSH@ doc
+
+EXTRA_DIST = aclocal.m4 SERVICES TODO REPORTING-BUGS vtysh/Makefile.in \
+	vtysh/Makefile.am update-autotools
+
+dist-hook:
+	mkdir $(distdir)/tools
+	cp -p $(srcdir)/tools/*.pl $(distdir)/tools
+	cp -p $(srcdir)/tools/*.el $(distdir)/tools
+	cp -p $(srcdir)/tools/*.cgi $(distdir)/tools
+	mkdir $(distdir)/init
+	mkdir $(distdir)/init/redhat
+	cp -p $(srcdir)/init/redhat/*.init $(distdir)/init/redhat
+	cp -p $(srcdir)/init/redhat/zebra.* $(distdir)/init/redhat
diff --git a/isisd/modified/Makefile.in b/isisd/modified/Makefile.in
new file mode 100644
index 0000000..6e13617
--- /dev/null
+++ b/isisd/modified/Makefile.in
@@ -0,0 +1,462 @@
+# Makefile.in generated by automake 1.6.2 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@
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+AMTAR = @AMTAR@
+AR = @AR@
+AWK = @AWK@
+BGPD = @BGPD@
+CC = @CC@
+CPP = @CPP@
+CURSES = @CURSES@
+DEPDIR = @DEPDIR@
+IF_METHOD = @IF_METHOD@
+IF_PROC = @IF_PROC@
+INCLUDES = @INCLUDES@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPFORWARD = @IPFORWARD@
+ISISD = @ISISD@
+KERNEL_METHOD = @KERNEL_METHOD@
+LIBPAM = @LIBPAM@
+LIB_IPV6 = @LIB_IPV6@
+LIB_REGEX = @LIB_REGEX@
+MULTIPATH_NUM = @MULTIPATH_NUM@
+OSPF6D = @OSPF6D@
+OSPFD = @OSPFD@
+OTHER_METHOD = @OTHER_METHOD@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+RIPD = @RIPD@
+RIPNGD = @RIPNGD@
+RTREAD_METHOD = @RTREAD_METHOD@
+RT_METHOD = @RT_METHOD@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VTYSH = @VTYSH@
+ZEBRA = @ZEBRA@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+
+SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @ISISD@ \
+	@VTYSH@ doc
+
+
+EXTRA_DIST = aclocal.m4 SERVICES TODO REPORTING-BUGS vtysh/Makefile.in \
+	vtysh/Makefile.am update-autotools
+
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
+	uninstall-info-recursive all-recursive install-data-recursive \
+	install-exec-recursive installdirs-recursive install-recursive \
+	uninstall-recursive check-recursive installcheck-recursive
+DIST_COMMON = README AUTHORS COPYING COPYING.LIB ChangeLog INSTALL \
+	Makefile.am Makefile.in NEWS TODO acconfig.h aclocal.m4 \
+	config.guess config.h.in config.sub configure configure.in \
+	depcomp install-sh missing mkinstalldirs
+DIST_SUBDIRS = $(SUBDIRS)
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)
+
+$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+$(srcdir)/configure:  $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+	cd $(srcdir) && $(AUTOCONF)
+
+$(ACLOCAL_M4):  configure.in 
+	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+
+$(srcdir)/config.h.in:  $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/acconfig.h
+	cd $(top_srcdir) && $(AUTOHEADER)
+	touch $(srcdir)/config.h.in
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@set fnord $$MAKEFLAGS; amf=$$2; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	   || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+
+ETAGS = etags
+ETAGSFLAGS =
+
+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: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(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
+
+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
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = .
+distdir = $(PACKAGE)-$(VERSION)
+
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+
+GZIP_ENV = --best
+distcleancheck_listfiles = find . -type f -print
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	mkdir $(distdir)
+	$(mkinstalldirs) $(distdir)/vtysh
+	@list='$(DISTFILES)'; for file in $$list; do \
+	  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
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d $(distdir)/$$subdir \
+	    || mkdir $(distdir)/$$subdir \
+	    || exit 1; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$(top_distdir)" \
+	        distdir=../$(distdir)/$$subdir \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="${top_distdir}" distdir="$(distdir)" \
+	  dist-hook
+	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r $(distdir)
+dist-gzip: distdir
+	$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+dist dist-all: distdir
+	$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	$(am__remove_distdir)
+	GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf -
+	chmod -R a-w $(distdir); chmod a+w $(distdir)
+	mkdir $(distdir)/=build
+	mkdir $(distdir)/=inst
+	chmod a-w $(distdir)
+	dc_install_base=`$(am__cd) $(distdir)/=inst && pwd` \
+	  && cd $(distdir)/=build \
+	  && ../configure --srcdir=.. --prefix=$$dc_install_base \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \
+	      || { echo "ERROR: files left after uninstall:" ; \
+	           find $$dc_install_base -type f -print ; \
+	           exit 1; } >&2 ) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \
+	  && rm -f $(distdir).tar.gz \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+	$(am__remove_distdir)
+	@echo "$(distdir).tar.gz is ready for distribution" | \
+	  sed 'h;s/./=/g;p;x;p;x'
+distcleancheck: distclean
+	if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+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-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf autom4te.cache
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \
+	clean-generic clean-recursive dist dist-all dist-gzip distcheck \
+	distclean distclean-generic distclean-hdr distclean-recursive \
+	distclean-tags distcleancheck distdir dvi dvi-am dvi-recursive \
+	info info-am info-recursive install install-am install-data \
+	install-data-am install-data-recursive install-exec \
+	install-exec-am install-exec-recursive install-info \
+	install-info-am install-info-recursive install-man \
+	install-recursive install-strip installcheck installcheck-am \
+	installdirs installdirs-am installdirs-recursive \
+	maintainer-clean maintainer-clean-generic \
+	maintainer-clean-recursive mostlyclean mostlyclean-generic \
+	mostlyclean-recursive tags tags-recursive uninstall \
+	uninstall-am uninstall-info-am uninstall-info-recursive \
+	uninstall-recursive
+
+
+dist-hook:
+	mkdir $(distdir)/tools
+	cp -p $(srcdir)/tools/*.pl $(distdir)/tools
+	cp -p $(srcdir)/tools/*.el $(distdir)/tools
+	cp -p $(srcdir)/tools/*.cgi $(distdir)/tools
+	mkdir $(distdir)/init
+	mkdir $(distdir)/init/redhat
+	cp -p $(srcdir)/init/redhat/*.init $(distdir)/init/redhat
+	cp -p $(srcdir)/init/redhat/zebra.* $(distdir)/init/redhat
+# 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/isisd/modified/README b/isisd/modified/README
new file mode 100644
index 0000000..0b29953
--- /dev/null
+++ b/isisd/modified/README
@@ -0,0 +1,4 @@
+cp config.h.in acconfig.h configure.in Makefile.am Makefile.in configure ../../
+cp command.h command.c memory.c memory.h log.h log.c vty.c ../../lib/
+cp thread.h thread.c zebra.h ../../lib
+cp rib.c ../../zebra/
diff --git a/isisd/modified/acconfig.h b/isisd/modified/acconfig.h
new file mode 100644
index 0000000..002666b
--- /dev/null
+++ b/isisd/modified/acconfig.h
@@ -0,0 +1,162 @@
+/* accconfig.h -- `autoheader' will generate config.h.in for zebra.
+   Copyright (C) 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org> */
+
+/* Version of GNU Zebra */
+#undef VERSION
+
+/* Solaris on x86. */
+#undef SOLARIS_X86
+
+/* Package name of GNU Zebra */
+#undef PACKAGE
+
+/* Define if host is GNU/Linux */
+#undef GNU_LINUX
+
+/* Define if you have the AF_ROUTE socket.  */
+#undef HAVE_AF_ROUTE
+
+/* Define if you have the inet_aton function.  */
+#undef HAVE_INET_ATON
+
+/* Define if you have the inet_ntop function.  */
+#undef HAVE_INET_NTOP
+
+/* Define if you have the inet_pton function.  */
+#undef HAVE_INET_PTON
+
+/* Define if you have the setproctitle function.  */
+#undef HAVE_SETPROCTITLE
+
+/* Define if you have ipv6 stack.  */
+#undef HAVE_IPV6
+
+/* Define if you wish to support ipv6 router advertisment.  */
+/* #undef HAVE_RTADV */
+
+/* whether system has GNU regex */
+#undef HAVE_GNU_REGEX
+
+/* whether system has SNMP library */
+#undef HAVE_SNMP
+
+/* whether sockaddr has a sa_len field */
+#undef HAVE_SA_LEN
+
+/* whether sockaddr_in has a sin_len field */
+#undef HAVE_SIN_LEN
+
+/* whether sockaddr_un has a sun_len field */
+#undef HAVE_SUN_LEN
+
+/* whether sockaddr_in6 has a sin6_scope_id field */
+#undef HAVE_SIN6_SCOPE_ID
+
+/* Define if there is socklen_t. */
+#undef HAVE_SOCKLEN_T
+
+/* Define if there is sockaddr_dl structure. */
+#undef HAVE_SOCKADDR_DL
+
+/* Define if there is ifaliasreq structure. */
+#undef HAVE_IFALIASREQ
+
+/* Define if there is in6_aliasreq structure. */
+#undef HAVE_IN6_ALIASREQ
+
+/* Define if there is rt_addrinfo structure. */
+#undef HAVE_RT_ADDRINFO
+
+/* Define if there is in_pktinfo structure. */
+#undef HAVE_INPKTINFO
+
+/* Define if you have the getrusage function. */
+#undef HAVE_RUSAGE
+
+/* Define if /proc/net/dev exists. */
+#undef HAVE_PROC_NET_DEV
+
+/* Define if /proc/net/if_inet6 exists. */
+#undef HAVE_PROC_NET_IF_INET6
+
+/* Define if NET_RT_IFLIST exists in sys/socket.h. */
+#undef HAVE_NET_RT_IFLIST
+
+/* Define if you have INRIA ipv6 stack.  */
+#undef INRIA_IPV6
+
+/* Define if you have KAME project ipv6 stack.  */
+#undef KAME
+
+/* Define if you have Linux ipv6 stack.  */
+#undef LINUX_IPV6
+
+/* Define if you have NRL ipv6 stack.  */
+#undef NRL
+
+/* Define if you have BSDI NRL IPv6 stack. */
+#undef BSDI_NRL
+
+/* Define if one-vty option is specified. */
+#undef VTYSH
+
+/* Define if interface aliases don't have distinct indeces */
+#undef HAVE_BROKEN_ALIASES
+
+/* Define if disable-bgp-announce option is specified. */
+#undef DISABLE_BGP_ANNOUNCE
+
+/* PAM support */
+#undef USE_PAM
+
+/* TCP/IP communication between zebra and protocol daemon. */
+#undef HAVE_TCP_ZEBRA
+
+/* The OSPF NSSA option (RFC1587). */
+#undef HAVE_NSSA
+
+/* The OSPF Opaque LSA option (RFC2370). */
+#undef HAVE_OPAQUE_LSA
+
+/* Traffic Engineering Extension to OSPF
+   (draft-katz-yeung-ospf-traffic-06.txt). */
+#undef HAVE_OSPF_TE
+
+/* Linux netlink. */
+#undef HAVE_NETLINK
+
+/* PATHS */
+#undef PATH_ZEBRA_PID
+#undef PATH_RIPD_PID
+#undef PATH_RIPNGD_PID
+#undef PATH_BGPD_PID
+#undef PATH_OSPFD_PID
+#undef PATH_OSPF6D_PID
+#undef PATH_ISISD_PID
+
+/* Define if Solaris */
+#undef SUNOS_5
+
+/* Define if FreeBSD 3.2 */
+#undef FREEBSD_32
+
+/* Define if OpenBSD */
+#undef OPEN_BSD
+
+#ifdef HAVE_IPV6
+#ifdef KAME
+#ifndef INET6
+#define INET6
+#endif /* INET6 */
+#endif /* KAME */
+#endif /* HAVE_IPV6 */
+
+#ifdef SUNOS_5
+typedef unsigned int u_int32_t; 
+typedef unsigned short u_int16_t; 
+typedef unsigned short u_int8_t; 
+#endif /* SUNOS_5 */
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif /* HAVE_SOCKLEN_T */
diff --git a/isisd/modified/command.c b/isisd/modified/command.c
new file mode 100644
index 0000000..5c18fd9
--- /dev/null
+++ b/isisd/modified/command.c
@@ -0,0 +1,2983 @@
+/* Command interpreter routine for virtual terminal [aka TeletYpe]
+   Copyright (C) 1997, 98, 99 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.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "memory.h"
+#include "log.h"
+#include "version.h"
+
+/* Command vector which includes some level of command lists. Normally
+   each daemon maintains each own cmdvec. */
+vector cmdvec;
+
+/* Host information structure. */
+struct host host;
+
+/* Default motd string. */
+char *default_motd = 
+"\r\n\
+Hello, this is zebra (version " ZEBRA_VERSION ").\r\n\
+Copyright 1996-2002 Kunihiro Ishiguro.\r\n\
+\r\n";
+
+/* Standard command node structures. */
+struct cmd_node auth_node =
+{
+  AUTH_NODE,
+  "Password: ",
+};
+
+struct cmd_node view_node =
+{
+  VIEW_NODE,
+  "%s> ",
+};
+
+struct cmd_node auth_enable_node =
+{
+  AUTH_ENABLE_NODE,
+  "Password: ",
+};
+
+struct cmd_node enable_node =
+{
+  ENABLE_NODE,
+  "%s# ",
+};
+
+struct cmd_node config_node =
+{
+  CONFIG_NODE,
+  "%s(config)# ",
+  1
+};
+
+/* Utility function to concatenate argv argument into a single string
+   with inserting ' ' character between each argument.  */
+char *
+argv_concat (char **argv, int argc, int shift)
+{
+  int i;
+  int len;
+  int index;
+  char *str;
+
+  str = NULL;
+  index = 0;
+
+  for (i = shift; i < argc; i++)
+    {
+      len = strlen (argv[i]);
+
+      if (i == shift)
+	{
+	  str = XSTRDUP (MTYPE_TMP, argv[i]);
+	  index = len;
+	}
+      else
+	{
+	  str = XREALLOC (MTYPE_TMP, str, (index + len + 2));
+	  str[index++] = ' ';
+	  memcpy (str + index, argv[i], len);
+	  index += len;
+	  str[index] = '\0';
+	}
+    }
+  return str;
+}
+
+/* Install top node of command vector. */
+void
+install_node (struct cmd_node *node, 
+	      int (*func) (struct vty *))
+{
+  vector_set_index (cmdvec, node->node, node);
+  node->func = func;
+  node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
+}
+
+/* Compare two command's string.  Used in sort_node (). */
+int
+cmp_node (const void *p, const void *q)
+{
+  struct cmd_element *a = *(struct cmd_element **)p;
+  struct cmd_element *b = *(struct cmd_element **)q;
+
+  return strcmp (a->string, b->string);
+}
+
+int
+cmp_desc (const void *p, const void *q)
+{
+  struct desc *a = *(struct desc **)p;
+  struct desc *b = *(struct desc **)q;
+
+  return strcmp (a->cmd, b->cmd);
+}
+
+/* Sort each node's command element according to command string. */
+void
+sort_node ()
+{
+  int i, j;
+  struct cmd_node *cnode;
+  vector descvec;
+  struct cmd_element *cmd_element;
+
+  for (i = 0; i < vector_max (cmdvec); i++) 
+    if ((cnode = vector_slot (cmdvec, i)) != NULL)
+      {	
+	vector cmd_vector = cnode->cmd_vector;
+	qsort (cmd_vector->index, cmd_vector->max, sizeof (void *), cmp_node);
+
+	for (j = 0; j < vector_max (cmd_vector); j++)
+	  if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
+	    {
+	      descvec = vector_slot (cmd_element->strvec,
+				     vector_max (cmd_element->strvec) - 1);
+	      qsort (descvec->index, descvec->max, sizeof (void *), cmp_desc);
+	    }
+      }
+}
+
+/* Breaking up string into each command piece. I assume given
+   character is separated by a space character. Return value is a
+   vector which includes char ** data element. */
+vector
+cmd_make_strvec (char *string)
+{
+  char *cp, *start, *token;
+  int strlen;
+  vector strvec;
+  
+  if (string == NULL)
+    return NULL;
+  
+  cp = string;
+
+  /* Skip white spaces. */
+  while (isspace ((int) *cp) && *cp != '\0')
+    cp++;
+
+  /* Return if there is only white spaces */
+  if (*cp == '\0')
+    return NULL;
+
+  if (*cp == '!' || *cp == '#')
+    return NULL;
+
+  /* Prepare return vector. */
+  strvec = vector_init (VECTOR_MIN_SIZE);
+
+  /* Copy each command piece and set into vector. */
+  while (1) 
+    {
+      start = cp;
+      while (!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') &&
+	     *cp != '\0')
+	cp++;
+      strlen = cp - start;
+      token = XMALLOC (MTYPE_STRVEC, strlen + 1);
+      memcpy (token, start, strlen);
+      *(token + strlen) = '\0';
+      vector_set (strvec, token);
+
+      while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r') &&
+	     *cp != '\0')
+	cp++;
+
+      if (*cp == '\0')
+	return strvec;
+    }
+}
+
+/* Free allocated string vector. */
+void
+cmd_free_strvec (vector v)
+{
+  int i;
+  char *cp;
+
+  if (!v)
+    return;
+
+  for (i = 0; i < vector_max (v); i++)
+    if ((cp = vector_slot (v, i)) != NULL)
+      XFREE (MTYPE_STRVEC, cp);
+
+  vector_free (v);
+}
+
+/* Fetch next description.  Used in cmd_make_descvec(). */
+char *
+cmd_desc_str (char **string)
+{
+  char *cp, *start, *token;
+  int strlen;
+  
+  cp = *string;
+
+  if (cp == NULL)
+    return NULL;
+
+  /* Skip white spaces. */
+  while (isspace ((int) *cp) && *cp != '\0')
+    cp++;
+
+  /* Return if there is only white spaces */
+  if (*cp == '\0')
+    return NULL;
+
+  start = cp;
+
+  while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
+    cp++;
+
+  strlen = cp - start;
+  token = XMALLOC (MTYPE_STRVEC, strlen + 1);
+  memcpy (token, start, strlen);
+  *(token + strlen) = '\0';
+
+  *string = cp;
+
+  return token;
+}
+
+/* New string vector. */
+vector
+cmd_make_descvec (char *string, char *descstr)
+{
+  int multiple = 0;
+  char *sp;
+  char *token;
+  int len;
+  char *cp;
+  char *dp;
+  vector allvec;
+  vector strvec = NULL;
+  struct desc *desc;
+
+  cp = string;
+  dp = descstr;
+
+  if (cp == NULL)
+    return NULL;
+
+  allvec = vector_init (VECTOR_MIN_SIZE);
+
+  while (1)
+    {
+      while (isspace ((int) *cp) && *cp != '\0')
+	cp++;
+
+      if (*cp == '(')
+	{
+	  multiple = 1;
+	  cp++;
+	}
+      if (*cp == ')')
+	{
+	  multiple = 0;
+	  cp++;
+	}
+      if (*cp == '|')
+	{
+	  if (! multiple)
+	    {
+	      fprintf (stderr, "Command parse error!: %s\n", string);
+	      exit (1);
+	    }
+	  cp++;
+	}
+      
+      while (isspace ((int) *cp) && *cp != '\0')
+	cp++;
+
+      if (*cp == '(')
+	{
+	  multiple = 1;
+	  cp++;
+	}
+
+      if (*cp == '\0') 
+	return allvec;
+
+      sp = cp;
+
+      while (! (isspace ((int) *cp) || *cp == '\r' || *cp == '\n' || *cp == ')' || *cp == '|') && *cp != '\0')
+	cp++;
+
+      len = cp - sp;
+
+      token = XMALLOC (MTYPE_STRVEC, len + 1);
+      memcpy (token, sp, len);
+      *(token + len) = '\0';
+
+      desc = XCALLOC (MTYPE_DESC, sizeof (struct desc));
+      desc->cmd = token;
+      desc->str = cmd_desc_str (&dp);
+
+      if (multiple)
+	{
+	  if (multiple == 1)
+	    {
+	      strvec = vector_init (VECTOR_MIN_SIZE);
+	      vector_set (allvec, strvec);
+	    }
+	  multiple++;
+	}
+      else
+	{
+	  strvec = vector_init (VECTOR_MIN_SIZE);
+	  vector_set (allvec, strvec);
+	}
+      vector_set (strvec, desc);
+    }
+}
+
+/* Count mandantory string vector size.  This is to determine inputed
+   command has enough command length. */
+int
+cmd_cmdsize (vector strvec)
+{
+  int i;
+  char *str;
+  int size = 0;
+  vector descvec;
+
+  for (i = 0; i < vector_max (strvec); i++)
+    {
+      descvec = vector_slot (strvec, i);
+
+      if (vector_max (descvec) == 1)
+	{
+	  struct desc *desc = vector_slot (descvec, 0);
+
+	  str = desc->cmd;
+	  
+	  if (str == NULL || CMD_OPTION (str))
+	    return size;
+	  else
+	    size++;
+	}
+      else
+	size++;
+    }
+  return size;
+}
+
+/* Return prompt character of specified node. */
+char *
+cmd_prompt (enum node_type node)
+{
+  struct cmd_node *cnode;
+
+  cnode = vector_slot (cmdvec, node);
+  return cnode->prompt;
+}
+
+/* Install a command into a node. */
+void
+install_element (enum node_type ntype, struct cmd_element *cmd)
+{
+  struct cmd_node *cnode;
+
+  cnode = vector_slot (cmdvec, ntype);
+
+  if (cnode == NULL) 
+    {
+      fprintf (stderr, "Command node %d doesn't exist, please check it\n",
+	       ntype);
+      exit (1);
+    }
+
+  vector_set (cnode->cmd_vector, cmd);
+
+  cmd->strvec = cmd_make_descvec (cmd->string, cmd->doc);
+  cmd->cmdsize = cmd_cmdsize (cmd->strvec);
+}
+
+static unsigned char itoa64[] =	
+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void
+to64(char *s, long v, int n)
+{
+  while (--n >= 0) 
+    {
+      *s++ = itoa64[v&0x3f];
+      v >>= 6;
+    }
+}
+
+char *zencrypt (char *passwd)
+{
+  char salt[6];
+  struct timeval tv;
+  char *crypt (const char *, const char *);
+
+  gettimeofday(&tv,0);
+  
+  to64(&salt[0], random(), 3);
+  to64(&salt[3], tv.tv_usec, 3);
+  salt[5] = '\0';
+
+  return crypt (passwd, salt);
+}
+
+/* This function write configuration of this host. */
+int
+config_write_host (struct vty *vty)
+{
+  if (host.name)
+    vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE);
+
+  if (host.encrypt)
+    {
+      if (host.password_encrypt)
+        vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE); 
+      if (host.enable_encrypt)
+        vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE); 
+    }
+  else
+    {
+      if (host.password)
+        vty_out (vty, "password %s%s", host.password, VTY_NEWLINE);
+      if (host.enable)
+        vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE);
+    }
+
+  if (host.logfile)
+    vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE);
+
+  if (host.log_stdout)
+    vty_out (vty, "log stdout%s", VTY_NEWLINE);
+
+  if (host.log_syslog)
+    vty_out (vty, "log syslog%s", VTY_NEWLINE);
+
+  if (zlog_default->maskpri != LOG_DEBUG)
+    vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], VTY_NEWLINE);
+
+  if (zlog_default->record_priority == 1)
+    vty_out (vty, "log record-priority%s", VTY_NEWLINE);
+
+  if (host.advanced)
+    vty_out (vty, "service advanced-vty%s", VTY_NEWLINE);
+
+  if (host.encrypt)
+    vty_out (vty, "service password-encryption%s", VTY_NEWLINE);
+
+  if (host.lines >= 0)
+    vty_out (vty, "service terminal-length %d%s", host.lines,
+	     VTY_NEWLINE);
+
+  if (! host.motd)
+    vty_out (vty, "no banner motd%s", VTY_NEWLINE);
+
+  return 1;
+}
+
+/* Utility function for getting command vector. */
+vector
+cmd_node_vector (vector v, enum node_type ntype)
+{
+  struct cmd_node *cnode = vector_slot (v, ntype);
+  return cnode->cmd_vector;
+}
+
+/* Filter command vector by symbol */
+int
+cmd_filter_by_symbol (char *command, char *symbol)
+{
+  int i, lim;
+
+  if (strcmp (symbol, "IPV4_ADDRESS") == 0)
+    {
+      i = 0;
+      lim = strlen (command);
+      while (i < lim)
+	{
+	  if (! (isdigit ((int) command[i]) || command[i] == '.' || command[i] == '/'))
+	    return 1;
+	  i++;
+	}
+      return 0;
+    }
+  if (strcmp (symbol, "STRING") == 0)
+    {
+      i = 0;
+      lim = strlen (command);
+      while (i < lim)
+	{
+	  if (! (isalpha ((int) command[i]) || command[i] == '_' || command[i] == '-'))
+	    return 1;
+	  i++;
+	}
+      return 0;
+    }
+  if (strcmp (symbol, "IFNAME") == 0)
+    {
+      i = 0;
+      lim = strlen (command);
+      while (i < lim)
+	{
+	  if (! isalnum ((int) command[i]))
+	    return 1;
+	  i++;
+	}
+      return 0;
+    }
+  return 0;
+}
+
+/* Completion match types. */
+enum match_type 
+{
+  no_match,
+  extend_match,
+  ipv4_prefix_match,
+  ipv4_match,
+  ipv6_prefix_match,
+  ipv6_match,
+  range_match,
+  vararg_match,
+  partly_match,
+  exact_match 
+};
+
+enum match_type
+cmd_ipv4_match (char *str)
+{
+  char *sp;
+  int dots = 0, nums = 0;
+  char buf[4];
+
+  if (str == NULL)
+    return partly_match;
+
+  for (;;)
+    {
+      memset (buf, 0, sizeof (buf));
+      sp = str;
+      while (*str != '\0')
+	{
+	  if (*str == '.')
+	    {
+	      if (dots >= 3)
+		return no_match;
+
+	      if (*(str + 1) == '.')
+		return no_match;
+
+	      if (*(str + 1) == '\0')
+		return partly_match;
+
+	      dots++;
+	      break;
+	    }
+	  if (!isdigit ((int) *str))
+	    return no_match;
+
+	  str++;
+	}
+
+      if (str - sp > 3)
+	return no_match;
+
+      strncpy (buf, sp, str - sp);
+      if (atoi (buf) > 255)
+	return no_match;
+
+      nums++;
+
+      if (*str == '\0')
+	break;
+
+      str++;
+    }
+
+  if (nums < 4)
+    return partly_match;
+
+  return exact_match;
+}
+
+enum match_type
+cmd_ipv4_prefix_match (char *str)
+{
+  char *sp;
+  int dots = 0;
+  char buf[4];
+
+  if (str == NULL)
+    return partly_match;
+
+  for (;;)
+    {
+      memset (buf, 0, sizeof (buf));
+      sp = str;
+      while (*str != '\0' && *str != '/')
+	{
+	  if (*str == '.')
+	    {
+	      if (dots == 3)
+		return no_match;
+
+	      if (*(str + 1) == '.' || *(str + 1) == '/')
+		return no_match;
+
+	      if (*(str + 1) == '\0')
+		return partly_match;
+
+	      dots++;
+	      break;
+	    }
+
+	  if (!isdigit ((int) *str))
+	    return no_match;
+
+	  str++;
+	}
+
+      if (str - sp > 3)
+	return no_match;
+
+      strncpy (buf, sp, str - sp);
+      if (atoi (buf) > 255)
+	return no_match;
+
+      if (dots == 3)
+	{
+	  if (*str == '/')
+	    {
+	      if (*(str + 1) == '\0')
+		return partly_match;
+
+	      str++;
+	      break;
+	    }
+	  else if (*str == '\0')
+	    return partly_match;
+	}
+
+      if (*str == '\0')
+	return partly_match;
+
+      str++;
+    }
+
+  sp = str;
+  while (*str != '\0')
+    {
+      if (!isdigit ((int) *str))
+	return no_match;
+
+      str++;
+    }
+
+  if (atoi (sp) > 32)
+    return no_match;
+
+  return exact_match;
+}
+
+#define IPV6_ADDR_STR		"0123456789abcdefABCDEF:.%"
+#define IPV6_PREFIX_STR		"0123456789abcdefABCDEF:.%/"
+#define STATE_START		1
+#define STATE_COLON		2
+#define STATE_DOUBLE		3
+#define STATE_ADDR		4
+#define STATE_DOT               5
+#define STATE_SLASH		6
+#define STATE_MASK		7
+
+enum match_type
+cmd_ipv6_match (char *str)
+{
+  int state = STATE_START;
+  int colons = 0, nums = 0, double_colon = 0;
+  char *sp = NULL;
+
+  if (str == NULL)
+    return partly_match;
+
+  if (strspn (str, IPV6_ADDR_STR) != strlen (str))
+    return no_match;
+
+  while (*str != '\0')
+    {
+      switch (state)
+	{
+	case STATE_START:
+	  if (*str == ':')
+	    {
+	      if (*(str + 1) != ':' && *(str + 1) != '\0')
+		return no_match;
+     	      colons--;
+	      state = STATE_COLON;
+	    }
+	  else
+	    {
+	      sp = str;
+	      state = STATE_ADDR;
+	    }
+
+	  continue;
+	case STATE_COLON:
+	  colons++;
+	  if (*(str + 1) == ':')
+	    state = STATE_DOUBLE;
+	  else
+	    {
+	      sp = str + 1;
+	      state = STATE_ADDR;
+	    }
+	  break;
+	case STATE_DOUBLE:
+	  if (double_colon)
+	    return no_match;
+
+	  if (*(str + 1) == ':')
+	    return no_match;
+	  else
+	    {
+	      if (*(str + 1) != '\0')
+		colons++;
+	      sp = str + 1;
+	      state = STATE_ADDR;
+	    }
+
+	  double_colon++;
+	  nums++;
+	  break;
+	case STATE_ADDR:
+	  if (*(str + 1) == ':' || *(str + 1) == '\0')
+	    {
+	      if (str - sp > 3)
+		return no_match;
+
+	      nums++;
+	      state = STATE_COLON;
+	    }
+	  if (*(str + 1) == '.')
+	    state = STATE_DOT;
+	  break;
+	case STATE_DOT:
+	  state = STATE_ADDR;
+	  break;
+	default:
+	  break;
+	}
+
+      if (nums > 8)
+	return no_match;
+
+      if (colons > 7)
+	return no_match;
+
+      str++;
+    }
+
+#if 0
+  if (nums < 11)
+    return partly_match;
+#endif /* 0 */
+
+  return exact_match;
+}
+
+enum match_type
+cmd_ipv6_prefix_match (char *str)
+{
+  int state = STATE_START;
+  int colons = 0, nums = 0, double_colon = 0;
+  int mask;
+  char *sp = NULL;
+  char *endptr = NULL;
+
+  if (str == NULL)
+    return partly_match;
+
+  if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
+    return no_match;
+
+  while (*str != '\0' && state != STATE_MASK)
+    {
+      switch (state)
+	{
+	case STATE_START:
+	  if (*str == ':')
+	    {
+	      if (*(str + 1) != ':' && *(str + 1) != '\0')
+		return no_match;
+	      colons--;
+	      state = STATE_COLON;
+	    }
+	  else
+	    {
+	      sp = str;
+	      state = STATE_ADDR;
+	    }
+
+	  continue;
+	case STATE_COLON:
+	  colons++;
+	  if (*(str + 1) == '/')
+	    return no_match;
+	  else if (*(str + 1) == ':')
+	    state = STATE_DOUBLE;
+	  else
+	    {
+	      sp = str + 1;
+	      state = STATE_ADDR;
+	    }
+	  break;
+	case STATE_DOUBLE:
+	  if (double_colon)
+	    return no_match;
+
+	  if (*(str + 1) == ':')
+	    return no_match;
+	  else
+	    {
+	      if (*(str + 1) != '\0' && *(str + 1) != '/')
+		colons++;
+	      sp = str + 1;
+
+	      if (*(str + 1) == '/')
+		state = STATE_SLASH;
+	      else
+		state = STATE_ADDR;
+	    }
+
+	  double_colon++;
+	  nums += 1;
+	  break;
+	case STATE_ADDR:
+	  if (*(str + 1) == ':' || *(str + 1) == '.'
+	      || *(str + 1) == '\0' || *(str + 1) == '/')
+	    {
+	      if (str - sp > 3)
+		return no_match;
+
+	      for (; sp <= str; sp++)
+		if (*sp == '/')
+		  return no_match;
+
+	      nums++;
+
+	      if (*(str + 1) == ':')
+		state = STATE_COLON;
+	      else if (*(str + 1) == '.')
+		state = STATE_DOT;
+	      else if (*(str + 1) == '/')
+		state = STATE_SLASH;
+	    }
+	  break;
+	case STATE_DOT:
+	  state = STATE_ADDR;
+	  break;
+	case STATE_SLASH:
+	  if (*(str + 1) == '\0')
+	    return partly_match;
+
+	  state = STATE_MASK;
+	  break;
+	default:
+	  break;
+	}
+
+      if (nums > 11)
+	return no_match;
+
+      if (colons > 7)
+	return no_match;
+
+      str++;
+    }
+
+  if (state < STATE_MASK)
+    return partly_match;
+
+  mask = strtol (str, &endptr, 10);
+  if (*endptr != '\0')
+    return no_match;
+
+  if (mask < 0 || mask > 128)
+    return no_match;
+  
+/* I don't know why mask < 13 makes command match partly.
+   Forgive me to make this comments. I Want to set static default route
+   because of lack of function to originate default in ospf6d; sorry
+       yasu
+  if (mask < 13)
+    return partly_match;
+*/
+
+  return exact_match;
+}
+
+#define DECIMAL_STRLEN_MAX 10
+
+int
+cmd_range_match (char *range, char *str)
+{
+  char *p;
+  char buf[DECIMAL_STRLEN_MAX + 1];
+  char *endptr = NULL;
+  unsigned long min, max, val;
+
+  if (str == NULL)
+    return 1;
+
+  val = strtoul (str, &endptr, 10);
+  if (*endptr != '\0')
+    return 0;
+
+  range++;
+  p = strchr (range, '-');
+  if (p == NULL)
+    return 0;
+  if (p - range > DECIMAL_STRLEN_MAX)
+    return 0;
+  strncpy (buf, range, p - range);
+  buf[p - range] = '\0';
+  min = strtoul (buf, &endptr, 10);
+  if (*endptr != '\0')
+    return 0;
+
+  range = p + 1;
+  p = strchr (range, '>');
+  if (p == NULL)
+    return 0;
+  if (p - range > DECIMAL_STRLEN_MAX)
+    return 0;
+  strncpy (buf, range, p - range);
+  buf[p - range] = '\0';
+  max = strtoul (buf, &endptr, 10);
+  if (*endptr != '\0')
+    return 0;
+
+  if (val < min || val > max)
+    return 0;
+
+  return 1;
+}
+
+/* Make completion match and return match type flag. */
+enum match_type
+cmd_filter_by_completion (char *command, vector v, int index)
+{
+  int i;
+  char *str;
+  struct cmd_element *cmd_element;
+  enum match_type match_type;
+  vector descvec;
+  struct desc *desc;
+  
+  match_type = no_match;
+
+  /* If command and cmd_element string does not match set NULL to vector */
+  for (i = 0; i < vector_max (v); i++) 
+    if ((cmd_element = vector_slot (v, i)) != NULL)
+      {
+	if (index >= vector_max (cmd_element->strvec))
+	  vector_slot (v, i) = NULL;
+	else
+	  {
+	    int j;
+	    int matched = 0;
+
+	    descvec = vector_slot (cmd_element->strvec, index);
+	    
+	    for (j = 0; j < vector_max (descvec); j++)
+	      {
+		desc = vector_slot (descvec, j);
+		str = desc->cmd;
+
+		if (CMD_VARARG (str))
+		  {
+		    if (match_type < vararg_match)
+		      match_type = vararg_match;
+		    matched++;
+		  }
+		else if (CMD_RANGE (str))
+		  {
+		    if (cmd_range_match (str, command))
+		      {
+			if (match_type < range_match)
+			  match_type = range_match;
+
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV6 (str))
+		  {
+		    if (cmd_ipv6_match (command))
+		      {
+			if (match_type < ipv6_match)
+			  match_type = ipv6_match;
+
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV6_PREFIX (str))
+		  {
+		    if (cmd_ipv6_prefix_match (command))
+		      {
+			if (match_type < ipv6_prefix_match)
+			  match_type = ipv6_prefix_match;
+
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV4 (str))
+		  {
+		    if (cmd_ipv4_match (command))
+		      {
+			if (match_type < ipv4_match)
+			  match_type = ipv4_match;
+
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV4_PREFIX (str))
+		  {
+		    if (cmd_ipv4_prefix_match (command))
+		      {
+			if (match_type < ipv4_prefix_match)
+			  match_type = ipv4_prefix_match;
+			matched++;
+		      }
+		  }
+		else
+		/* Check is this point's argument optional ? */
+		if (CMD_OPTION (str) || CMD_VARIABLE (str))
+		  {
+		    if (match_type < extend_match)
+		      match_type = extend_match;
+		    matched++;
+		  }
+		else if (strncmp (command, str, strlen (command)) == 0)
+		  {
+		    if (strcmp (command, str) == 0) 
+		      match_type = exact_match;
+		    else
+		      {
+			if (match_type < partly_match)
+			  match_type = partly_match;
+		      }
+		    matched++;
+		  }
+	      }
+	    if (! matched)
+	      vector_slot (v, i) = NULL;
+	  }
+      }
+  return match_type;
+}
+
+/* Filter vector by command character with index. */
+enum match_type
+cmd_filter_by_string (char *command, vector v, int index)
+{
+  int i;
+  char *str;
+  struct cmd_element *cmd_element;
+  enum match_type match_type;
+  vector descvec;
+  struct desc *desc;
+  
+  match_type = no_match;
+
+  /* If command and cmd_element string does not match set NULL to vector */
+  for (i = 0; i < vector_max (v); i++) 
+    if ((cmd_element = vector_slot (v, i)) != NULL)
+      {
+	/* If given index is bigger than max string vector of command,
+           set NULL*/
+	if (index >= vector_max (cmd_element->strvec))
+	  vector_slot (v, i) = NULL;
+	else 
+	  {
+	    int j;
+	    int matched = 0;
+
+	    descvec = vector_slot (cmd_element->strvec, index);
+
+	    for (j = 0; j < vector_max (descvec); j++)
+	      {
+		desc = vector_slot (descvec, j);
+		str = desc->cmd;
+
+		if (CMD_VARARG (str))
+		  {
+		    if (match_type < vararg_match)
+		      match_type = vararg_match;
+		    matched++;
+		  }
+		else if (CMD_RANGE (str))
+		  {
+		    if (cmd_range_match (str, command))
+		      {
+			if (match_type < range_match)
+			  match_type = range_match;
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV6 (str))
+		  {
+		    if (cmd_ipv6_match (command) == exact_match)
+		      {
+			if (match_type < ipv6_match)
+			  match_type = ipv6_match;
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV6_PREFIX (str))
+		  {
+		    if (cmd_ipv6_prefix_match (command) == exact_match)
+		      {
+			if (match_type < ipv6_prefix_match)
+			  match_type = ipv6_prefix_match;
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV4 (str))
+		  {
+		    if (cmd_ipv4_match (command) == exact_match)
+		      {
+			if (match_type < ipv4_match)
+			  match_type = ipv4_match;
+			matched++;
+		      }
+		  }
+		else if (CMD_IPV4_PREFIX (str))
+		  {
+		    if (cmd_ipv4_prefix_match (command) == exact_match)
+		      {
+			if (match_type < ipv4_prefix_match)
+			  match_type = ipv4_prefix_match;
+			matched++;
+		      }
+		  }
+		else if (CMD_OPTION (str) || CMD_VARIABLE (str))
+		  {
+		    if (match_type < extend_match)
+		      match_type = extend_match;
+		    matched++;
+		  }
+		else
+		  {		  
+		    if (strcmp (command, str) == 0)
+		      {
+			match_type = exact_match;
+			matched++;
+		      }
+		  }
+	      }
+	    if (! matched)
+	      vector_slot (v, i) = NULL;
+	  }
+      }
+  return match_type;
+}
+
+/* Check ambiguous match */
+int
+is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
+{
+  int i;
+  int j;
+  char *str = NULL;
+  struct cmd_element *cmd_element;
+  char *matched = NULL;
+  vector descvec;
+  struct desc *desc;
+  
+  for (i = 0; i < vector_max (v); i++) 
+    if ((cmd_element = vector_slot (v, i)) != NULL)
+      {
+	int match = 0;
+
+	descvec = vector_slot (cmd_element->strvec, index);
+
+	for (j = 0; j < vector_max (descvec); j++)
+	  {
+	    enum match_type ret;
+
+	    desc = vector_slot (descvec, j);
+	    str = desc->cmd;
+
+	    switch (type)
+	      {
+	      case exact_match:
+		if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
+		    && strcmp (command, str) == 0)
+		  match++;
+		break;
+	      case partly_match:
+		if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
+		    && strncmp (command, str, strlen (command)) == 0)
+		  {
+		    if (matched && strcmp (matched, str) != 0)
+		      return 1;	/* There is ambiguous match. */
+		    else
+		      matched = str;
+		    match++;
+		  }
+		break;
+	      case range_match:
+		if (cmd_range_match (str, command))
+		  {
+		    if (matched && strcmp (matched, str) != 0)
+		      return 1;
+		    else
+		      matched = str;
+		    match++;
+		  }
+		break;
+ 	      case ipv6_match:
+		if (CMD_IPV6 (str))
+		  match++;
+		break;
+	      case ipv6_prefix_match:
+		if ((ret = cmd_ipv6_prefix_match (command)) != no_match)
+		  {
+		    if (ret == partly_match)
+		      return 2; /* There is incomplete match. */
+
+		    match++;
+		  }
+		break;
+	      case ipv4_match:
+		if (CMD_IPV4 (str))
+		  match++;
+		break;
+	      case ipv4_prefix_match:
+		if ((ret = cmd_ipv4_prefix_match (command)) != no_match)
+		  {
+		    if (ret == partly_match)
+		      return 2; /* There is incomplete match. */
+
+		    match++;
+		  }
+		break;
+	      case extend_match:
+		if (CMD_OPTION (str) || CMD_VARIABLE (str))
+		  match++;
+		break;
+	      case no_match:
+	      default:
+		break;
+	      }
+	  }
+	if (! match)
+	  vector_slot (v, i) = NULL;
+      }
+  return 0;
+}
+
+/* If src matches dst return dst string, otherwise return NULL */
+char *
+cmd_entry_function (char *src, char *dst)
+{
+  /* Skip variable arguments. */
+  if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) ||
+      CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst))
+    return NULL;
+
+  /* In case of 'command \t', given src is NULL string. */
+  if (src == NULL)
+    return dst;
+
+  /* Matched with input string. */
+  if (strncmp (src, dst, strlen (src)) == 0)
+    return dst;
+
+  return NULL;
+}
+
+/* If src matches dst return dst string, otherwise return NULL */
+/* This version will return the dst string always if it is
+   CMD_VARIABLE for '?' key processing */
+char *
+cmd_entry_function_desc (char *src, char *dst)
+{
+  if (CMD_VARARG (dst))
+    return dst;
+
+  if (CMD_RANGE (dst))
+    {
+      if (cmd_range_match (dst, src))
+	return dst;
+      else
+	return NULL;
+    }
+
+  if (CMD_IPV6 (dst))
+    {
+      if (cmd_ipv6_match (src))
+	return dst;
+      else
+	return NULL;
+    }
+
+  if (CMD_IPV6_PREFIX (dst))
+    {
+      if (cmd_ipv6_prefix_match (src))
+	return dst;
+      else
+	return NULL;
+    }
+
+  if (CMD_IPV4 (dst))
+    {
+      if (cmd_ipv4_match (src))
+	return dst;
+      else
+	return NULL;
+    }
+
+  if (CMD_IPV4_PREFIX (dst))
+    {
+      if (cmd_ipv4_prefix_match (src))
+	return dst;
+      else
+	return NULL;
+    }
+
+  /* Optional or variable commands always match on '?' */
+  if (CMD_OPTION (dst) || CMD_VARIABLE (dst))
+    return dst;
+
+  /* In case of 'command \t', given src is NULL string. */
+  if (src == NULL)
+    return dst;
+
+  if (strncmp (src, dst, strlen (src)) == 0)
+    return dst;
+  else
+    return NULL;
+}
+
+/* Check same string element existence.  If it isn't there return
+    1. */
+int
+cmd_unique_string (vector v, char *str)
+{
+  int i;
+  char *match;
+
+  for (i = 0; i < vector_max (v); i++)
+    if ((match = vector_slot (v, i)) != NULL)
+      if (strcmp (match, str) == 0)
+	return 0;
+  return 1;
+}
+
+/* Compare string to description vector.  If there is same string
+   return 1 else return 0. */
+int
+desc_unique_string (vector v, char *str)
+{
+  int i;
+  struct desc *desc;
+
+  for (i = 0; i < vector_max (v); i++)
+    if ((desc = vector_slot (v, i)) != NULL)
+      if (strcmp (desc->cmd, str) == 0)
+	return 1;
+  return 0;
+}
+
+/* '?' describe command support. */
+vector
+cmd_describe_command (vector vline, struct vty *vty, int *status)
+{
+  int i;
+  vector cmd_vector;
+#define INIT_MATCHVEC_SIZE 10
+  vector matchvec;
+  struct cmd_element *cmd_element;
+  int index;
+  static struct desc desc_cr = { "<cr>", "" };
+
+  /* Set index. */
+  index = vector_max (vline) - 1;
+
+  /* Make copy vector of current node's command vector. */
+  cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
+
+  /* Prepare match vector */
+  matchvec = vector_init (INIT_MATCHVEC_SIZE);
+
+  /* Filter commands. */
+  for (i = 0; i < index; i++)
+    {
+      enum match_type match;
+      char *command;
+      int ret;
+
+      command = vector_slot (vline, i);
+
+      match = cmd_filter_by_completion (command, cmd_vector, i);
+
+      if (match == vararg_match)
+	{
+	  struct cmd_element *cmd_element;
+	  vector descvec;
+	  int j, k;
+
+	  for (j = 0; j < vector_max (cmd_vector); j++)
+	    if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
+	      {
+		descvec = vector_slot (cmd_element->strvec,
+				       vector_max (cmd_element->strvec) - 1);
+		for (k = 0; k < vector_max (descvec); k++)
+		  {
+		    struct desc *desc = vector_slot (descvec, k);
+		    vector_set (matchvec, desc);
+		  }
+	      }
+
+	  vector_set (matchvec, &desc_cr);
+
+	  vector_free (cmd_vector);
+
+	  return matchvec;
+	}
+
+      if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
+	{
+	  vector_free (cmd_vector);
+	  *status = CMD_ERR_AMBIGUOUS;
+	  return NULL;
+	}
+      else if (ret == 2)
+	{
+	  vector_free (cmd_vector);
+	  *status = CMD_ERR_NO_MATCH;
+	  return NULL;
+	}
+    }
+
+  /* Prepare match vector */
+  /*  matchvec = vector_init (INIT_MATCHVEC_SIZE); */
+
+  /* Make description vector. */
+  for (i = 0; i < vector_max (cmd_vector); i++)
+    if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
+      {
+	char *string = NULL;
+	vector strvec = cmd_element->strvec;
+
+	if (index > vector_max (strvec))
+	  vector_slot (cmd_vector, i) = NULL;
+	else
+	  {
+	    /* Check is command is completed. */
+	    if (index == vector_max (strvec))
+	      {
+		string = "<cr>";
+		if (! desc_unique_string (matchvec, string))
+		  vector_set (matchvec, &desc_cr);
+	      }
+	    else
+	      {
+		int j;
+		vector descvec = vector_slot (strvec, index);
+		struct desc *desc;
+
+		for (j = 0; j < vector_max (descvec); j++)
+		  {
+		    desc = vector_slot (descvec, j);
+		    string = cmd_entry_function_desc (vector_slot (vline, index), desc->cmd);
+		    if (string)
+		      {
+			/* Uniqueness check */
+			if (! desc_unique_string (matchvec, string))
+			  vector_set (matchvec, desc);
+		      }
+		  }
+	      }
+	  }
+      }
+  vector_free (cmd_vector);
+
+  if (vector_slot (matchvec, 0) == NULL)
+    {
+      vector_free (matchvec);
+      *status= CMD_ERR_NO_MATCH;
+    }
+  else
+    *status = CMD_SUCCESS;
+
+  return matchvec;
+}
+
+/* Check LCD of matched command. */
+int
+cmd_lcd (char **matched)
+{
+  int i;
+  int j;
+  int lcd = -1;
+  char *s1, *s2;
+  char c1, c2;
+
+  if (matched[0] == NULL || matched[1] == NULL)
+    return 0;
+
+  for (i = 1; matched[i] != NULL; i++)
+    {
+      s1 = matched[i - 1];
+      s2 = matched[i];
+
+      for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
+	if (c1 != c2)
+	  break;
+
+      if (lcd < 0)
+	lcd = j;
+      else
+	{
+	  if (lcd > j)
+	    lcd = j;
+	}
+    }
+  return lcd;
+}
+
+/* Command line completion support. */
+char **
+cmd_complete_command (vector vline, struct vty *vty, int *status)
+{
+  int i;
+  vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
+#define INIT_MATCHVEC_SIZE 10
+  vector matchvec;
+  struct cmd_element *cmd_element;
+  int index = vector_max (vline) - 1;
+  char **match_str;
+  struct desc *desc;
+  vector descvec;
+  char *command;
+  int lcd;
+
+  /* First, filter by preceeding command string */
+  for (i = 0; i < index; i++)
+    {
+      enum match_type match;
+      int ret;
+
+      command = vector_slot (vline, i);
+
+      /* First try completion match, if there is exactly match return 1 */
+      match = cmd_filter_by_completion (command, cmd_vector, i);
+
+      /* If there is exact match then filter ambiguous match else check
+	 ambiguousness. */
+      if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
+	{
+	  vector_free (cmd_vector);
+	  *status = CMD_ERR_AMBIGUOUS;
+	  return NULL;
+	}
+      /*
+	else if (ret == 2)
+	{
+	  vector_free (cmd_vector);
+	  *status = CMD_ERR_NO_MATCH;
+	  return NULL;
+	}
+      */
+    }
+
+  /* Prepare match vector. */
+  matchvec = vector_init (INIT_MATCHVEC_SIZE);
+
+  /* Now we got into completion */
+  for (i = 0; i < vector_max (cmd_vector); i++)
+    if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
+      {
+	char *string;
+	vector strvec = cmd_element->strvec;
+	
+	/* Check field length */
+	if (index >= vector_max (strvec))
+	  vector_slot (cmd_vector, i) = NULL;
+	else 
+	  {
+	    int j;
+
+	    descvec = vector_slot (strvec, index);
+	    for (j = 0; j < vector_max (descvec); j++)
+	      {
+		desc = vector_slot (descvec, j);
+
+		if ((string = cmd_entry_function (vector_slot (vline, index),
+						  desc->cmd)))
+		  if (cmd_unique_string (matchvec, string))
+		    vector_set (matchvec, XSTRDUP (MTYPE_TMP, string));
+	      }
+	  }
+      }
+
+  /* We don't need cmd_vector any more. */
+  vector_free (cmd_vector);
+
+  /* No matched command */
+  if (vector_slot (matchvec, 0) == NULL)
+    {
+      vector_free (matchvec);
+
+      /* In case of 'command \t' pattern.  Do you need '?' command at
+         the end of the line. */
+      if (vector_slot (vline, index) == '\0')
+	*status = CMD_ERR_NOTHING_TODO;
+      else
+	*status = CMD_ERR_NO_MATCH;
+      return NULL;
+    }
+
+  /* Only one matched */
+  if (vector_slot (matchvec, 1) == NULL)
+    {
+      match_str = (char **) matchvec->index;
+      vector_only_wrapper_free (matchvec);
+      *status = CMD_COMPLETE_FULL_MATCH;
+      return match_str;
+    }
+  /* Make it sure last element is NULL. */
+  vector_set (matchvec, NULL);
+
+  /* Check LCD of matched strings. */
+  if (vector_slot (vline, index) != NULL)
+    {
+      lcd = cmd_lcd ((char **) matchvec->index);
+
+      if (lcd)
+	{
+	  int len = strlen (vector_slot (vline, index));
+	  
+	  if (len < lcd)
+	    {
+	      char *lcdstr;
+	      
+	      lcdstr = XMALLOC (MTYPE_TMP, lcd + 1);
+	      memcpy (lcdstr, matchvec->index[0], lcd);
+	      lcdstr[lcd] = '\0';
+
+	      /* match_str = (char **) &lcdstr; */
+
+	      /* Free matchvec. */
+	      for (i = 0; i < vector_max (matchvec); i++)
+		{
+		  if (vector_slot (matchvec, i))
+		    XFREE (MTYPE_TMP, vector_slot (matchvec, i));
+		}
+	      vector_free (matchvec);
+
+      	      /* Make new matchvec. */
+	      matchvec = vector_init (INIT_MATCHVEC_SIZE);
+	      vector_set (matchvec, lcdstr);
+	      match_str = (char **) matchvec->index;
+	      vector_only_wrapper_free (matchvec);
+
+	      *status = CMD_COMPLETE_MATCH;
+	      return match_str;
+	    }
+	}
+    }
+
+  match_str = (char **) matchvec->index;
+  vector_only_wrapper_free (matchvec);
+  *status = CMD_COMPLETE_LIST_MATCH;
+  return match_str;
+}
+
+/* Execute command by argument vline vector. */
+int
+cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd)
+{
+  int i;
+  int index;
+  vector cmd_vector;
+  struct cmd_element *cmd_element;
+  struct cmd_element *matched_element;
+  unsigned int matched_count, incomplete_count;
+  int argc;
+  char *argv[CMD_ARGC_MAX];
+  enum match_type match = 0;
+  int varflag;
+  char *command;
+
+  /* Make copy of command elements. */
+  cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
+
+  for (index = 0; index < vector_max (vline); index++) 
+    {
+      int ret;
+
+      command = vector_slot (vline, index);
+
+      match = cmd_filter_by_completion (command, cmd_vector, index);
+
+      if (match == vararg_match)
+	break;
+
+      ret = is_cmd_ambiguous (command, cmd_vector, index, match);
+
+      if (ret == 1)
+	{
+	  vector_free (cmd_vector);
+	  return CMD_ERR_AMBIGUOUS;
+	}
+      else if (ret == 2)
+	{
+	  vector_free (cmd_vector);
+	  return CMD_ERR_NO_MATCH;
+	}
+    }
+
+  /* Check matched count. */
+  matched_element = NULL;
+  matched_count = 0;
+  incomplete_count = 0;
+
+  for (i = 0; i < vector_max (cmd_vector); i++) 
+    if (vector_slot (cmd_vector,i) != NULL)
+      {
+	cmd_element = vector_slot (cmd_vector,i);
+
+	if (match == vararg_match || index >= cmd_element->cmdsize)
+	  {
+	    matched_element = cmd_element;
+#if 0
+	    printf ("DEBUG: %s\n", cmd_element->string);
+#endif
+	    matched_count++;
+	  }
+	else
+	  {
+	    incomplete_count++;
+	  }
+      }
+  
+  /* Finish of using cmd_vector. */
+  vector_free (cmd_vector);
+
+  /* To execute command, matched_count must be 1.*/
+  if (matched_count == 0) 
+    {
+      if (incomplete_count)
+	return CMD_ERR_INCOMPLETE;
+      else
+	return CMD_ERR_NO_MATCH;
+    }
+
+  if (matched_count > 1) 
+    return CMD_ERR_AMBIGUOUS;
+
+  /* Argument treatment */
+  varflag = 0;
+  argc = 0;
+
+  for (i = 0; i < vector_max (vline); i++)
+    {
+      if (varflag)
+	argv[argc++] = vector_slot (vline, i);
+      else
+	{	  
+	  vector descvec = vector_slot (matched_element->strvec, i);
+
+	  if (vector_max (descvec) == 1)
+	    {
+	      struct desc *desc = vector_slot (descvec, 0);
+	      char *str = desc->cmd;
+
+	      if (CMD_VARARG (str))
+		varflag = 1;
+
+	      if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str))
+		argv[argc++] = vector_slot (vline, i);
+	    }
+	  else
+	    argv[argc++] = vector_slot (vline, i);
+	}
+
+      if (argc >= CMD_ARGC_MAX)
+	return CMD_ERR_EXEED_ARGC_MAX;
+    }
+
+  /* For vtysh execution. */
+  if (cmd)
+    *cmd = matched_element;
+
+  if (matched_element->daemon)
+    return CMD_SUCCESS_DAEMON;
+
+  /* Execute matched command. */
+  return (*matched_element->func) (matched_element, vty, argc, argv);
+}
+
+/* Execute command by argument readline. */
+int
+cmd_execute_command_strict (vector vline, struct vty *vty, 
+			    struct cmd_element **cmd)
+{
+  int i;
+  int index;
+  vector cmd_vector;
+  struct cmd_element *cmd_element;
+  struct cmd_element *matched_element;
+  unsigned int matched_count, incomplete_count;
+  int argc;
+  char *argv[CMD_ARGC_MAX];
+  int varflag;
+  enum match_type match = 0;
+  char *command;
+
+  /* Make copy of command element */
+  cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
+
+  for (index = 0; index < vector_max (vline); index++) 
+    {
+      int ret;
+
+      command = vector_slot (vline, index);
+
+      match = cmd_filter_by_string (vector_slot (vline, index), 
+				    cmd_vector, index);
+
+      /* If command meets '.VARARG' then finish matching. */
+      if (match == vararg_match)
+	break;
+
+      ret = is_cmd_ambiguous (command, cmd_vector, index, match);
+      if (ret == 1)
+	{
+	  vector_free (cmd_vector);
+	  return CMD_ERR_AMBIGUOUS;
+	}
+      if (ret == 2)
+	{
+	  vector_free (cmd_vector);
+	  return CMD_ERR_NO_MATCH;
+	}
+    }
+
+  /* Check matched count. */
+  matched_element = NULL;
+  matched_count = 0;
+  incomplete_count = 0;
+  for (i = 0; i < vector_max (cmd_vector); i++) 
+    if (vector_slot (cmd_vector,i) != NULL)
+      {
+	cmd_element = vector_slot (cmd_vector,i);
+
+	if (match == vararg_match || index >= cmd_element->cmdsize)
+	  {
+	    matched_element = cmd_element;
+	    matched_count++;
+	  }
+	else
+	  incomplete_count++;
+      }
+  
+  /* Finish of using cmd_vector. */
+  vector_free (cmd_vector);
+
+  /* To execute command, matched_count must be 1.*/
+  if (matched_count == 0) 
+    {
+      if (incomplete_count)
+	return CMD_ERR_INCOMPLETE;
+      else
+	return CMD_ERR_NO_MATCH;
+    }
+
+  if (matched_count > 1) 
+    return CMD_ERR_AMBIGUOUS;
+
+  /* Argument treatment */
+  varflag = 0;
+  argc = 0;
+
+  for (i = 0; i < vector_max (vline); i++)
+    {
+      if (varflag)
+	argv[argc++] = vector_slot (vline, i);
+      else
+	{	  
+	  vector descvec = vector_slot (matched_element->strvec, i);
+
+	  if (vector_max (descvec) == 1)
+	    {
+	      struct desc *desc = vector_slot (descvec, 0);
+	      char *str = desc->cmd;
+
+	      if (CMD_VARARG (str))
+		varflag = 1;
+	  
+	      if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str))
+		argv[argc++] = vector_slot (vline, i);
+	    }
+	  else
+	    argv[argc++] = vector_slot (vline, i);
+	}
+
+      if (argc >= CMD_ARGC_MAX)
+	return CMD_ERR_EXEED_ARGC_MAX;
+    }
+
+  /* For vtysh execution. */
+  if (cmd)
+    *cmd = matched_element;
+
+  if (matched_element->daemon)
+    return CMD_SUCCESS_DAEMON;
+
+  /* Now execute matched command */
+  return (*matched_element->func) (matched_element, vty, argc, argv);
+}
+
+/* Configration make from file. */
+int
+config_from_file (struct vty *vty, FILE *fp)
+{
+  int ret;
+  vector vline;
+
+  while (fgets (vty->buf, VTY_BUFSIZ, fp))
+    {
+      vline = cmd_make_strvec (vty->buf);
+
+      /* In case of comment line */
+      if (vline == NULL)
+	continue;
+      /* Execute configuration command : this is strict match */
+      ret = cmd_execute_command_strict (vline, vty, NULL);
+
+      /* Try again with setting node to CONFIG_NODE */
+      if (ret != CMD_SUCCESS && ret != CMD_WARNING)
+	{
+	  if (vty->node == KEYCHAIN_KEY_NODE)
+	    {
+	      vty->node = KEYCHAIN_NODE;
+
+	      ret = cmd_execute_command_strict (vline, vty, NULL);
+
+	      if (ret != CMD_SUCCESS && ret != CMD_WARNING)
+		{
+		  vty->node = CONFIG_NODE;
+		  ret = cmd_execute_command_strict (vline, vty, NULL);
+		}
+	    }
+	  else
+	    {
+	      vty->node = CONFIG_NODE;
+	      ret = cmd_execute_command_strict (vline, vty, NULL);
+	    }
+	}	  
+
+      cmd_free_strvec (vline);
+
+      if (ret != CMD_SUCCESS && ret != CMD_WARNING)
+	return ret;
+    }
+  return CMD_SUCCESS;
+}
+
+/* Configration from terminal */
+DEFUN (config_terminal,
+       config_terminal_cmd,
+       "configure terminal",
+       "Configuration from vty interface\n"
+       "Configuration terminal\n")
+{
+  if (vty_config_lock (vty))
+    vty->node = CONFIG_NODE;
+  else
+    {
+      vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+/* Enable command */
+DEFUN (enable, 
+       config_enable_cmd,
+       "enable",
+       "Turn on privileged mode command\n")
+{
+  /* If enable password is NULL, change to ENABLE_NODE */
+  if ((host.enable == NULL && host.enable_encrypt == NULL) ||
+      vty->type == VTY_SHELL_SERV)
+    vty->node = ENABLE_NODE;
+  else
+    vty->node = AUTH_ENABLE_NODE;
+
+  return CMD_SUCCESS;
+}
+
+/* Disable command */
+DEFUN (disable, 
+       config_disable_cmd,
+       "disable",
+       "Turn off privileged mode command\n")
+{
+  if (vty->node == ENABLE_NODE)
+    vty->node = VIEW_NODE;
+  return CMD_SUCCESS;
+}
+
+/* Down vty node level. */
+DEFUN (config_exit,
+       config_exit_cmd,
+       "exit",
+       "Exit current mode and down to previous mode\n")
+{
+  switch (vty->node)
+    {
+    case VIEW_NODE:
+    case ENABLE_NODE:
+      if (vty_shell (vty))
+	exit (0);
+      else
+	vty->status = VTY_CLOSE;
+      break;
+    case CONFIG_NODE:
+      vty->node = ENABLE_NODE;
+      vty_config_unlock (vty);
+      break;
+    case INTERFACE_NODE:
+    case ZEBRA_NODE:
+    case BGP_NODE:
+    case RIP_NODE:
+    case RIPNG_NODE:
+    case OSPF_NODE:
+    case OSPF6_NODE:
+    case ISIS_NODE:
+    case KEYCHAIN_NODE:
+    case MASC_NODE:
+    case RMAP_NODE:
+    case VTY_NODE:
+      vty->node = CONFIG_NODE;
+      break;
+    case BGP_VPNV4_NODE:
+    case BGP_IPV4_NODE:
+    case BGP_IPV4M_NODE:
+    case BGP_IPV6_NODE:
+      vty->node = BGP_NODE;
+      break;
+    case KEYCHAIN_KEY_NODE:
+      vty->node = KEYCHAIN_NODE;
+      break;
+    default:
+      break;
+    }
+  return CMD_SUCCESS;
+}
+
+/* quit is alias of exit. */
+ALIAS (config_exit,
+       config_quit_cmd,
+       "quit",
+       "Exit current mode and down to previous mode\n")
+       
+/* End of configuration. */
+DEFUN (config_end,
+       config_end_cmd,
+       "end",
+       "End current mode and change to enable mode.")
+{
+  switch (vty->node)
+    {
+    case VIEW_NODE:
+    case ENABLE_NODE:
+      /* Nothing to do. */
+      break;
+    case CONFIG_NODE:
+    case INTERFACE_NODE:
+    case ZEBRA_NODE:
+    case RIP_NODE:
+    case RIPNG_NODE:
+    case BGP_NODE:
+    case BGP_VPNV4_NODE:
+    case BGP_IPV4_NODE:
+    case BGP_IPV4M_NODE:
+    case BGP_IPV6_NODE:
+    case RMAP_NODE:
+    case OSPF_NODE:
+    case OSPF6_NODE:
+    case ISIS_NODE:
+    case KEYCHAIN_NODE:
+    case KEYCHAIN_KEY_NODE:
+    case MASC_NODE:
+    case VTY_NODE:
+      vty_config_unlock (vty);
+      vty->node = ENABLE_NODE;
+      break;
+    default:
+      break;
+    }
+  return CMD_SUCCESS;
+}
+
+/* Show version. */
+DEFUN (show_version,
+       show_version_cmd,
+       "show version",
+       SHOW_STR
+       "Displays zebra version\n")
+{
+  vty_out (vty, "Zebra %s (%s).%s", ZEBRA_VERSION,
+	   host_name,
+	   VTY_NEWLINE);
+  vty_out (vty, "Copyright 1996-2002, Kunihiro Ishiguro.%s", VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+/* Help display function for all node. */
+DEFUN (config_help,
+       config_help_cmd,
+       "help",
+       "Description of the interactive help system\n")
+{
+  vty_out (vty, 
+	   "Zebra VTY provides advanced help feature.  When you need help,%s\
+anytime at the command line please press '?'.%s\
+%s\
+If nothing matches, the help list will be empty and you must backup%s\
+ until entering a '?' shows the available options.%s\
+Two styles of help are provided:%s\
+1. Full help is available when you are ready to enter a%s\
+command argument (e.g. 'show ?') and describes each possible%s\
+argument.%s\
+2. Partial help is provided when an abbreviated argument is entered%s\
+   and you want to know what arguments match the input%s\
+   (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
+	   VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
+	   VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
+
+/* Help display function for all node. */
+DEFUN (config_list,
+       config_list_cmd,
+       "list",
+       "Print command list\n")
+{
+  int i;
+  struct cmd_node *cnode = vector_slot (cmdvec, vty->node);
+  struct cmd_element *cmd;
+
+  for (i = 0; i < vector_max (cnode->cmd_vector); i++)
+    if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL)
+      vty_out (vty, "  %s%s", cmd->string,
+	       VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
+
+/* Write current configuration into file. */
+DEFUN (config_write_file, 
+       config_write_file_cmd,
+       "write file",  
+       "Write running configuration to memory, network, or terminal\n"
+       "Write to configuration file\n")
+{
+  int i;
+  int fd;
+  struct cmd_node *node;
+  char *config_file;
+  char *config_file_tmp = NULL;
+  char *config_file_sav = NULL;
+  struct vty *file_vty;
+
+  /* Check and see if we are operating under vtysh configuration */
+  if (host.config == NULL)
+    {
+      vty_out (vty, "Can't save to configuration file, using vtysh.%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Get filename. */
+  config_file = host.config;
+  
+  config_file_sav = malloc (strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1);
+  strcpy (config_file_sav, config_file);
+  strcat (config_file_sav, CONF_BACKUP_EXT);
+
+
+  config_file_tmp = malloc (strlen (config_file) + 8);
+  sprintf (config_file_tmp, "%s.XXXXXX", config_file);
+  
+  /* Open file to configuration write. */
+  fd = mkstemp (config_file_tmp);
+  if (fd < 0)
+    {
+      vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp,
+	       VTY_NEWLINE);
+      free (config_file_tmp);
+      free (config_file_sav);
+      return CMD_WARNING;
+    }
+  
+  /* Make vty for configuration file. */
+  file_vty = vty_new ();
+  file_vty->fd = fd;
+  file_vty->type = VTY_FILE;
+
+  /* Config file header print. */
+  vty_out (file_vty, "!\n! Zebra configuration saved from vty\n!   ");
+  vty_time_print (file_vty, 1);
+  vty_out (file_vty, "!\n");
+
+  for (i = 0; i < vector_max (cmdvec); i++)
+    if ((node = vector_slot (cmdvec, i)) && node->func)
+      {
+	if ((*node->func) (file_vty))
+	  vty_out (file_vty, "!\n");
+      }
+  vty_close (file_vty);
+
+  if (unlink (config_file_sav) != 0)
+    if (errno != ENOENT)
+      {
+	vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav,
+		 VTY_NEWLINE);
+	free (config_file_sav);
+	free (config_file_tmp);
+	unlink (config_file_tmp);	
+	return CMD_WARNING;
+      }
+  if (link (config_file, config_file_sav) != 0)
+    {
+      vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
+	        VTY_NEWLINE);
+      free (config_file_sav);
+      free (config_file_tmp);
+      unlink (config_file_tmp);
+      return CMD_WARNING;
+    }
+  sync ();
+  if (unlink (config_file) != 0)
+    {
+      vty_out (vty, "Can't unlink configuration file %s.%s", config_file,
+	        VTY_NEWLINE);
+      free (config_file_sav);
+      free (config_file_tmp);
+      unlink (config_file_tmp);
+      return CMD_WARNING;      
+    }
+  if (link (config_file_tmp, config_file) != 0)
+    {
+      vty_out (vty, "Can't save configuration file %s.%s", config_file,
+	       VTY_NEWLINE);
+      free (config_file_sav);
+      free (config_file_tmp);
+      unlink (config_file_tmp);
+      return CMD_WARNING;      
+    }
+  unlink (config_file_tmp);
+  sync ();
+  
+  free (config_file_sav);
+  free (config_file_tmp);
+  vty_out (vty, "Configuration saved to %s%s", config_file,
+	   VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
+
+ALIAS (config_write_file, 
+       config_write_cmd,
+       "write",  
+       "Write running configuration to memory, network, or terminal\n")
+
+ALIAS (config_write_file, 
+       config_write_memory_cmd,
+       "write memory",  
+       "Write running configuration to memory, network, or terminal\n"
+       "Write configuration to the file (same as write file)\n")
+
+ALIAS (config_write_file, 
+       copy_runningconfig_startupconfig_cmd,
+       "copy running-config startup-config",  
+       "Copy configuration\n"
+       "Copy running config to... \n"
+       "Copy running config to startup config (same as write file)\n")
+
+/* Write current configuration into the terminal. */
+DEFUN (config_write_terminal,
+       config_write_terminal_cmd,
+       "write terminal",
+       "Write running configuration to memory, network, or terminal\n"
+       "Write to terminal\n")
+{
+  int i;
+  struct cmd_node *node;
+
+  if (vty->type == VTY_SHELL_SERV)
+    {
+      for (i = 0; i < vector_max (cmdvec); i++)
+	if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
+	  {
+	    if ((*node->func) (vty))
+	      vty_out (vty, "!%s", VTY_NEWLINE);
+	  }
+    }
+  else
+    {
+      vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
+	       VTY_NEWLINE);
+      vty_out (vty, "!%s", VTY_NEWLINE);
+
+      for (i = 0; i < vector_max (cmdvec); i++)
+	if ((node = vector_slot (cmdvec, i)) && node->func)
+	  {
+	    if ((*node->func) (vty))
+	      vty_out (vty, "!%s", VTY_NEWLINE);
+	  }
+      vty_out (vty, "end%s",VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+/* Write current configuration into the terminal. */
+ALIAS (config_write_terminal,
+       show_running_config_cmd,
+       "show running-config",
+       SHOW_STR
+       "running configuration\n")
+
+/* Write startup configuration into the terminal. */
+DEFUN (show_startup_config,
+       show_startup_config_cmd,
+       "show startup-config",
+       SHOW_STR
+       "Contentes of startup configuration\n")
+{
+  char buf[BUFSIZ];
+  FILE *confp;
+
+  confp = fopen (host.config, "r");
+  if (confp == NULL)
+    {
+      vty_out (vty, "Can't open configuration file [%s]%s",
+	       host.config, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  while (fgets (buf, BUFSIZ, confp))
+    {
+      char *cp = buf;
+
+      while (*cp != '\r' && *cp != '\n' && *cp != '\0')
+	cp++;
+      *cp = '\0';
+
+      vty_out (vty, "%s%s", buf, VTY_NEWLINE);
+    }
+
+  fclose (confp);
+
+  return CMD_SUCCESS;
+}
+
+/* Hostname configuration */
+DEFUN (config_hostname, 
+       hostname_cmd,
+       "hostname WORD",
+       "Set system's network name\n"
+       "This system's network name\n")
+{
+  if (!isalpha((int) *argv[0]))
+    {
+      vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (host.name)
+    XFREE (0, host.name);
+    
+  host.name = strdup (argv[0]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_no_hostname, 
+       no_hostname_cmd,
+       "no hostname [HOSTNAME]",
+       NO_STR
+       "Reset system's network name\n"
+       "Host name of this router\n")
+{
+  if (host.name)
+    XFREE (0, host.name);
+  host.name = NULL;
+  return CMD_SUCCESS;
+}
+
+/* VTY interface password set. */
+DEFUN (config_password, password_cmd,
+       "password (8|) WORD",
+       "Assign the terminal connection password\n"
+       "Specifies a HIDDEN password will follow\n"
+       "dummy string \n"
+       "The HIDDEN line password string\n")
+{
+  /* Argument check. */
+  if (argc == 0)
+    {
+      vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (argc == 2)
+    {
+      if (*argv[0] == '8')
+	{
+	  if (host.password)
+	    XFREE (0, host.password);
+	  host.password = NULL;
+	  if (host.password_encrypt)
+	    XFREE (0, host.password_encrypt);
+	  host.password_encrypt = XSTRDUP (0, strdup (argv[1]));
+	  return CMD_SUCCESS;
+	}
+      else
+	{
+	  vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+
+  if (!isalnum ((int) *argv[0]))
+    {
+      vty_out (vty, 
+	       "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (host.password)
+    XFREE (0, host.password);
+  host.password = NULL;
+
+  if (host.encrypt)
+    {
+      if (host.password_encrypt)
+	XFREE (0, host.password_encrypt);
+      host.password_encrypt = XSTRDUP (0, zencrypt (argv[0]));
+    }
+  else
+    host.password = XSTRDUP (0, argv[0]);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (config_password, password_text_cmd,
+       "password LINE",
+       "Assign the terminal connection password\n"
+       "The UNENCRYPTED (cleartext) line password\n")
+
+/* VTY enable password set. */
+DEFUN (config_enable_password, enable_password_cmd,
+       "enable password (8|) WORD",
+       "Modify enable password parameters\n"
+       "Assign the privileged level password\n"
+       "Specifies a HIDDEN password will follow\n"
+       "dummy string \n"
+       "The HIDDEN 'enable' password string\n")
+{
+  /* Argument check. */
+  if (argc == 0)
+    {
+      vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Crypt type is specified. */
+  if (argc == 2)
+    {
+      if (*argv[0] == '8')
+	{
+	  if (host.enable)
+	    XFREE (0, host.enable);
+	  host.enable = NULL;
+
+	  if (host.enable_encrypt)
+	    XFREE (0, host.enable_encrypt);
+	  host.enable_encrypt = XSTRDUP (0, argv[1]);
+
+	  return CMD_SUCCESS;
+	}
+      else
+	{
+	  vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+
+  if (!isalnum ((int) *argv[0]))
+    {
+      vty_out (vty, 
+	       "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (host.enable)
+    XFREE (0, host.enable);
+  host.enable = NULL;
+
+  /* Plain password input. */
+  if (host.encrypt)
+    {
+      if (host.enable_encrypt)
+	XFREE (0, host.enable_encrypt);
+      host.enable_encrypt = XSTRDUP (0, zencrypt (argv[0]));
+    }
+  else
+    host.enable = XSTRDUP (0, argv[0]);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (config_enable_password,
+       enable_password_text_cmd,
+       "enable password LINE",
+       "Modify enable password parameters\n"
+       "Assign the privileged level password\n"
+       "The UNENCRYPTED (cleartext) 'enable' password\n")
+
+/* VTY enable password delete. */
+DEFUN (no_config_enable_password, no_enable_password_cmd,
+       "no enable password",
+       NO_STR
+       "Modify enable password parameters\n"
+       "Assign the privileged level password\n")
+{
+  if (host.enable)
+    XFREE (0, host.enable);
+  host.enable = NULL;
+
+  if (host.enable_encrypt)
+    XFREE (0, host.enable_encrypt);
+  host.enable_encrypt = NULL;
+
+  return CMD_SUCCESS;
+}
+	
+DEFUN (service_password_encrypt,
+       service_password_encrypt_cmd,
+       "service password-encryption",
+       "Set up miscellaneous service\n"
+       "Enable encrypted passwords\n")
+{
+  if (host.encrypt)
+    return CMD_SUCCESS;
+
+  host.encrypt = 1;
+
+  if (host.password)
+    {
+      if (host.password_encrypt)
+	XFREE (0, host.password_encrypt);
+      host.password_encrypt = XSTRDUP (0, zencrypt (host.password));
+    }
+  if (host.enable)
+    {
+      if (host.enable_encrypt)
+	XFREE (0, host.enable_encrypt);
+      host.enable_encrypt = XSTRDUP (0, zencrypt (host.enable));
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_service_password_encrypt,
+       no_service_password_encrypt_cmd,
+       "no service password-encryption",
+       NO_STR
+       "Set up miscellaneous service\n"
+       "Enable encrypted passwords\n")
+{
+  if (! host.encrypt)
+    return CMD_SUCCESS;
+
+  host.encrypt = 0;
+
+  if (host.password_encrypt)
+    XFREE (0, host.password_encrypt);
+  host.password_encrypt = NULL;
+
+  if (host.enable_encrypt)
+    XFREE (0, host.enable_encrypt);
+  host.enable_encrypt = NULL;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_terminal_length, config_terminal_length_cmd,
+       "terminal length <0-512>",
+       "Set terminal line parameters\n"
+       "Set number of lines on a screen\n"
+       "Number of lines on screen (0 for no pausing)\n")
+{
+  int lines;
+  char *endptr = NULL;
+
+  lines = strtol (argv[0], &endptr, 10);
+  if (lines < 0 || lines > 512 || *endptr != '\0')
+    {
+      vty_out (vty, "length is malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  vty->lines = lines;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_terminal_no_length, config_terminal_no_length_cmd,
+       "terminal no length",
+       "Set terminal line parameters\n"
+       NO_STR
+       "Set number of lines on a screen\n")
+{
+  vty->lines = -1;
+  return CMD_SUCCESS;
+}
+
+DEFUN (service_terminal_length, service_terminal_length_cmd,
+       "service terminal-length <0-512>",
+       "Set up miscellaneous service\n"
+       "System wide terminal length configuration\n"
+       "Number of lines of VTY (0 means no line control)\n")
+{
+  int lines;
+  char *endptr = NULL;
+
+  lines = strtol (argv[0], &endptr, 10);
+  if (lines < 0 || lines > 512 || *endptr != '\0')
+    {
+      vty_out (vty, "length is malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  host.lines = lines;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_service_terminal_length, no_service_terminal_length_cmd,
+       "no service terminal-length [<0-512>]",
+       NO_STR
+       "Set up miscellaneous service\n"
+       "System wide terminal length configuration\n"
+       "Number of lines of VTY (0 means no line control)\n")
+{
+  host.lines = -1;
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_log_stdout,
+       config_log_stdout_cmd,
+       "log stdout",
+       "Logging control\n"
+       "Logging goes to stdout\n")
+{
+  zlog_set_flag (NULL, ZLOG_STDOUT);
+  host.log_stdout = 1;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_config_log_stdout,
+       no_config_log_stdout_cmd,
+       "no log stdout",
+       NO_STR
+       "Logging control\n"
+       "Cancel logging to stdout\n")
+{
+  zlog_reset_flag (NULL, ZLOG_STDOUT);
+  host.log_stdout = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_log_file,
+       config_log_file_cmd,
+       "log file FILENAME",
+       "Logging control\n"
+       "Logging to file\n"
+       "Logging filename\n")
+{
+  int ret;
+  char *cwd;
+  char *fullpath;
+
+  /* Path detection. */
+  if (! IS_DIRECTORY_SEP (*argv[0]))
+    {
+      cwd = getcwd (NULL, MAXPATHLEN);
+      fullpath = XMALLOC (MTYPE_TMP,
+			  strlen (cwd) + strlen (argv[0]) + 2);
+      sprintf (fullpath, "%s/%s", cwd, argv[0]);
+    }
+  else
+    fullpath = argv[0];
+
+  ret = zlog_set_file (NULL, ZLOG_FILE, fullpath);
+
+  if (!ret)
+    {
+      vty_out (vty, "can't open logfile %s\n", argv[0]);
+      return CMD_WARNING;
+    }
+
+  if (host.logfile)
+    XFREE (MTYPE_TMP, host.logfile);
+
+  host.logfile = strdup (argv[0]);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_config_log_file,
+       no_config_log_file_cmd,
+       "no log file [FILENAME]",
+       NO_STR
+       "Logging control\n"
+       "Cancel logging to file\n"
+       "Logging file name\n")
+{
+  zlog_reset_file (NULL);
+
+  if (host.logfile)
+    XFREE (MTYPE_TMP, host.logfile);
+
+  host.logfile = NULL;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_log_syslog,
+       config_log_syslog_cmd,
+       "log syslog",
+       "Logging control\n"
+       "Logging goes to syslog\n")
+{
+  zlog_set_flag (NULL, ZLOG_SYSLOG);
+  host.log_syslog = 1;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_config_log_syslog,
+       no_config_log_syslog_cmd,
+       "no log syslog",
+       NO_STR
+       "Logging control\n"
+       "Cancel logging to syslog\n")
+{
+  zlog_reset_flag (NULL, ZLOG_SYSLOG);
+  host.log_syslog = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_log_trap,
+       config_log_trap_cmd,
+       "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)",
+       "Logging control\n"
+       "Limit logging to specifed level\n")
+{
+  int new_level ;
+  
+  for ( new_level = 0 ; zlog_priority [new_level] != NULL ; new_level ++ )
+    {
+    if ( strcmp ( argv[0], zlog_priority [new_level] ) == 0 )
+      /* found new logging level */
+      {
+      zlog_default->maskpri = new_level;
+      return CMD_SUCCESS;
+      }
+    }
+  return CMD_ERR_NO_MATCH;
+}
+
+DEFUN (no_config_log_trap,
+       no_config_log_trap_cmd,
+       "no log trap",
+       NO_STR
+       "Logging control\n"
+       "Permit all logging information\n")
+{
+  zlog_default->maskpri = LOG_DEBUG;
+  return CMD_SUCCESS;
+}
+
+DEFUN (config_log_record_priority,
+       config_log_record_priority_cmd,
+       "log record-priority",
+       "Logging control\n"
+       "Log the priority of the message within the message\n")
+{
+  zlog_default->record_priority = 1 ;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_config_log_record_priority,
+       no_config_log_record_priority_cmd,
+       "no log record-priority",
+       NO_STR
+       "Logging control\n"
+       "Do not log the priority of the message within the message\n")
+{
+  zlog_default->record_priority = 0 ;
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (banner_motd_default,
+       banner_motd_default_cmd,
+       "banner motd default",
+       "Set banner string\n"
+       "Strings for motd\n"
+       "Default string\n")
+{
+  host.motd = default_motd;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_banner_motd,
+       no_banner_motd_cmd,
+       "no banner motd",
+       NO_STR
+       "Set banner string\n"
+       "Strings for motd\n")
+{
+  host.motd = NULL;
+  return CMD_SUCCESS;
+}
+
+/* Set config filename.  Called from vty.c */
+void
+host_config_set (char *filename)
+{
+  host.config = strdup (filename);
+}
+
+void
+install_default (enum node_type node)
+{
+  install_element (node, &config_exit_cmd);
+  install_element (node, &config_quit_cmd);
+  install_element (node, &config_end_cmd);
+  install_element (node, &config_help_cmd);
+  install_element (node, &config_list_cmd);
+
+  install_element (node, &config_write_terminal_cmd);
+  install_element (node, &config_write_file_cmd);
+  install_element (node, &config_write_memory_cmd);
+  install_element (node, &config_write_cmd);
+}
+
+/* Initialize command interface. Install basic nodes and commands. */
+void
+cmd_init (int terminal)
+{
+  /* Allocate initial top vector of commands. */
+  cmdvec = vector_init (VECTOR_MIN_SIZE);
+
+  /* Default host value settings. */
+  host.name = NULL;
+  host.password = NULL;
+  host.enable = NULL;
+  host.logfile = NULL;
+  host.config = NULL;
+  host.lines = -1;
+  host.motd = default_motd;
+
+  /* Install top nodes. */
+  install_node (&view_node, NULL);
+  install_node (&enable_node, NULL);
+  install_node (&auth_node, NULL);
+  install_node (&auth_enable_node, NULL);
+  install_node (&config_node, config_write_host);
+
+  /* Each node's basic commands. */
+  install_element (VIEW_NODE, &show_version_cmd);
+  if (terminal)
+    {
+      install_element (VIEW_NODE, &config_list_cmd);
+      install_element (VIEW_NODE, &config_exit_cmd);
+      install_element (VIEW_NODE, &config_quit_cmd);
+      install_element (VIEW_NODE, &config_help_cmd);
+      install_element (VIEW_NODE, &config_enable_cmd);
+      install_element (VIEW_NODE, &config_terminal_length_cmd);
+      install_element (VIEW_NODE, &config_terminal_no_length_cmd);
+    }
+
+  if (terminal)
+    {
+      install_default (ENABLE_NODE);
+      install_element (ENABLE_NODE, &config_disable_cmd);
+      install_element (ENABLE_NODE, &config_terminal_cmd);
+      install_element (ENABLE_NODE, &show_running_config_cmd);
+      install_element (ENABLE_NODE, &copy_runningconfig_startupconfig_cmd);
+    }
+  install_element (ENABLE_NODE, &show_startup_config_cmd);
+  install_element (ENABLE_NODE, &show_version_cmd);
+  install_element (ENABLE_NODE, &config_terminal_length_cmd);
+  install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
+
+  if (terminal)
+    install_default (CONFIG_NODE);
+  install_element (CONFIG_NODE, &hostname_cmd);
+  install_element (CONFIG_NODE, &no_hostname_cmd);
+  install_element (CONFIG_NODE, &password_cmd);
+  install_element (CONFIG_NODE, &password_text_cmd);
+  install_element (CONFIG_NODE, &enable_password_cmd);
+  install_element (CONFIG_NODE, &enable_password_text_cmd);
+  install_element (CONFIG_NODE, &no_enable_password_cmd);
+  if (terminal)
+    {
+      install_element (CONFIG_NODE, &config_log_stdout_cmd);
+      install_element (CONFIG_NODE, &no_config_log_stdout_cmd);
+      install_element (CONFIG_NODE, &config_log_file_cmd);
+      install_element (CONFIG_NODE, &no_config_log_file_cmd);
+      install_element (CONFIG_NODE, &config_log_syslog_cmd);
+      install_element (CONFIG_NODE, &no_config_log_syslog_cmd);
+      install_element (CONFIG_NODE, &config_log_trap_cmd);
+      install_element (CONFIG_NODE, &no_config_log_trap_cmd);
+      install_element (CONFIG_NODE, &config_log_record_priority_cmd);
+      install_element (CONFIG_NODE, &no_config_log_record_priority_cmd);
+      install_element (CONFIG_NODE, &service_password_encrypt_cmd);
+      install_element (CONFIG_NODE, &no_service_password_encrypt_cmd);
+      install_element (CONFIG_NODE, &banner_motd_default_cmd);
+      install_element (CONFIG_NODE, &no_banner_motd_cmd);
+      install_element (CONFIG_NODE, &service_terminal_length_cmd);
+      install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
+    }
+
+  srand(time(NULL));
+}
diff --git a/isisd/modified/command.h b/isisd/modified/command.h
new file mode 100644
index 0000000..d407c5a
--- /dev/null
+++ b/isisd/modified/command.h
@@ -0,0 +1,311 @@
+/*
+ * Zebra configuration command interface routine
+ * Copyright (C) 1997, 98 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.
+ */
+
+#ifndef _ZEBRA_COMMAND_H
+#define _ZEBRA_COMMAND_H
+
+#include "vector.h"
+#include "vty.h"
+
+/* Host configuration variable */
+struct host
+{
+  /* Host name of this router. */
+  char *name;
+
+  /* Password for vty interface. */
+  char *password;
+  char *password_encrypt;
+
+  /* Enable password */
+  char *enable;
+  char *enable_encrypt;
+
+  /* System wide terminal lines. */
+  int lines;
+
+  /* Log filename. */
+  char *logfile;
+
+  /* Log stdout. */
+  u_char log_stdout;
+
+  /* Log syslog. */
+  u_char log_syslog;
+  
+  /* config file name of this host */
+  char *config;
+
+  /* Flags for services */
+  int advanced;
+  int encrypt;
+
+  /* Banner configuration. */
+  char *motd;
+};
+
+/* There are some command levels which called from command node. */
+enum node_type 
+{
+  AUTH_NODE,			/* Authentication mode of vty interface. */
+  VIEW_NODE,			/* View node. Default mode of vty interface. */
+  AUTH_ENABLE_NODE,		/* Authentication mode for change enable. */
+  ENABLE_NODE,			/* Enable node. */
+  CONFIG_NODE,			/* Config node. Default mode of config file. */
+  DEBUG_NODE,			/* Debug node. */
+  AAA_NODE,			/* AAA node. */
+  KEYCHAIN_NODE,		/* Key-chain node. */
+  KEYCHAIN_KEY_NODE,		/* Key-chain key node. */
+  INTERFACE_NODE,		/* Interface mode node. */
+  ZEBRA_NODE,			/* zebra connection node. */
+  TABLE_NODE,			/* rtm_table selection node. */
+  RIP_NODE,			/* RIP protocol mode node. */ 
+  RIPNG_NODE,			/* RIPng protocol mode node. */
+  BGP_NODE,			/* BGP protocol mode which includes BGP4+ */
+  BGP_VPNV4_NODE,		/* BGP MPLS-VPN PE exchange. */
+  BGP_IPV4_NODE,		/* BGP IPv4 unicast address family.  */
+  BGP_IPV4M_NODE,		/* BGP IPv4 multicast address family.  */
+  BGP_IPV6_NODE,		/* BGP IPv6 address family */
+  OSPF_NODE,			/* OSPF protocol mode */
+  OSPF6_NODE,			/* OSPF protocol for IPv6 mode */
+  ISIS_NODE,                    /* IS-IS protocol mode */
+  MASC_NODE,			/* MASC for multicast.  */
+  IRDP_NODE,			/* ICMP Router Discovery Protocol mode. */ 
+  IP_NODE,			/* Static ip route node. */
+  ACCESS_NODE,			/* Access list node. */
+  PREFIX_NODE,			/* Prefix list node. */
+  ACCESS_IPV6_NODE,		/* Access list node. */
+  PREFIX_IPV6_NODE,		/* Prefix list node. */
+  AS_LIST_NODE,			/* AS list node. */
+  COMMUNITY_LIST_NODE,		/* Community list node. */
+  RMAP_NODE,			/* Route map node. */
+  SMUX_NODE,			/* SNMP configuration node. */
+  DUMP_NODE,			/* Packet dump node. */
+  FORWARDING_NODE,		/* IP forwarding node. */
+  VTY_NODE			/* Vty node. */
+};
+
+/* Node which has some commands and prompt string and configuration
+   function pointer . */
+struct cmd_node 
+{
+  /* Node index. */
+  enum node_type node;		
+
+  /* Prompt character at vty interface. */
+  char *prompt;			
+
+  /* Is this node's configuration goes to vtysh ? */
+  int vtysh;
+  
+  /* Node's configuration write function */
+  int (*func) (struct vty *);
+
+  /* Vector of this node's command list. */
+  vector cmd_vector;	
+};
+
+/* Structure of command element. */
+struct cmd_element 
+{
+  char *string;			/* Command specification by string. */
+  int (*func) (struct cmd_element *, struct vty *, int, char **);
+  char *doc;			/* Documentation of this command. */
+  int daemon;                   /* Daemon to which this command belong. */
+  vector strvec;		/* Pointing out each description vector. */
+  int cmdsize;			/* Command index count. */
+  char *config;			/* Configuration string */
+  vector subconfig;		/* Sub configuration string */
+};
+
+/* Command description structure. */
+struct desc
+{
+  char *cmd;			/* Command string. */
+  char *str;			/* Command's description. */
+};
+
+/* Return value of the commands. */
+#define CMD_SUCCESS              0
+#define CMD_WARNING              1
+#define CMD_ERR_NO_MATCH         2
+#define CMD_ERR_AMBIGUOUS        3
+#define CMD_ERR_INCOMPLETE       4
+#define CMD_ERR_EXEED_ARGC_MAX   5
+#define CMD_ERR_NOTHING_TODO     6
+#define CMD_COMPLETE_FULL_MATCH  7
+#define CMD_COMPLETE_MATCH       8
+#define CMD_COMPLETE_LIST_MATCH  9
+#define CMD_SUCCESS_DAEMON      10
+
+/* Argc max counts. */
+#define CMD_ARGC_MAX   25
+
+/* Turn off these macros when uisng cpp with extract.pl */
+#ifndef VTYSH_EXTRACT_PL  
+
+/* DEFUN for vty command interafce. Little bit hacky ;-). */
+#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
+  int funcname (struct cmd_element *, struct vty *, int, char **); \
+  struct cmd_element cmdname = \
+  { \
+    cmdstr, \
+    funcname, \
+    helpstr \
+  }; \
+  int funcname \
+  (struct cmd_element *self, struct vty *vty, int argc, char **argv)
+
+/* DEFUN_NOSH for commands that vtysh should ignore */
+#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN(funcname, cmdname, cmdstr, helpstr)
+
+/* DEFSH for vtysh. */
+#define DEFSH(daemon, cmdname, cmdstr, helpstr) \
+  struct cmd_element cmdname = \
+  { \
+    cmdstr, \
+    NULL, \
+    helpstr, \
+    daemon \
+  }; \
+
+/* DEFUN + DEFSH */
+#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
+  int funcname (struct cmd_element *, struct vty *, int, char **); \
+  struct cmd_element cmdname = \
+  { \
+    cmdstr, \
+    funcname, \
+    helpstr, \
+    daemon \
+  }; \
+  int funcname \
+  (struct cmd_element *self, struct vty *vty, int argc, char **argv)
+
+/* ALIAS macro which define existing command's alias. */
+#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
+  struct cmd_element cmdname = \
+  { \
+    cmdstr, \
+    funcname, \
+    helpstr \
+  };
+
+#endif /* VTYSH_EXTRACT_PL */
+
+/* Some macroes */
+#define CMD_OPTION(S)   ((S[0]) == '[')
+#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<'))
+#define CMD_VARARG(S)   ((S[0]) == '.')
+#define CMD_RANGE(S)	((S[0] == '<'))
+
+#define CMD_IPV4(S)	   ((strcmp ((S), "A.B.C.D") == 0))
+#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0))
+#define CMD_IPV6(S)        ((strcmp ((S), "X:X::X:X") == 0))
+#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
+
+/* Common descriptions. */
+#define SHOW_STR "Show running system information\n"
+#define IP_STR "IP information\n"
+#define IPV6_STR "IPv6 information\n"
+#define NO_STR "Negate a command or set its defaults\n"
+#define CLEAR_STR "Reset functions\n"
+#define RIP_STR "RIP information\n"
+#define BGP_STR "BGP information\n"
+#define OSPF_STR "OSPF information\n"
+#define NEIGHBOR_STR "Specify neighbor router\n"
+#define DEBUG_STR "Debugging functions (see also 'undebug')\n"
+#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
+#define ROUTER_STR "Enable a routing process\n"
+#define AS_STR "AS number\n"
+#define MBGP_STR "MBGP information\n"
+#define MATCH_STR "Match values from routing table\n"
+#define SET_STR "Set values in destination routing protocol\n"
+#define OUT_STR "Filter outgoing routing updates\n"
+#define IN_STR  "Filter incoming routing updates\n"
+#define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n"
+#define OSPF6_NUMBER_STR "Specify by number\n"
+#define INTERFACE_STR "Interface infomation\n"
+#define IFNAME_STR "Interface name(e.g. ep0)\n"
+#define IP6_STR "IPv6 Information\n"
+#define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n"
+#define OSPF6_ROUTER_STR "Enable a routing process\n"
+#define OSPF6_INSTANCE_STR "<1-65535> Instance ID\n"
+#define SECONDS_STR "<1-65535> Seconds\n"
+#define ROUTE_STR "Routing Table\n"
+#define PREFIX_LIST_STR "Build a prefix list\n"
+#define OSPF6_DUMP_TYPE_LIST \
+"(neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr)"
+#define ISIS_STR "IS-IS information\n"
+#define AREA_TAG_STR "[area tag]\n"
+
+#define CONF_BACKUP_EXT ".sav"
+
+/* IPv4 only machine should not accept IPv6 address for peer's IP
+   address.  So we replace VTY command string like below. */
+#ifdef HAVE_IPV6
+#define NEIGHBOR_CMD       "neighbor (A.B.C.D|X:X::X:X) "
+#define NO_NEIGHBOR_CMD    "no neighbor (A.B.C.D|X:X::X:X) "
+#define NEIGHBOR_ADDR_STR  "Neighbor address\nIPv6 address\n"
+#define NEIGHBOR_CMD2      "neighbor (A.B.C.D|X:X::X:X|WORD) "
+#define NO_NEIGHBOR_CMD2   "no neighbor (A.B.C.D|X:X::X:X|WORD) "
+#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor IPv6 address\nNeighbor tag\n"
+#else
+#define NEIGHBOR_CMD       "neighbor A.B.C.D "
+#define NO_NEIGHBOR_CMD    "no neighbor A.B.C.D "
+#define NEIGHBOR_ADDR_STR  "Neighbor address\n"
+#define NEIGHBOR_CMD2      "neighbor (A.B.C.D|WORD) "
+#define NO_NEIGHBOR_CMD2   "no neighbor (A.B.C.D|WORD) "
+#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor tag\n"
+#endif /* HAVE_IPV6 */
+
+/* Prototypes. */
+void install_node (struct cmd_node *, int (*) (struct vty *));
+void install_default (enum node_type);
+void install_element (enum node_type, struct cmd_element *);
+void sort_node ();
+
+char *argv_concat (char **, int, int);
+vector cmd_make_strvec (char *);
+void cmd_free_strvec (vector);
+vector cmd_describe_command ();
+char **cmd_complete_command ();
+char *cmd_prompt (enum node_type);
+int config_from_file (struct vty *, FILE *);
+int cmd_execute_command (vector, struct vty *, struct cmd_element **);
+int cmd_execute_command_strict (vector, struct vty *, struct cmd_element **);
+void config_replace_string (struct cmd_element *, char *, ...);
+void cmd_init (int);
+
+/* Export typical functions. */
+extern struct cmd_element config_end_cmd;
+extern struct cmd_element config_exit_cmd;
+extern struct cmd_element config_quit_cmd;
+extern struct cmd_element config_help_cmd;
+extern struct cmd_element config_list_cmd;
+int config_exit (struct cmd_element *, struct vty *, int, char **);
+int config_help (struct cmd_element *, struct vty *, int, char **);
+char *host_config_file ();
+void host_config_set (char *);
+
+#endif /* _ZEBRA_COMMAND_H */
diff --git a/isisd/modified/config.h.in b/isisd/modified/config.h.in
new file mode 100644
index 0000000..c06839e
--- /dev/null
+++ b/isisd/modified/config.h.in
@@ -0,0 +1,368 @@
+/* config.h.in.  Generated from configure.in by autoheader.  */
+/* accconfig.h -- `autoheader' will generate config.h.in for zebra.
+   Copyright (C) 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org> */
+
+/* Version of GNU Zebra */
+#undef VERSION
+
+/* Solaris on x86. */
+#undef SOLARIS_X86
+
+/* Package name of GNU Zebra */
+#undef PACKAGE
+
+/* Define if host is GNU/Linux */
+#undef GNU_LINUX
+
+/* Define if you have the AF_ROUTE socket.  */
+#undef HAVE_AF_ROUTE
+
+/* Define if you have the inet_aton function.  */
+#undef HAVE_INET_ATON
+
+/* Define if you have the inet_ntop function.  */
+#undef HAVE_INET_NTOP
+
+/* Define if you have the inet_pton function.  */
+#undef HAVE_INET_PTON
+
+/* Define if you have the setproctitle function.  */
+#undef HAVE_SETPROCTITLE
+
+/* Define if you have ipv6 stack.  */
+#undef HAVE_IPV6
+
+/* Define if you wish to support ipv6 router advertisment.  */
+/* #undef HAVE_RTADV */
+
+/* whether system has GNU regex */
+#undef HAVE_GNU_REGEX
+
+/* whether system has SNMP library */
+#undef HAVE_SNMP
+
+/* whether sockaddr has a sa_len field */
+#undef HAVE_SA_LEN
+
+/* whether sockaddr_in has a sin_len field */
+#undef HAVE_SIN_LEN
+
+/* whether sockaddr_un has a sun_len field */
+#undef HAVE_SUN_LEN
+
+/* whether sockaddr_in6 has a sin6_scope_id field */
+#undef HAVE_SIN6_SCOPE_ID
+
+/* Define if there is socklen_t. */
+#undef HAVE_SOCKLEN_T
+
+/* Define if there is sockaddr_dl structure. */
+#undef HAVE_SOCKADDR_DL
+
+/* Define if there is ifaliasreq structure. */
+#undef HAVE_IFALIASREQ
+
+/* Define if there is in6_aliasreq structure. */
+#undef HAVE_IN6_ALIASREQ
+
+/* Define if there is rt_addrinfo structure. */
+#undef HAVE_RT_ADDRINFO
+
+/* Define if there is in_pktinfo structure. */
+#undef HAVE_INPKTINFO
+
+/* Define if you have the getrusage function. */
+#undef HAVE_RUSAGE
+
+/* Define if /proc/net/dev exists. */
+#undef HAVE_PROC_NET_DEV
+
+/* Define if /proc/net/if_inet6 exists. */
+#undef HAVE_PROC_NET_IF_INET6
+
+/* Define if NET_RT_IFLIST exists in sys/socket.h. */
+#undef HAVE_NET_RT_IFLIST
+
+/* Define if you have INRIA ipv6 stack.  */
+#undef INRIA_IPV6
+
+/* Define if you have KAME project ipv6 stack.  */
+#undef KAME
+
+/* Define if you have Linux ipv6 stack.  */
+#undef LINUX_IPV6
+
+/* Define if you have NRL ipv6 stack.  */
+#undef NRL
+
+/* Define if you have BSDI NRL IPv6 stack. */
+#undef BSDI_NRL
+
+/* Define if one-vty option is specified. */
+#undef VTYSH
+
+/* Define if interface aliases don't have distinct indeces */
+#undef HAVE_BROKEN_ALIASES
+
+/* Define if disable-bgp-announce option is specified. */
+#undef DISABLE_BGP_ANNOUNCE
+
+/* PAM support */
+#undef USE_PAM
+
+/* TCP/IP communication between zebra and protocol daemon. */
+#undef HAVE_TCP_ZEBRA
+
+/* The OSPF NSSA option (RFC1587). */
+#undef HAVE_NSSA
+
+/* The OSPF Opaque LSA option (RFC2370). */
+#undef HAVE_OPAQUE_LSA
+
+/* Traffic Engineering Extension to OSPF
+   (draft-katz-yeung-ospf-traffic-06.txt). */
+#undef HAVE_OSPF_TE
+
+/* Linux netlink. */
+#undef HAVE_NETLINK
+
+/* PATHS */
+#undef PATH_ZEBRA_PID
+#undef PATH_RIPD_PID
+#undef PATH_RIPNGD_PID
+#undef PATH_BGPD_PID
+#undef PATH_OSPFD_PID
+#undef PATH_OSPF6D_PID
+#undef PATH_ISISD_PID
+
+/* Define if Solaris */
+#undef SUNOS_5
+
+/* Define if FreeBSD 3.2 */
+#undef FREEBSD_32
+
+/* Define if OpenBSD */
+#undef OPEN_BSD
+
+#ifdef HAVE_IPV6
+#ifdef KAME
+#ifndef INET6
+#define INET6
+#endif /* INET6 */
+#endif /* KAME */
+#endif /* HAVE_IPV6 */
+
+#ifdef SUNOS_5
+typedef unsigned int u_int32_t; 
+typedef unsigned short u_int16_t; 
+typedef unsigned short u_int8_t; 
+#endif /* SUNOS_5 */
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif /* HAVE_SOCKLEN_T */
+
+/* Define to 1 if you have the <asm/types.h> header file. */
+#undef HAVE_ASM_TYPES_H
+
+/* Define to 1 if you have the `bcopy' function. */
+#undef HAVE_BCOPY
+
+/* Define to 1 if you have the `bzero' function. */
+#undef HAVE_BZERO
+
+/* Define to 1 if you have the `daemon' function. */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#undef HAVE_GETIFADDRS
+
+/* Define to 1 if you have the `if_indextoname' function. */
+#undef HAVE_IF_INDEXTONAME
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#undef HAVE_IF_NAMETOINDEX
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if you have the <inet/nd.h> header file. */
+#undef HAVE_INET_ND_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <kvm.h> header file. */
+#undef HAVE_KVM_H
+
+/* Define to 1 if you have the `crypt' library (-lcrypt). */
+#undef HAVE_LIBCRYPT
+
+/* Define to 1 if you have the `kvm' library (-lkvm). */
+#undef HAVE_LIBKVM
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the `ncurses' library (-lncurses). */
+#undef HAVE_LIBNCURSES
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `readline' library (-lreadline). */
+#undef HAVE_LIBREADLINE
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the `tinfo' library (-ltinfo). */
+#undef HAVE_LIBTINFO
+
+/* Define to 1 if you have the <libutil.h> header file. */
+#undef HAVE_LIBUTIL_H
+
+/* Define to 1 if you have the `xnet' library (-lxnet). */
+#undef HAVE_LIBXNET
+
+/* Define to 1 if you have the <linux/version.h> header file. */
+#undef HAVE_LINUX_VERSION_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet6/nd6.h> header file. */
+#undef HAVE_NETINET6_ND6_H
+
+/* Define to 1 if you have the <netinet/icmp6.h> header file. */
+#undef HAVE_NETINET_ICMP6_H
+
+/* Define to 1 if you have the <netinet/in6.h> header file. */
+#undef HAVE_NETINET_IN6_H
+
+/* Define to 1 if you have the <netinet/in6_var.h> header file. */
+#undef HAVE_NETINET_IN6_VAR_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/in_var.h> header file. */
+#undef HAVE_NETINET_IN_VAR_H
+
+/* Define to 1 if you have the <net/if_dl.h> header file. */
+#undef HAVE_NET_IF_DL_H
+
+/* Define to 1 if you have the <net/if_var.h> header file. */
+#undef HAVE_NET_IF_VAR_H
+
+/* Define to 1 if you have the <net/netopt.h> header file. */
+#undef HAVE_NET_NETOPT_H
+
+/* Define to 1 if you have the `setproctitle' function. */
+#undef HAVE_SETPROCTITLE
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the <stropts.h> header file. */
+#undef HAVE_STROPTS_H
+
+/* Define to 1 if you have the <sys/conf.h> header file. */
+#undef HAVE_SYS_CONF_H
+
+/* Define to 1 if you have the <sys/ksym.h> header file. */
+#undef HAVE_SYS_KSYM_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
+/* Define to 1 if you have the <sys/times.h> header file. */
+#undef HAVE_SYS_TIMES_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
diff --git a/isisd/modified/configure b/isisd/modified/configure
new file mode 100755
index 0000000..e4bf6d4
--- /dev/null
+++ b/isisd/modified/configure
@@ -0,0 +1,8277 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.53.
+#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# NLS nuisances.
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+    { $as_unset LANG || test "${LANG+set}" != set; } ||
+      { LANG=C; export LANG; }
+(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+      { LC_ALL=C; export LC_ALL; }
+(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+      { LC_TIME=C; export LC_TIME; }
+(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+      { LC_CTYPE=C; export LC_CTYPE; }
+(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+      { LANGUAGE=C; export LANGUAGE; }
+(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+      { LC_COLLATE=C; export LC_COLLATE; }
+(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+      { LC_NUMERIC=C; export LC_NUMERIC; }
+(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+      { LC_MESSAGES=C; export LC_MESSAGES; }
+
+
+# Name of the executable.
+as_me=`(basename "$0") 2>/dev/null ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conftest.sh
+  echo  "exit 0"   >>conftest.sh
+  chmod +x conftest.sh
+  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conftest.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="lib/zebra.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+              localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$0" : 'X\(//\)[^/]' \| \
+         X"$0" : 'X\(//\)$' \| \
+         X"$0" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-dependency-tracking Speeds up one-time builds
+  --enable-dependency-tracking  Do not reject slow dependency extractors
+  --enable-vtysh,       Make integrated VTY version of zebra
+  --disable-ipv6          turn off IPv6 related features and daemons
+  --disable-zebra         do not build zebra daemon
+  --disable-bgpd          do not build bgpd
+  --disable-ripd          do not build ripd
+  --disable-ripngd        do not build ripngd
+  --disable-ospfd         do not build ospfd
+  --disable-ospf6d        do not build ospf6d
+  --disable-isisd         do not build isisd
+  --disable-bgp-announce, turn off BGP route announcement
+  --enable-netlink        force to use Linux netlink interface
+  --enable-broken-aliases enable aliases as distinct interfaces for Linux 2.2.X
+  --enable-snmp           enable SNMP support
+  --enable-tcp-zebra      enable TCP/IP socket connection between zebra and protocol daemon
+  --enable-nssa           enable OSPF NSSA option
+  --enable-opaque-lsa     enable OSPF Opaque-LSA support (RFC2370)
+  --enable-ospf-te        enable Traffic Engineering Extension to OSPF
+  --enable-multipath=ARG  enable multipath function, ARG must be digit
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-cflags           Set CFLAGS for use in compilation.
+  --with-libpam           use libpam for PAM support in vtysh
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+           test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.53.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell meta-characters.
+ac_configure_args=
+ac_sep=
+for ac_arg
+do
+  case $ac_arg in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n ) continue ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    continue ;;
+  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+    ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+  esac
+  case " $ac_configure_args " in
+    *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+    *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+       ac_sep=" " ;;
+  esac
+  # Get rid of the leading space.
+done
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+        "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core core.* *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+               sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+        { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+        { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+        { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+        ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+am__api_version="1.6"
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+        if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+          if test $ac_prog = install &&
+            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # AIX install.  It has an incompatible calling convention.
+            :
+          elif test $ac_prog = install &&
+            grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # program-specific install script used by HP pwplus--don't use.
+            :
+          else
+            ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+            break 3
+          fi
+        fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$AWK" && break
+done
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+	@echo 'ac_maketemp="${MAKE}"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+ # test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# Define the identity of the package.
+ PACKAGE=zebra
+ VERSION=0.93
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  STRIP=$ac_ct_STRIP
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+
+
+
+# Add the stamp file to the list of files AC keeps track of,
+# along with our hook.
+ac_config_headers="$ac_config_headers config.h"
+
+
+
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+
+
+# Check whether --with-cflags or --without-cflags was given.
+if test "${with_cflags+set}" = set; then
+  withval="$with_cflags"
+
+fi;
+if test "x$with_cflags" != "x" ; then
+  CFLAGS="$with_cflags" ; cflags_specified=yes ;
+elif test -n "$CFLAGS" ; then
+  cflags_specified=yes ;
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$as_dir/$ac_word" ${1+"$@"}
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output" >&5
+echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null;
+                ls a.out conftest 2>/dev/null;
+                ls a.* conftest.* 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;;
+    a.out ) # We found the default executable, but exeext='' is most
+            # certainly right.
+            break;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          # FIXME: I believe we export ac_cv_exeext for Libtool --akim.
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5
+echo "$as_me: error: C compiler cannot create executables" >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   ''\
+   '#include <stdlib.h>' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+$ac_declaration
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_declaration
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+rm -f .deps 2>/dev/null
+mkdir .deps 2>/dev/null
+if test -d .deps; then
+  DEPDIR=.deps
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  DEPDIR=_deps
+fi
+rmdir .deps 2>/dev/null
+
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+doit:
+	@echo done
+END
+# If we don't find an include directive, just comment out the code.
+echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+
+
+echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval="$enable_dependency_tracking"
+
+fi;
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+
+depcc="$CC"   am_compiler_list=
+
+echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    echo '#include "conftest.h"' > conftest.c
+    echo 'int i;' > conftest.h
+    echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=conftest.c object=conftest.o \
+       depfile=conftest.Po tmpdepfile=conftest.TPo \
+       $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 &&
+       grep conftest.h conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      am_cv_CC_dependencies_compiler_type=$depmode
+      break
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+
+
+if test "x$cflags_specified" = "x" ; then
+  CFLAGS="$CFLAGS -Wall"
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+        if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+          if test $ac_prog = install &&
+            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # AIX install.  It has an incompatible calling convention.
+            :
+          elif test $ac_prog = install &&
+            grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # program-specific install script used by HP pwplus--don't use.
+            :
+          else
+            ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+            break 3
+          fi
+        fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+	@echo 'ac_maketemp="${MAKE}"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="ar"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  AR=$ac_ct_AR
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+
+
+echo "$as_me:$LINENO: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#ifdef _AIX
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\_ACEOF
+#define _ALL_SOURCE 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+
+# Check whether --enable-vtysh or --disable-vtysh was given.
+if test "${enable_vtysh+set}" = set; then
+  enableval="$enable_vtysh"
+
+fi;
+# Check whether --enable-ipv6 or --disable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then
+  enableval="$enable_ipv6"
+
+fi;
+# Check whether --enable-zebra or --disable-zebra was given.
+if test "${enable_zebra+set}" = set; then
+  enableval="$enable_zebra"
+
+fi;
+# Check whether --enable-bgpd or --disable-bgpd was given.
+if test "${enable_bgpd+set}" = set; then
+  enableval="$enable_bgpd"
+
+fi;
+# Check whether --enable-ripd or --disable-ripd was given.
+if test "${enable_ripd+set}" = set; then
+  enableval="$enable_ripd"
+
+fi;
+# Check whether --enable-ripngd or --disable-ripngd was given.
+if test "${enable_ripngd+set}" = set; then
+  enableval="$enable_ripngd"
+
+fi;
+# Check whether --enable-ospfd or --disable-ospfd was given.
+if test "${enable_ospfd+set}" = set; then
+  enableval="$enable_ospfd"
+
+fi;
+# Check whether --enable-ospf6d or --disable-ospf6d was given.
+if test "${enable_ospf6d+set}" = set; then
+  enableval="$enable_ospf6d"
+
+fi;
+# Check whether --enable-isisd or --disable-isisd was given.
+if test "${enable_isisd+set}" = set; then
+  enableval="$enable_isisd"
+
+fi;
+# Check whether --enable-bgp-announce or --disable-bgp-announce was given.
+if test "${enable_bgp_announce+set}" = set; then
+  enableval="$enable_bgp_announce"
+
+fi;
+# Check whether --enable-netlink or --disable-netlink was given.
+if test "${enable_netlink+set}" = set; then
+  enableval="$enable_netlink"
+
+fi;
+# Check whether --enable-broken-aliases or --disable-broken-aliases was given.
+if test "${enable_broken_aliases+set}" = set; then
+  enableval="$enable_broken_aliases"
+
+fi;
+# Check whether --enable-snmp or --disable-snmp was given.
+if test "${enable_snmp+set}" = set; then
+  enableval="$enable_snmp"
+
+fi;
+
+# Check whether --with-libpam or --without-libpam was given.
+if test "${with_libpam+set}" = set; then
+  withval="$with_libpam"
+
+fi;
+# Check whether --enable-tcpsock or --disable-tcpsock was given.
+if test "${enable_tcpsock+set}" = set; then
+  enableval="$enable_tcpsock"
+
+fi;
+# Check whether --enable-nssa or --disable-nssa was given.
+if test "${enable_nssa+set}" = set; then
+  enableval="$enable_nssa"
+
+fi;
+# Check whether --enable-opaque-lsa or --disable-opaque-lsa was given.
+if test "${enable_opaque_lsa+set}" = set; then
+  enableval="$enable_opaque_lsa"
+
+fi;
+# Check whether --enable-ospf-te or --disable-ospf-te was given.
+if test "${enable_ospf_te+set}" = set; then
+  enableval="$enable_ospf_te"
+
+fi;
+# Check whether --enable-multipath or --disable-multipath was given.
+if test "${enable_multipath+set}" = set; then
+  enableval="$enable_multipath"
+
+fi;
+
+
+if test "${enable_broken_aliases}" = "yes"; then
+  if test "${enable_netlink}" = "yes"
+  then
+    echo "Sorry, you can't use netlink with broken aliases"
+    exit 1
+  fi
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_BROKEN_ALIASES 1
+_ACEOF
+
+  enable_netlink=no
+fi
+
+if test "${enable_tcp_zebra}" = "yes"; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_TCP_ZEBRA 1
+_ACEOF
+
+fi
+
+if test "${enable_nssa}" = "yes"; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_NSSA 1
+_ACEOF
+
+fi
+
+if test "${enable_opaque_lsa}" = "yes"; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_OPAQUE_LSA 1
+_ACEOF
+
+fi
+
+if test "${enable_ospf_te}" = "yes"; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_OPAQUE_LSA 1
+_ACEOF
+
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_OSPF_TE 1
+_ACEOF
+
+fi
+
+
+
+MULTIPATH_NUM=1
+
+case "${enable_multipath}" in
+  [0-9]|[1-9][0-9])
+    MULTIPATH_NUM="${enable_multipath}"
+    ;;
+  "")
+    ;;
+  *)
+    echo "Please specify digit to --enable-multipath ARG."
+    exit 1
+    ;;
+esac
+
+
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \
+                     || ('j' <= (c) && (c) <= 'r') \
+                     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+        || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in string.h stropts.h sys/conf.h sys/ksym.h sys/time.h sys/times.h sys/select.h sys/sysctl.h sys/sockio.h sys/types.h net/if_dl.h net/if_var.h linux/version.h kvm.h netdb.h netinet/in.h net/netopt.h netinet/in_var.h netinet/in6_var.h netinet/in6.h inet/nd.h asm/types.h netinet/icmp6.h netinet6/nd6.h libutil.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+  yes:no )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+  no:yes )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset x;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *ccp;
+  char **p;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  ccp = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++ccp;
+  p = (char**) ccp;
+  ccp = (char const *const *) p;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+  }
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_c_const=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
+if test "${ac_cv_type_signal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_signal=int
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+case "$host" in
+  *-sunos5.6* | *-solaris2.6*)
+      opsys=sol2-6
+      cat >>confdefs.h <<\_ACEOF
+#define SUNOS_5 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for main in -lxnet" >&5
+echo $ECHO_N "checking for main in -lxnet... $ECHO_C" >&6
+if test "${ac_cv_lib_xnet_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxnet  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_xnet_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_xnet_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_xnet_main" >&5
+echo "${ECHO_T}$ac_cv_lib_xnet_main" >&6
+if test $ac_cv_lib_xnet_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXNET 1
+_ACEOF
+
+  LIBS="-lxnet $LIBS"
+
+fi
+
+      CURSES=-lcurses
+  ;;
+  *-sunos5* | *-solaris2*)
+      cat >>confdefs.h <<\_ACEOF
+#define SUNOS_5 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for main in -lsocket" >&5
+echo $ECHO_N "checking for main in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_socket_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_main" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_main" >&6
+if test $ac_cv_lib_socket_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for main in -lnsl" >&5
+echo $ECHO_N "checking for main in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_nsl_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_nsl_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_main" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_main" >&6
+if test $ac_cv_lib_nsl_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+  LIBS="-lnsl $LIBS"
+
+fi
+
+      CURSES=-lcurses
+  ;;
+  *-linux-*)
+      opsys=gnu-linux
+      cat >>confdefs.h <<\_ACEOF
+#define GNU_LINUX 1
+_ACEOF
+
+  ;;
+  *-nec-sysv4*)
+
+echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5
+echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gethostbyname ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_nsl_gethostbyname=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_nsl_gethostbyname=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6
+if test $ac_cv_lib_nsl_gethostbyname = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+  LIBS="-lnsl $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+socket ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_socket_socket=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6
+if test $ac_cv_lib_socket_socket = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+fi
+
+  ;;
+  *-freebsd3.2)
+      cat >>confdefs.h <<\_ACEOF
+#define FREEBSD_32 1
+_ACEOF
+
+  ;;
+  *-openbsd*)
+      opsys=openbsd
+      cat >>confdefs.h <<\_ACEOF
+#define OPEN_BSD 1
+_ACEOF
+
+  ;;
+  *-bsdi*)
+      opsys=bsdi
+      OTHER_METHOD="mtu_kvm.o"
+
+echo "$as_me:$LINENO: checking for main in -lkvm" >&5
+echo $ECHO_N "checking for main in -lkvm... $ECHO_C" >&6
+if test "${ac_cv_lib_kvm_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkvm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_kvm_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_kvm_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_kvm_main" >&5
+echo "${ECHO_T}$ac_cv_lib_kvm_main" >&6
+if test $ac_cv_lib_kvm_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBKVM 1
+_ACEOF
+
+  LIBS="-lkvm $LIBS"
+
+fi
+
+  ;;
+esac
+
+case "${host_cpu}-${host_os}" in
+  i?86-solaris*)
+    cat >>confdefs.h <<\_ACEOF
+#define SOLARIS_X86 1
+_ACEOF
+
+  ;;
+esac
+
+case "${enable_vtysh}" in
+  "yes") VTYSH="vtysh";
+         cat >>confdefs.h <<\_ACEOF
+#define VTYSH 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for tputs in -ltinfo" >&5
+echo $ECHO_N "checking for tputs in -ltinfo... $ECHO_C" >&6
+if test "${ac_cv_lib_tinfo_tputs+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltinfo  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char tputs ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+tputs ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_tinfo_tputs=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_tinfo_tputs=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_tinfo_tputs" >&5
+echo "${ECHO_T}$ac_cv_lib_tinfo_tputs" >&6
+if test $ac_cv_lib_tinfo_tputs = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBTINFO 1
+_ACEOF
+
+  LIBS="-ltinfo $LIBS"
+
+else
+
+echo "$as_me:$LINENO: checking for tputs in -lncurses" >&5
+echo $ECHO_N "checking for tputs in -lncurses... $ECHO_C" >&6
+if test "${ac_cv_lib_ncurses_tputs+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lncurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char tputs ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+tputs ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ncurses_tputs=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_ncurses_tputs=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_tputs" >&5
+echo "${ECHO_T}$ac_cv_lib_ncurses_tputs" >&6
+if test $ac_cv_lib_ncurses_tputs = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNCURSES 1
+_ACEOF
+
+  LIBS="-lncurses $LIBS"
+
+fi
+
+fi
+
+
+echo "$as_me:$LINENO: checking for main in -lreadline" >&5
+echo $ECHO_N "checking for main in -lreadline... $ECHO_C" >&6
+if test "${ac_cv_lib_readline_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_readline_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_readline_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_readline_main" >&5
+echo "${ECHO_T}$ac_cv_lib_readline_main" >&6
+if test $ac_cv_lib_readline_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBREADLINE 1
+_ACEOF
+
+  LIBS="-lreadline $LIBS"
+
+fi
+
+         if test $ac_cv_lib_readline_main = no; then
+           { { echo "$as_me:$LINENO: error: vtysh needs libreadline but was not found on your system." >&5
+echo "$as_me: error: vtysh needs libreadline but was not found on your system." >&2;}
+   { (exit 1); exit 1; }; }
+         fi
+	 if test "${ac_cv_header_readline_history_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for readline/history.h" >&5
+echo $ECHO_N "checking for readline/history.h... $ECHO_C" >&6
+if test "${ac_cv_header_readline_history_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_readline_history_h" >&5
+echo "${ECHO_T}$ac_cv_header_readline_history_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking readline/history.h usability" >&5
+echo $ECHO_N "checking readline/history.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#include <readline/history.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking readline/history.h presence" >&5
+echo $ECHO_N "checking readline/history.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <readline/history.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+  yes:no )
+    { echo "$as_me:$LINENO: WARNING: readline/history.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: readline/history.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/history.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: readline/history.h: proceeding with the preprocessor's result" >&2;};;
+  no:yes )
+    { echo "$as_me:$LINENO: WARNING: readline/history.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: readline/history.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/history.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: readline/history.h: check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: readline/history.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: readline/history.h: proceeding with the preprocessor's result" >&2;};;
+esac
+echo "$as_me:$LINENO: checking for readline/history.h" >&5
+echo $ECHO_N "checking for readline/history.h... $ECHO_C" >&6
+if test "${ac_cv_header_readline_history_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_readline_history_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_readline_history_h" >&5
+echo "${ECHO_T}$ac_cv_header_readline_history_h" >&6
+
+fi
+
+
+	 if test $ac_cv_header_readline_history_h = no;then
+           { { echo "$as_me:$LINENO: error: readline is too old to have readline/history.h, please update to the latest readline library." >&5
+echo "$as_me: error: readline is too old to have readline/history.h, please update to the latest readline library." >&2;}
+   { (exit 1); exit 1; }; }
+	 fi
+         ;;
+  "no" ) VTYSH="";;
+  *    ) ;;
+esac
+
+if test "$with_libpam" = "yes"; then
+echo "$as_me:$LINENO: checking for pam_start in -lpam" >&5
+echo $ECHO_N "checking for pam_start in -lpam... $ECHO_C" >&6
+if test "${ac_cv_lib_pam_pam_start+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpam  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pam_start ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+pam_start ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_pam_pam_start=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_pam_pam_start=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pam_pam_start" >&5
+echo "${ECHO_T}$ac_cv_lib_pam_pam_start" >&6
+if test $ac_cv_lib_pam_pam_start = yes; then
+  echo "$as_me:$LINENO: checking for misc_conv in -lpam" >&5
+echo $ECHO_N "checking for misc_conv in -lpam... $ECHO_C" >&6
+if test "${ac_cv_lib_pam_misc_conv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpam  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char misc_conv ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+misc_conv ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_pam_misc_conv=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_pam_misc_conv=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pam_misc_conv" >&5
+echo "${ECHO_T}$ac_cv_lib_pam_misc_conv" >&6
+if test $ac_cv_lib_pam_misc_conv = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define USE_PAM 1
+_ACEOF
+
+     LIBPAM="-lpam"
+else
+  cat >>confdefs.h <<\_ACEOF
+#define USE_PAM 1
+_ACEOF
+
+     LIBPAM="-lpam -lpam_misc"
+
+fi
+
+
+else
+  echo "$as_me:$LINENO: checking for pam_end in -lpam" >&5
+echo $ECHO_N "checking for pam_end in -lpam... $ECHO_C" >&6
+if test "${ac_cv_lib_pam_pam_end+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpam -ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pam_end ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+pam_end ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_pam_pam_end=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_pam_pam_end=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pam_pam_end" >&5
+echo "${ECHO_T}$ac_cv_lib_pam_pam_end" >&6
+if test $ac_cv_lib_pam_pam_end = yes; then
+  echo "$as_me:$LINENO: checking for misc_conv in -lpam" >&5
+echo $ECHO_N "checking for misc_conv in -lpam... $ECHO_C" >&6
+if test "${ac_cv_lib_pam_misc_conv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpam  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char misc_conv ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+misc_conv ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_pam_misc_conv=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_pam_misc_conv=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pam_misc_conv" >&5
+echo "${ECHO_T}$ac_cv_lib_pam_misc_conv" >&6
+if test $ac_cv_lib_pam_misc_conv = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define USE_PAM 1
+_ACEOF
+
+       LIBPAM="-lpam -ldl"
+else
+  cat >>confdefs.h <<\_ACEOF
+#define USE_PAM 1
+_ACEOF
+
+       LIBPAM="-lpam -ldl -lpam_misc"
+
+fi
+
+
+else
+  { echo "$as_me:$LINENO: WARNING: *** pam support will not be built ***" >&5
+echo "$as_me: WARNING: *** pam support will not be built ***" >&2;}
+fi
+
+
+
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in bcopy bzero strerror inet_aton daemon snprintf vsnprintf strlcat strlcpy if_nametoindex if_indextoname getifaddrs
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in setproctitle
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: checking for setproctitle in -lutil" >&5
+echo $ECHO_N "checking for setproctitle in -lutil... $ECHO_C" >&6
+if test "${ac_cv_lib_util_setproctitle+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lutil  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char setproctitle ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+setproctitle ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_util_setproctitle=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_util_setproctitle=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_util_setproctitle" >&5
+echo "${ECHO_T}$ac_cv_lib_util_setproctitle" >&6
+if test $ac_cv_lib_util_setproctitle = yes; then
+  LIBS="$LIBS -lutil"; cat >>confdefs.h <<\_ACEOF
+#define HAVE_SETPROCTITLE 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+echo "$as_me:$LINENO: checking zebra between kernel interface method" >&5
+echo $ECHO_N "checking zebra between kernel interface method... $ECHO_C" >&6
+if test x"$opsys" = x"gnu-linux"; then
+  if test "${enable_netlink}" = "yes";then
+    echo "$as_me:$LINENO: result: netlink" >&5
+echo "${ECHO_T}netlink" >&6
+    RT_METHOD=rt_netlink.o
+    cat >>confdefs.h <<\_ACEOF
+#define HAVE_NETLINK 1
+_ACEOF
+
+    netlink=yes
+  elif test "${enable_netlink}" = "no"; then
+    echo "$as_me:$LINENO: result: ioctl" >&5
+echo "${ECHO_T}ioctl" >&6
+    RT_METHOD=rt_ioctl.o
+    netlink=no
+  else
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <linux/autoconf.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE > 131328  /* 2.1.0 or later */
+#ifdef CONFIG_RTNETLINK
+  yes
+#endif
+#endif
+#if LINUX_VERSION_CODE > 132112  /* 2.4.17 or later */
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: netlink" >&5
+echo "${ECHO_T}netlink" >&6
+    RT_METHOD=rt_netlink.o
+    cat >>confdefs.h <<\_ACEOF
+#define HAVE_NETLINK 1
+_ACEOF
+
+    netlink=yes
+else
+  echo "$as_me:$LINENO: result: ioctl" >&5
+echo "${ECHO_T}ioctl" >&6
+    RT_METHOD=rt_ioctl.o
+fi
+rm -f conftest*
+
+  fi
+else
+  if test "$opsys" = "sol2-6";then
+    echo "$as_me:$LINENO: result: solaris" >&5
+echo "${ECHO_T}solaris" >&6
+    KERNEL_METHOD="kernel_socket.o"
+    RT_METHOD="rt_socket.o"
+  else
+    if test "$cross_compiling" = yes; then
+  KERNEL_METHOD=kernel_socket.o
+   RT_METHOD=rt_socket.o
+   echo "$as_me:$LINENO: result: socket" >&5
+echo "${ECHO_T}socket" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+main ()
+{
+  int ac_sock;
+
+  ac_sock = socket (AF_ROUTE, SOCK_RAW, 0);
+  if (ac_sock < 0 && errno == EINVAL)
+    exit (1);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_AF_ROUTE 1
+_ACEOF
+
+   KERNEL_METHOD=kernel_socket.o
+   RT_METHOD=rt_socket.o
+   echo "$as_me:$LINENO: result: socket" >&5
+echo "${ECHO_T}socket" >&6
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+RT_METHOD=rt_ioctl.o
+   echo "$as_me:$LINENO: result: ioctl" >&5
+echo "${ECHO_T}ioctl" >&6
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+  fi
+fi
+
+
+
+
+echo "$as_me:$LINENO: checking route read method check" >&5
+echo $ECHO_N "checking route read method check... $ECHO_C" >&6
+if test "${zebra_rtread+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$netlink" = yes; then
+  RTREAD_METHOD="rtread_netlink.o"
+  zebra_rtread="netlink"
+else
+for zebra_rtread in /proc/net/route /dev/ip /dev/null;
+do
+  test x`ls $zebra_rtread 2>/dev/null` = x"$zebra_rtread" && break
+done
+case $zebra_rtread in
+  "/proc/net/route") RTREAD_METHOD="rtread_proc.o"
+                     zebra_rtread="proc";;
+  "/dev/ip")         RTREAD_METHOD="rtread_getmsg.o"
+                     zebra_rtread="getmsg";;
+  *)                 RTREAD_METHOD="rtread_sysctl.o"
+                     zebra_rtread="sysctl";;
+esac
+fi
+fi
+echo "$as_me:$LINENO: result: $zebra_rtread" >&5
+echo "${ECHO_T}$zebra_rtread" >&6
+
+
+echo "$as_me:$LINENO: checking interface looking up method" >&5
+echo $ECHO_N "checking interface looking up method... $ECHO_C" >&6
+if test "$netlink" = yes; then
+  echo "$as_me:$LINENO: result: netlink" >&5
+echo "${ECHO_T}netlink" >&6
+  IF_METHOD=if_netlink.o
+else
+  if test "$opsys" = "sol2-6";then
+    echo "$as_me:$LINENO: result: solaris" >&5
+echo "${ECHO_T}solaris" >&6
+    IF_METHOD=if_ioctl.o
+  elif test "$opsys" = "openbsd";then
+    echo "$as_me:$LINENO: result: openbsd" >&5
+echo "${ECHO_T}openbsd" >&6
+    IF_METHOD=if_ioctl.o
+  elif grep NET_RT_IFLIST /usr/include/sys/socket.h >/dev/null 2>&1; then
+    echo "$as_me:$LINENO: result: sysctl" >&5
+echo "${ECHO_T}sysctl" >&6
+    IF_METHOD=if_sysctl.o
+    cat >>confdefs.h <<\_ACEOF
+#define HAVE_NET_RT_IFLIST 1
+_ACEOF
+
+  else
+    echo "$as_me:$LINENO: result: ioctl" >&5
+echo "${ECHO_T}ioctl" >&6
+    IF_METHOD=if_ioctl.o
+  fi
+fi
+
+
+if test -r /proc/net/dev; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_PROC_NET_DEV 1
+_ACEOF
+
+  IF_PROC=if_proc.o
+fi
+
+if test -r /proc/net/if_inet6; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_PROC_NET_IF_INET6 1
+_ACEOF
+
+  IF_PROC=if_proc.o
+fi
+
+
+echo "$as_me:$LINENO: checking ipforward method check" >&5
+echo $ECHO_N "checking ipforward method check... $ECHO_C" >&6
+if test "${zebra_ipforward_path+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  for zebra_ipforward_path in /proc/net/snmp /dev/ip /dev/null;
+do
+  test x`ls $zebra_ipforward_path 2>/dev/null` = x"$zebra_ipforward_path" && break
+done
+case $zebra_ipforward_path in
+  "/proc/net/snmp")  IPFORWARD=ipforward_proc.o
+                     zebra_ipforward_path="proc";;
+  "/dev/ip")
+                     case "$host" in
+                       *-nec-sysv4*)  IPFORWARD=ipforward_ews.o
+                                      zebra_ipforward_path="ews";;
+                       *)             IPFORWARD=ipforward_solaris.o
+                                      zebra_ipforward_path="solaris";;
+                     esac;;
+  *)                 IPFORWARD=ipforward_sysctl.o
+                     zebra_ipforward_path="sysctl";;
+esac
+fi
+echo "$as_me:$LINENO: result: $zebra_ipforward_path" >&5
+echo "${ECHO_T}$zebra_ipforward_path" >&6
+
+
+
+for ac_func in getaddrinfo
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ have_getaddrinfo=yes
+else
+  have_getaddrinfo=no
+fi
+done
+
+
+echo "$as_me:$LINENO: checking whether does this OS have IPv6 stack" >&5
+echo $ECHO_N "checking whether does this OS have IPv6 stack... $ECHO_C" >&6
+if test "${enable_ipv6}" = "no"; then
+  echo "$as_me:$LINENO: result: disabled" >&5
+echo "${ECHO_T}disabled" >&6
+else
+if grep IPV6_INRIA_VERSION /usr/include/netinet/in.h >/dev/null 2>&1; then
+   zebra_cv_ipv6=yes
+   cat >>confdefs.h <<\_ACEOF
+#define HAVE_IPV6 1
+_ACEOF
+
+   cat >>confdefs.h <<\_ACEOF
+#define INRIA_IPV6 1
+_ACEOF
+
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   LIB_IPV6=""
+   echo "$as_me:$LINENO: result: INRIA IPv6" >&5
+echo "${ECHO_T}INRIA IPv6" >&6
+fi
+if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then
+   zebra_cv_ipv6=yes
+   cat >>confdefs.h <<\_ACEOF
+#define HAVE_IPV6 1
+_ACEOF
+
+   cat >>confdefs.h <<\_ACEOF
+#define KAME 1
+_ACEOF
+
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then
+      LIB_IPV6="-L/usr/local/v6/lib -linet6"
+   fi
+   echo "$as_me:$LINENO: result: KAME" >&5
+echo "${ECHO_T}KAME" >&6
+fi
+if grep NRL /usr/include/netinet6/in6.h >/dev/null 2>&1; then
+   zebra_cv_ipv6=yes
+   cat >>confdefs.h <<\_ACEOF
+#define HAVE_IPV6 1
+_ACEOF
+
+   cat >>confdefs.h <<\_ACEOF
+#define NRL 1
+_ACEOF
+
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   if test x"$opsys" = x"bsdi";then
+      cat >>confdefs.h <<\_ACEOF
+#define BSDI_NRL 1
+_ACEOF
+
+      echo "$as_me:$LINENO: result: BSDI_NRL" >&5
+echo "${ECHO_T}BSDI_NRL" >&6
+   else
+      echo "$as_me:$LINENO: result: NRL" >&5
+echo "${ECHO_T}NRL" >&6
+   fi
+fi
+
+if test "${enable_ipv6}" = "yes"; then
+   cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+   #include <linux/version.h>
+   /* 2.1.128 or later */
+   #if LINUX_VERSION_CODE >= 0x020180
+   yes
+   #endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "yes" >/dev/null 2>&1; then
+  zebra_cv_ipv6=yes; zebra_cv_linux_ipv6=yes;echo "$as_me:$LINENO: result: Linux IPv6" >&5
+echo "${ECHO_T}Linux IPv6" >&6
+fi
+rm -f conftest*
+
+else
+   if test x`ls /proc/net/ipv6_route 2>/dev/null` = x"/proc/net/ipv6_route"
+   then
+      zebra_cv_ipv6=yes
+      zebra_cv_linux_ipv6=yes
+      echo "$as_me:$LINENO: result: Linux IPv6" >&5
+echo "${ECHO_T}Linux IPv6" >&6
+   fi
+fi
+
+if test "$zebra_cv_linux_ipv6" = "yes";then
+   cat >>confdefs.h <<\_ACEOF
+#define HAVE_IPV6 1
+_ACEOF
+
+   echo "$as_me:$LINENO: checking for GNU libc 2.1" >&5
+echo $ECHO_N "checking for GNU libc 2.1... $ECHO_C" >&6
+   cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <features.h>
+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+  yes
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "yes" >/dev/null 2>&1; then
+  glibc=yes; echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+   cat >>confdefs.h <<\_ACEOF
+#define LINUX_IPV6 1
+_ACEOF
+
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   if test "$glibc" != "yes"; then
+      INCLUDES="-I/usr/inet6/include"
+      if test x`ls /usr/inet6/lib/libinet6.a 2>/dev/null` != x;then
+         LIB_IPV6="-L/usr/inet6/lib -linet6"
+      fi
+   fi
+fi
+
+LIBS="$LIB_IPV6 $LIBS"
+
+
+if test x"$RIPNGD" = x""; then
+  echo "$as_me:$LINENO: result: IPv4 only" >&5
+echo "${ECHO_T}IPv4 only" >&6
+fi
+fi
+
+if test "${enable_zebra}" = "no";then
+  ZEBRA=""
+else
+  ZEBRA="zebra"
+fi
+
+if test "${enable_bgpd}" = "no";then
+  BGPD=""
+else
+  BGPD="bgpd"
+fi
+
+if test "${enable_ripd}" = "no";then
+  RIPD=""
+else
+  RIPD="ripd"
+fi
+
+if test "${enable_ospfd}" = "no";then
+  OSPFD=""
+else
+  OSPFD="ospfd"
+fi
+
+case "${enable_ripngd}" in
+  "yes") RIPNGD="ripngd";;
+  "no" ) RIPNGD="";;
+  *    ) ;;
+esac
+
+case "${enable_ospf6d}" in
+  "yes") OSPF6D="ospf6d";;
+  "no" ) OSPF6D="";;
+  *    ) ;;
+esac
+
+case "${enable_isisd}" in
+  "yes") ISISD="isisd";;
+  "no" ) ISISD="";;
+  *    ) ;;
+esac
+
+if test "${enable_bgp_announce}" = "no";then
+  cat >>confdefs.h <<\_ACEOF
+#define DISABLE_BGP_ANNOUNCE 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking for inet_ntop in -lc" >&5
+echo $ECHO_N "checking for inet_ntop in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_inet_ntop+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_ntop ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+inet_ntop ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_inet_ntop=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_c_inet_ntop=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_inet_ntop" >&5
+echo "${ECHO_T}$ac_cv_lib_c_inet_ntop" >&6
+if test $ac_cv_lib_c_inet_ntop = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_INET_NTOP 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for inet_pton in -lc" >&5
+echo $ECHO_N "checking for inet_pton in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_inet_pton+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_pton ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+inet_pton ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_inet_pton=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_c_inet_pton=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_inet_pton" >&5
+echo "${ECHO_T}$ac_cv_lib_c_inet_pton" >&6
+if test $ac_cv_lib_c_inet_pton = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_INET_PTON 1
+_ACEOF
+
+fi
+
+
+echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
+echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6
+if test "${ac_cv_lib_crypt_crypt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char crypt ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+crypt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_crypt_crypt=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_crypt_crypt=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
+echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6
+if test $ac_cv_lib_crypt_crypt = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPT 1
+_ACEOF
+
+  LIBS="-lcrypt $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for res_init in -lresolv" >&5
+echo $ECHO_N "checking for res_init in -lresolv... $ECHO_C" >&6
+if test "${ac_cv_lib_resolv_res_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char res_init ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+res_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_resolv_res_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_resolv_res_init=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_res_init" >&5
+echo "${ECHO_T}$ac_cv_lib_resolv_res_init" >&6
+if test $ac_cv_lib_resolv_res_init = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBRESOLV 1
+_ACEOF
+
+  LIBS="-lresolv $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for main in -lm" >&5
+echo $ECHO_N "checking for main in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_m_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_main" >&5
+echo "${ECHO_T}$ac_cv_lib_m_main" >&6
+if test $ac_cv_lib_m_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+
+echo "$as_me:$LINENO: checking for __inet_ntop" >&5
+echo $ECHO_N "checking for __inet_ntop... $ECHO_C" >&6
+if test "${ac_cv_func___inet_ntop+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char __inet_ntop (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char __inet_ntop ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub___inet_ntop) || defined (__stub_____inet_ntop)
+choke me
+#else
+f = __inet_ntop;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func___inet_ntop=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func___inet_ntop=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func___inet_ntop" >&5
+echo "${ECHO_T}$ac_cv_func___inet_ntop" >&6
+if test $ac_cv_func___inet_ntop = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_INET_NTOP 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for __inet_pton" >&5
+echo $ECHO_N "checking for __inet_pton... $ECHO_C" >&6
+if test "${ac_cv_func___inet_pton+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char __inet_pton (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char __inet_pton ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub___inet_pton) || defined (__stub_____inet_pton)
+choke me
+#else
+f = __inet_pton;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func___inet_pton=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func___inet_pton=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func___inet_pton" >&5
+echo "${ECHO_T}$ac_cv_func___inet_pton" >&6
+if test $ac_cv_func___inet_pton = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_INET_PTON 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for __inet_aton" >&5
+echo $ECHO_N "checking for __inet_aton... $ECHO_C" >&6
+if test "${ac_cv_func___inet_aton+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char __inet_aton (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char __inet_aton ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub___inet_aton) || defined (__stub_____inet_aton)
+choke me
+#else
+f = __inet_aton;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func___inet_aton=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func___inet_aton=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func___inet_aton" >&5
+echo "${ECHO_T}$ac_cv_func___inet_aton" >&6
+if test $ac_cv_func___inet_aton = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_INET_ATON 1
+_ACEOF
+
+fi
+
+
+echo "$as_me:$LINENO: checking for regexec in -lc" >&5
+echo $ECHO_N "checking for regexec in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_regexec+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char regexec ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+regexec ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_regexec=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_c_regexec=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_regexec" >&5
+echo "${ECHO_T}$ac_cv_lib_c_regexec" >&6
+if test $ac_cv_lib_c_regexec = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_GNU_REGEX 1
+_ACEOF
+
+ LIB_REGEX=""
+else
+  LIB_REGEX="regex.o"
+fi
+
+
+
+
+if test "${enable_snmp}" = "yes";then
+  old_libs="${LIBS}"
+  LIBS="-L/usr/local/lib"
+  unset ac_cv_lib_snmp_asn_parse_int
+  echo "$as_me:$LINENO: checking for asn_parse_int in -lsnmp" >&5
+echo $ECHO_N "checking for asn_parse_int in -lsnmp... $ECHO_C" >&6
+if test "${ac_cv_lib_snmp_asn_parse_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsnmp  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char asn_parse_int ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asn_parse_int ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_snmp_asn_parse_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_snmp_asn_parse_int=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_snmp_asn_parse_int" >&5
+echo "${ECHO_T}$ac_cv_lib_snmp_asn_parse_int" >&6
+if test $ac_cv_lib_snmp_asn_parse_int = yes; then
+  HAVE_SNMP=yes
+fi
+
+  if test "${HAVE_SNMP}" = ""; then
+    unset ac_cv_lib_snmp_asn_parse_int
+    echo "$as_me:$LINENO: checking for main in -lcrypto" >&5
+echo $ECHO_N "checking for main in -lcrypto... $ECHO_C" >&6
+if test "${ac_cv_lib_crypto_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_crypto_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_crypto_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypto_main" >&5
+echo "${ECHO_T}$ac_cv_lib_crypto_main" >&6
+if test $ac_cv_lib_crypto_main = yes; then
+  NEED_CRYPTO=yes
+fi
+
+	if test "${NEED_CRYPTO}" = ""; then
+		echo "$as_me:$LINENO: checking for asn_parse_int in -lsnmp" >&5
+echo $ECHO_N "checking for asn_parse_int in -lsnmp... $ECHO_C" >&6
+if test "${ac_cv_lib_snmp_asn_parse_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsnmp  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char asn_parse_int ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asn_parse_int ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_snmp_asn_parse_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_snmp_asn_parse_int=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_snmp_asn_parse_int" >&5
+echo "${ECHO_T}$ac_cv_lib_snmp_asn_parse_int" >&6
+if test $ac_cv_lib_snmp_asn_parse_int = yes; then
+  HAVE_SNMP=yes; NEED_CRYPTO=yes
+fi
+
+	else
+	    echo "$as_me:$LINENO: checking for asn_parse_int in -lsnmp" >&5
+echo $ECHO_N "checking for asn_parse_int in -lsnmp... $ECHO_C" >&6
+if test "${ac_cv_lib_snmp_asn_parse_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsnmp "-lcrypto" $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char asn_parse_int ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asn_parse_int ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_snmp_asn_parse_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_snmp_asn_parse_int=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_snmp_asn_parse_int" >&5
+echo "${ECHO_T}$ac_cv_lib_snmp_asn_parse_int" >&6
+if test $ac_cv_lib_snmp_asn_parse_int = yes; then
+  HAVE_SNMP=yes; NEED_CRYPTO=yes;LIBS="$LIBS -lcrypto"
+fi
+
+	fi
+  fi
+  LIBS="${old_libs}"
+
+  if test "${HAVE_SNMP}" = ""; then
+	old_libs="${LIBS}"
+	LIBS="-L/usr/local/lib"
+	echo "$as_me:$LINENO: checking for asn_parse_int in -lsnmp" >&5
+echo $ECHO_N "checking for asn_parse_int in -lsnmp... $ECHO_C" >&6
+if test "${ac_cv_lib_snmp_asn_parse_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsnmp  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char asn_parse_int ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asn_parse_int ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_snmp_asn_parse_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_snmp_asn_parse_int=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_snmp_asn_parse_int" >&5
+echo "${ECHO_T}$ac_cv_lib_snmp_asn_parse_int" >&6
+if test $ac_cv_lib_snmp_asn_parse_int = yes; then
+  HAVE_SNMP=yes
+fi
+
+	LIBS="${old_libs}"
+  fi
+  if test "${HAVE_SNMP}" = "yes"; then
+    for ac_snmp in /usr/include/ucd-snmp/asn1.h /usr/local/include/ucd-snmp/asn1.h /dev/null
+    do
+      test -f "${ac_snmp}" && break
+    done
+    case ${ac_snmp} in
+      /usr/include/ucd-snmp/*)
+                  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SNMP 1
+_ACEOF
+
+                  CFLAGS="${CFLAGS} -I/usr/include/ucd-snmp"
+    		  LIBS="${LIBS} -lsnmp"
+                  ;;
+      /usr/local/include/ucd-snmp/*)
+                  cat >>confdefs.h <<\_ACEOF
+#define HAVE_SNMP 1
+_ACEOF
+
+  	          CFLAGS="${CFLAGS} -I/usr/local/include/ucd-snmp"
+  		  LIBS="${LIBS} -L/usr/local/lib -lsnmp"
+                  ;;
+    esac
+    if test "${NEED_CRYPTO}" = "yes"; then
+      LIBS="${LIBS} -lcrypto"
+    fi
+  fi
+fi
+
+echo "$as_me:$LINENO: checking whether struct sockaddr has a sa_len field" >&5
+echo $ECHO_N "checking whether struct sockaddr has a sa_len field... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static struct sockaddr ac_i;int ac_j = sizeof (ac_i.sa_len);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SA_LEN 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+echo "$as_me:$LINENO: checking whether struct sockaddr_in has a sin_len field" >&5
+echo $ECHO_N "checking whether struct sockaddr_in has a sin_len field... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static struct sockaddr_in ac_i;int ac_j = sizeof (ac_i.sin_len);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SIN_LEN 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+echo "$as_me:$LINENO: checking whether struct sockaddr_un has a sun_len field" >&5
+echo $ECHO_N "checking whether struct sockaddr_un has a sun_len field... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/un.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static struct sockaddr_un ac_i;int ac_j = sizeof (ac_i.sun_len);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SUN_LEN 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+if test "$zebra_cv_ipv6" = yes; then
+  echo "$as_me:$LINENO: checking whether struct sockaddr_in6 has a sin6_scope_id field" >&5
+echo $ECHO_N "checking whether struct sockaddr_in6 has a sin6_scope_id field... $ECHO_C" >&6
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static struct sockaddr_in6 ac_i;int ac_j = sizeof (ac_i.sin6_scope_id);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SIN6_SCOPE_ID 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+
+echo "$as_me:$LINENO: checking whther socklen_t is defined" >&5
+echo $ECHO_N "checking whther socklen_t is defined... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+socklen_t ac_x;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SOCKLEN_T 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+echo "$as_me:$LINENO: checking whether struct sockaddr_dl exist" >&5
+echo $ECHO_N "checking whether struct sockaddr_dl exist... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <net/if_dl.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "sockaddr_dl" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SOCKADDR_DL 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking whether struct ifaliasreq exist" >&5
+echo $ECHO_N "checking whether struct ifaliasreq exist... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <net/if.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "ifaliasreq" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_IFALIASREQ 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking whether struct if6_aliasreq exist" >&5
+echo $ECHO_N "checking whether struct if6_aliasreq exist... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <netinet6/in6_var.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "in6_aliasreq" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_IN6_ALIASREQ 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking whether struct rt_addrinfo exist" >&5
+echo $ECHO_N "checking whether struct rt_addrinfo exist... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <net/route.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "rt_addrinfo" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_RT_ADDRINFO 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking whether struct in_pktinfo exist" >&5
+echo $ECHO_N "checking whether struct in_pktinfo exist... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <netinet/in.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+struct in_pktinfo ac_x;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_INPKTINFO 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+echo "$as_me:$LINENO: checking whether getrusage is available" >&5
+echo $ECHO_N "checking whether getrusage is available... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/resource.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+struct rusage ac_x; getrusage (RUSAGE_SELF, &ac_x);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_RUSAGE 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+file="${srcdir}/lib/version.h"
+VERSION=`sed -ne 's/^#.*ZEBRA_VERSION.*\"\([^\"]*\)\"$/\1/p' $file`
+
+
+echo "$as_me:$LINENO: checking pid file directory" >&5
+echo $ECHO_N "checking pid file directory... $ECHO_C" >&6
+if test "${ac_piddir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  for ZEBRA_PID_DIR in /var/run	                   /var/adm	                   /etc		                   /dev/null;
+do
+  test -d $ZEBRA_PID_DIR && break
+done
+ac_piddir=$ZEBRA_PID_DIR
+if test $ZEBRA_PID_DIR = "/dev/null"; then
+  echo "PID DIRECTORY NOT FOUND!"
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_piddir" >&5
+echo "${ECHO_T}$ac_piddir" >&6
+cat >>confdefs.h <<_ACEOF
+#define PATH_ZEBRA_PID "$ac_piddir/zebra.pid"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_RIPD_PID "$ac_piddir/ripd.pid"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_RIPNGD_PID "$ac_piddir/ripngd.pid"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_BGPD_PID "$ac_piddir/bgpd.pid"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_OSPFD_PID "$ac_piddir/ospfd.pid"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_OSPF6D_PID "$ac_piddir/ospf6d.pid"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_ISISD_PID "$ac_piddir/isisd.pid"
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for working htonl" >&5
+echo $ECHO_N "checking for working htonl... $ECHO_C" >&6
+if test "${ac_cv_htonl_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+htonl (0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_htonl_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_htonl_works=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+echo "$as_me:$LINENO: result: $ac_cv_htonl_works" >&5
+echo "${ECHO_T}$ac_cv_htonl_works" >&6
+
+ac_config_files="$ac_config_files Makefile lib/Makefile zebra/Makefile ripd/Makefile ripngd/Makefile bgpd/Makefile ospfd/Makefile ospf6d/Makefile isisd/Makefile vtysh/Makefile doc/Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overriden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+        "s/'/'\\\\''/g;
+    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if cmp -s $cache_file confcache; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[ 	]*VPATH[ 	]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ 	]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ 	]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# NLS nuisances.
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+    { $as_unset LANG || test "${LANG+set}" != set; } ||
+      { LANG=C; export LANG; }
+(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+      { LC_ALL=C; export LC_ALL; }
+(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+      { LC_TIME=C; export LC_TIME; }
+(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+      { LC_CTYPE=C; export LC_CTYPE; }
+(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+      { LANGUAGE=C; export LANGUAGE; }
+(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+      { LC_COLLATE=C; export LC_COLLATE; }
+(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+      { LC_NUMERIC=C; export LC_NUMERIC; }
+(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+      { LC_MESSAGES=C; export LC_MESSAGES; }
+
+
+# Name of the executable.
+as_me=`(basename "$0") 2>/dev/null ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conftest.sh
+  echo  "exit 0"   >>conftest.sh
+  chmod +x conftest.sh
+  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conftest.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.53.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.53,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    shift
+    set dummy "$ac_option" "$ac_optarg" ${1+"$@"}
+    shift
+    ;;
+  -*);;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_need_defaults=false;;
+  esac
+
+  case $1 in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion"
+    exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;;
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    shift
+    CONFIG_FILES="$CONFIG_FILES $1"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $1"
+    ac_need_defaults=false;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+  "zebra/Makefile" ) CONFIG_FILES="$CONFIG_FILES zebra/Makefile" ;;
+  "ripd/Makefile" ) CONFIG_FILES="$CONFIG_FILES ripd/Makefile" ;;
+  "ripngd/Makefile" ) CONFIG_FILES="$CONFIG_FILES ripngd/Makefile" ;;
+  "bgpd/Makefile" ) CONFIG_FILES="$CONFIG_FILES bgpd/Makefile" ;;
+  "ospfd/Makefile" ) CONFIG_FILES="$CONFIG_FILES ospfd/Makefile" ;;
+  "ospf6d/Makefile" ) CONFIG_FILES="$CONFIG_FILES ospf6d/Makefile" ;;
+  "isisd/Makefile" ) CONFIG_FILES="$CONFIG_FILES isisd/Makefile" ;;
+  "vtysh/Makefile" ) CONFIG_FILES="$CONFIG_FILES vtysh/Makefile" ;;
+  "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+  "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=$TMPDIR/cs$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@AMTAR@,$AMTAR,;t t
+s,@install_sh@,$install_sh,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t
+s,@AWK@,$AWK,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@DEPDIR@,$DEPDIR,;t t
+s,@am__include@,$am__include,;t t
+s,@am__quote@,$am__quote,;t t
+s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t
+s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t
+s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t
+s,@CCDEPMODE@,$CCDEPMODE,;t t
+s,@CPP@,$CPP,;t t
+s,@AR@,$AR,;t t
+s,@ac_ct_AR@,$ac_ct_AR,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@MULTIPATH_NUM@,$MULTIPATH_NUM,;t t
+s,@LIBPAM@,$LIBPAM,;t t
+s,@RT_METHOD@,$RT_METHOD,;t t
+s,@KERNEL_METHOD@,$KERNEL_METHOD,;t t
+s,@OTHER_METHOD@,$OTHER_METHOD,;t t
+s,@RTREAD_METHOD@,$RTREAD_METHOD,;t t
+s,@IF_METHOD@,$IF_METHOD,;t t
+s,@IF_PROC@,$IF_PROC,;t t
+s,@IPFORWARD@,$IPFORWARD,;t t
+s,@LIB_IPV6@,$LIB_IPV6,;t t
+s,@ZEBRA@,$ZEBRA,;t t
+s,@BGPD@,$BGPD,;t t
+s,@RIPD@,$RIPD,;t t
+s,@RIPNGD@,$RIPNGD,;t t
+s,@OSPFD@,$OSPFD,;t t
+s,@OSPF6D@,$OSPF6D,;t t
+s,@ISISD@,$ISISD,;t t
+s,@VTYSH@,$VTYSH,;t t
+s,@INCLUDES@,$INCLUDES,;t t
+s,@CURSES@,$CURSES,;t t
+s,@LIB_REGEX@,$LIB_REGEX,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+  	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+  	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+	{ { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
+ac_dB='[ 	].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[ 	]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	(][^ 	(]*\)\(([^)]*)\)[ 	]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	][^ 	]*\)[ 	]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if egrep "^[ 	]*#[ 	]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[ 	]*#[ 	]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # egrep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[ 	]*#[ 	]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+      { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+	{ { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+  # Run the commands associated with the file.
+  case $ac_file in
+    config.h ) # update the timestamp
+echo 'timestamp for config.h' >"./stamp-h1"
+ ;;
+  esac
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_dest" : 'X\(//\)[^/]' \| \
+         X"$ac_dest" : 'X\(//\)$' \| \
+         X"$ac_dest" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # So let's grep whole file.
+  if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+    dirpart=`(dirname "$mf") 2>/dev/null ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$mf" : 'X\(//\)[^/]' \| \
+         X"$mf" : 'X\(//\)$' \| \
+         X"$mf" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  else
+    continue
+  fi
+  grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue
+  # Extract the definition of DEP_FILES from the Makefile without
+  # running `make'.
+  DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n -e '/^U = / s///p' < "$mf"`
+  test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
+  # We invoke sed twice because it is the simplest approach to
+  # changing $(DEPDIR) to its actual value in the expansion.
+  for file in `sed -n -e '
+    /^DEP_FILES = .*\\\\$/ {
+      s/^DEP_FILES = //
+      :loop
+	s/\\\\$//
+	p
+	n
+	/\\\\$/ b loop
+      p
+    }
+    /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`(dirname "$file") 2>/dev/null ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$file" : 'X\(//\)[^/]' \| \
+         X"$file" : 'X\(//\)$' \| \
+         X"$file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    { case $dirpart/$fdir in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy=$dirpart/$fdir
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+	{ { echo "$as_me:$LINENO: error: cannot create $dirpart/$fdir" >&5
+echo "$as_me: error: cannot create $dirpart/$fdir" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+ ;;
+  esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+echo "
+zebra configuration
+-------------------
+zebra version           : ${VERSION}
+host operationg system  : ${host_os}
+source code location    : ${srcdir}
+compiler                : ${CC}
+compiler flags          : ${CFLAGS}
+directory for pid files : ${ac_piddir}
+"
diff --git a/isisd/modified/configure.in b/isisd/modified/configure.in
new file mode 100755
index 0000000..49b508b
--- /dev/null
+++ b/isisd/modified/configure.in
@@ -0,0 +1,882 @@
+##
+## Configure template file for Zebra.
+## autoconf will generate configure script.
+##
+##  Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+##
+AC_PREREQ(2.13)
+
+AC_INIT(lib/zebra.h)
+AM_INIT_AUTOMAKE(zebra, 0.93)
+AM_CONFIG_HEADER(config.h)
+
+dnl -----------------------------------
+dnl Get hostname and other information.
+dnl -----------------------------------
+AC_CANONICAL_HOST
+
+dnl ------------
+dnl Check CFLAGS
+dnl ------------
+AC_ARG_WITH(cflags,
+[  --with-cflags           Set CFLAGS for use in compilation.])
+if test "x$with_cflags" != "x" ; then
+  CFLAGS="$with_cflags" ; cflags_specified=yes ;
+elif test -n "$CFLAGS" ; then
+  cflags_specified=yes ;
+fi
+
+dnl --------
+dnl Check CC
+dnl --------
+AC_PROG_CC
+
+dnl -----------------------------------------
+dnl If CLFAGS doesn\'t exist set default value
+dnl -----------------------------------------
+if test "x$cflags_specified" = "x" ; then
+  CFLAGS="$CFLAGS -Wall"
+fi
+
+dnl --------------
+dnl Check programs
+dnl --------------
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+
+dnl ---------
+dnl AIX check
+dnl ---------
+AC_AIX
+
+dnl ----------------------
+dnl Packages configuration
+dnl ----------------------
+AC_ARG_ENABLE(vtysh,
+[  --enable-vtysh,       Make integrated VTY version of zebra])
+AC_ARG_ENABLE(ipv6,
+[  --disable-ipv6          turn off IPv6 related features and daemons])
+AC_ARG_ENABLE(zebra,
+[  --disable-zebra         do not build zebra daemon])
+AC_ARG_ENABLE(bgpd,
+[  --disable-bgpd          do not build bgpd])
+AC_ARG_ENABLE(ripd,
+[  --disable-ripd          do not build ripd])
+AC_ARG_ENABLE(ripngd,
+[  --disable-ripngd        do not build ripngd])
+AC_ARG_ENABLE(ospfd,
+[  --disable-ospfd         do not build ospfd])
+AC_ARG_ENABLE(ospf6d,
+[  --disable-ospf6d        do not build ospf6d])
+AC_ARG_ENABLE(isisd,
+[  --disable-isisd         do not build isisd])
+AC_ARG_ENABLE(bgp-announce,
+[  --disable-bgp-announce, turn off BGP route announcement])
+AC_ARG_ENABLE(netlink,
+[  --enable-netlink        force to use Linux netlink interface])
+AC_ARG_ENABLE(broken-aliases,
+[  --enable-broken-aliases enable aliases as distinct interfaces for Linux 2.2.X])
+AC_ARG_ENABLE(snmp,
+[  --enable-snmp           enable SNMP support])
+AC_ARG_WITH(libpam,
+[  --with-libpam           use libpam for PAM support in vtysh])
+AC_ARG_ENABLE(tcpsock,
+[  --enable-tcp-zebra      enable TCP/IP socket connection between zebra and protocol daemon])
+dnl Temporary option until OSPF NSSA implementation complete
+AC_ARG_ENABLE(nssa,
+[  --enable-nssa           enable OSPF NSSA option])
+AC_ARG_ENABLE(opaque-lsa,
+[  --enable-opaque-lsa     enable OSPF Opaque-LSA support (RFC2370)])
+AC_ARG_ENABLE(ospf-te,
+[  --enable-ospf-te        enable Traffic Engineering Extension to OSPF])
+AC_ARG_ENABLE(multipath,
+[  --enable-multipath=ARG  enable multipath function, ARG must be digit])
+
+dnl AC_ARG_ENABLE(rtadv,
+dnl [  --enable-rtadv          enable IPV6 router advertisment option])
+
+if test "${enable_broken_aliases}" = "yes"; then
+  if test "${enable_netlink}" = "yes"
+  then
+    echo "Sorry, you can't use netlink with broken aliases"
+    exit 1
+  fi
+  AC_DEFINE(HAVE_BROKEN_ALIASES)
+  enable_netlink=no
+fi
+
+if test "${enable_tcp_zebra}" = "yes"; then
+  AC_DEFINE(HAVE_TCP_ZEBRA)
+fi
+
+if test "${enable_nssa}" = "yes"; then
+  AC_DEFINE(HAVE_NSSA)
+fi
+
+if test "${enable_opaque_lsa}" = "yes"; then
+  AC_DEFINE(HAVE_OPAQUE_LSA)
+fi
+
+if test "${enable_ospf_te}" = "yes"; then
+  AC_DEFINE(HAVE_OPAQUE_LSA)
+  AC_DEFINE(HAVE_OSPF_TE)
+fi
+
+dnl if test "${enable_rtadv}" = "yes"; then
+dnl   AC_DEFINE(HAVE_RTADV)
+dnl fi
+
+changequote(, )dnl
+
+MULTIPATH_NUM=1
+
+case "${enable_multipath}" in
+  [0-9]|[1-9][0-9])
+    MULTIPATH_NUM="${enable_multipath}"
+    ;;
+  "")
+    ;;
+  *)           
+    echo "Please specify digit to --enable-multipath ARG."
+    exit 1
+    ;;
+esac
+
+changequote([, ])dnl
+
+AC_SUBST(MULTIPATH_NUM)
+
+dnl -------------------
+dnl Check header files.
+dnl -------------------
+AC_STDC_HEADERS
+AC_CHECK_HEADERS(string.h stropts.h sys/conf.h sys/ksym.h sys/time.h sys/times.h sys/select.h sys/sysctl.h sys/sockio.h sys/types.h net/if_dl.h net/if_var.h linux/version.h kvm.h netdb.h netinet/in.h net/netopt.h netinet/in_var.h netinet/in6_var.h netinet/in6.h inet/nd.h asm/types.h netinet/icmp6.h netinet6/nd6.h libutil.h)
+
+dnl check some types
+AC_C_CONST
+dnl AC_TYPE_PID_T
+AC_TYPE_SIGNAL
+
+dnl Some systems (Solaris 2.x) require libnsl (Network Services Library)
+case "$host" in
+  *-sunos5.6* | *-solaris2.6*)
+      opsys=sol2-6
+      AC_DEFINE(SUNOS_5)
+      AC_CHECK_LIB(xnet, main)
+      CURSES=-lcurses
+  ;;
+  *-sunos5* | *-solaris2*)
+      AC_DEFINE(SUNOS_5)
+      AC_CHECK_LIB(socket, main)
+      AC_CHECK_LIB(nsl, main)
+      CURSES=-lcurses
+  ;;
+  *-linux-*)
+      opsys=gnu-linux
+      AC_DEFINE(GNU_LINUX)
+  ;;
+  *-nec-sysv4*)
+      AC_CHECK_LIB(nsl, gethostbyname)
+      AC_CHECK_LIB(socket, socket)
+  ;;
+  *-freebsd3.2)
+      AC_DEFINE(FREEBSD_32)
+  ;;
+  *-openbsd*)
+      opsys=openbsd
+      AC_DEFINE(OPEN_BSD)
+  ;;
+  *-bsdi*)
+      opsys=bsdi
+      OTHER_METHOD="mtu_kvm.o"
+      AC_CHECK_LIB(kvm, main)
+  ;;
+esac
+
+case "${host_cpu}-${host_os}" in
+  i?86-solaris*)
+    AC_DEFINE(SOLARIS_X86)
+  ;;
+esac
+
+dnl ---------------------
+dnl Integrated VTY option
+dnl ---------------------
+case "${enable_vtysh}" in
+  "yes") VTYSH="vtysh";
+         AC_DEFINE(VTYSH)
+	 AC_CHECK_LIB(tinfo, tputs, , AC_CHECK_LIB(ncurses, tputs))
+         AC_CHECK_LIB(readline, main)
+         if test $ac_cv_lib_readline_main = no; then
+           AC_MSG_ERROR([vtysh needs libreadline but was not found on your system.])
+         fi
+	 AC_CHECK_HEADER(readline/history.h)
+	 if test $ac_cv_header_readline_history_h = no;then
+           AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.])
+	 fi
+         ;;
+  "no" ) VTYSH="";;
+  *    ) ;;
+esac
+
+dnl ----------
+dnl PAM module
+dnl ----------
+if test "$with_libpam" = "yes"; then
+dnl took this test from proftpd's configure.in and suited to our needs
+dnl -------------------------------------------------------------------------
+dnl
+dnl This next check looks funky due to a linker problem with some versions
+dnl of the PAM library.  Prior to 0.72 release, the Linux PAM shared library
+dnl omitted requiring libdl linking information. PAM-0.72 or better ships
+dnl with RedHat 6.2 and Debian 2.2 or better.
+AC_CHECK_LIB(pam, pam_start,
+  [AC_CHECK_LIB(pam, misc_conv,
+    [AC_DEFINE(USE_PAM)
+     LIBPAM="-lpam"],
+    [AC_DEFINE(USE_PAM)
+     LIBPAM="-lpam -lpam_misc"]
+    )
+  ],
+
+  [AC_CHECK_LIB(pam, pam_end,
+    [AC_CHECK_LIB(pam, misc_conv,
+      [AC_DEFINE(USE_PAM)
+       LIBPAM="-lpam -ldl"],
+      [AC_DEFINE(USE_PAM)
+       LIBPAM="-lpam -ldl -lpam_misc"]
+     )
+  ],AC_MSG_WARN([*** pam support will not be built ***]),
+  [-ldl])
+  ]
+)
+fi
+AC_SUBST(LIBPAM)
+
+dnl -------------------------------
+dnl Endian-ness check
+dnl -------------------------------
+AC_DEFUN(ZEBRA_AC_C_BIGENDIAN,
+[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian,
+[ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif], [# It does; now see whether it defined to BIG_ENDIAN or not.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)])
+if test $ac_cv_c_bigendian = unknown; then
+AC_TRY_RUN([main () {
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)
+fi])
+if test $ac_cv_c_bigendian = yes; then
+  AC_DEFINE(WORDS_BIGENDIAN,1,Big endian words)
+fi
+])
+
+dnl -------------------------------
+dnl check the size in byte of the C
+dnl -------------------------------
+dnl AC_CHECK_SIZEOF(char)
+dnl AC_CHECK_SIZEOF(int)
+dnl AC_CHECK_SIZEOF(short)
+dnl AC_CHECK_SIZEOF(long)
+
+dnl ----------------------------
+dnl check existance of functions
+dnl ----------------------------
+AC_CHECK_FUNCS(bcopy bzero strerror inet_aton daemon snprintf vsnprintf strlcat strlcpy if_nametoindex if_indextoname getifaddrs)
+AC_CHECK_FUNCS(setproctitle, ,[AC_CHECK_LIB(util, setproctitle, [LIBS="$LIBS -lutil"; AC_DEFINE(HAVE_SETPROCTITLE)])])
+
+dnl ------------------------------------
+dnl Determine routing get and set method
+dnl ------------------------------------
+AC_MSG_CHECKING(zebra between kernel interface method)
+if test x"$opsys" = x"gnu-linux"; then
+  if test "${enable_netlink}" = "yes";then
+    AC_MSG_RESULT(netlink)
+    RT_METHOD=rt_netlink.o
+    AC_DEFINE(HAVE_NETLINK)
+    netlink=yes
+  elif test "${enable_netlink}" = "no"; then
+    AC_MSG_RESULT(ioctl)
+    RT_METHOD=rt_ioctl.o
+    netlink=no
+  else
+    AC_EGREP_CPP(yes,
+    [#include <linux/autoconf.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE > 131328  /* 2.1.0 or later */
+#ifdef CONFIG_RTNETLINK
+  yes
+#endif
+#endif
+#if LINUX_VERSION_CODE > 132112  /* 2.4.17 or later */
+  yes
+#endif
+    ],
+   [AC_MSG_RESULT(netlink)
+    RT_METHOD=rt_netlink.o
+    AC_DEFINE(HAVE_NETLINK)
+    netlink=yes],
+   [AC_MSG_RESULT(ioctl)
+    RT_METHOD=rt_ioctl.o])
+  fi
+else
+  if test "$opsys" = "sol2-6";then
+    AC_MSG_RESULT(solaris)
+    KERNEL_METHOD="kernel_socket.o"
+    RT_METHOD="rt_socket.o"
+  else
+    AC_TRY_RUN([#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+main ()
+{
+  int ac_sock;
+
+  ac_sock = socket (AF_ROUTE, SOCK_RAW, 0);
+  if (ac_sock < 0 && errno == EINVAL)
+    exit (1);
+  exit (0);
+}],
+  [AC_DEFINE(HAVE_AF_ROUTE)
+   KERNEL_METHOD=kernel_socket.o
+   RT_METHOD=rt_socket.o
+   AC_MSG_RESULT(socket)],
+  [RT_METHOD=rt_ioctl.o
+   AC_MSG_RESULT(ioctl)],
+  [KERNEL_METHOD=kernel_socket.o
+   RT_METHOD=rt_socket.o
+   AC_MSG_RESULT(socket)])
+  fi
+fi
+AC_SUBST(RT_METHOD)
+AC_SUBST(KERNEL_METHOD)
+AC_SUBST(OTHER_METHOD)
+
+dnl ------------------------------
+dnl check kernel route read method
+dnl ------------------------------
+AC_CACHE_CHECK(route read method check, zebra_rtread,
+[if test "$netlink" = yes; then
+  RTREAD_METHOD="rtread_netlink.o"
+  zebra_rtread="netlink"
+else
+for zebra_rtread in /proc/net/route /dev/ip /dev/null;
+do
+  test x`ls $zebra_rtread 2>/dev/null` = x"$zebra_rtread" && break
+done
+case $zebra_rtread in
+  "/proc/net/route") RTREAD_METHOD="rtread_proc.o"
+                     zebra_rtread="proc";;
+  "/dev/ip")         RTREAD_METHOD="rtread_getmsg.o"
+                     zebra_rtread="getmsg";;
+  *)                 RTREAD_METHOD="rtread_sysctl.o"
+                     zebra_rtread="sysctl";;
+esac
+fi])
+AC_SUBST(RTREAD_METHOD)
+
+dnl -----------------------------
+dnl check interface lookup method
+dnl -----------------------------
+AC_MSG_CHECKING(interface looking up method)
+if test "$netlink" = yes; then
+  AC_MSG_RESULT(netlink)
+  IF_METHOD=if_netlink.o
+else
+  if test "$opsys" = "sol2-6";then
+    AC_MSG_RESULT(solaris)
+    IF_METHOD=if_ioctl.o
+  elif test "$opsys" = "openbsd";then
+    AC_MSG_RESULT(openbsd)
+    IF_METHOD=if_ioctl.o
+  elif grep NET_RT_IFLIST /usr/include/sys/socket.h >/dev/null 2>&1; then
+    AC_MSG_RESULT(sysctl)
+    IF_METHOD=if_sysctl.o
+    AC_DEFINE(HAVE_NET_RT_IFLIST)
+  else
+    AC_MSG_RESULT(ioctl)
+    IF_METHOD=if_ioctl.o
+  fi
+fi
+AC_SUBST(IF_METHOD)
+
+dnl -----------------------
+dnl check proc file system.
+dnl -----------------------
+if test -r /proc/net/dev; then
+  AC_DEFINE(HAVE_PROC_NET_DEV)
+  IF_PROC=if_proc.o
+fi
+
+if test -r /proc/net/if_inet6; then
+  AC_DEFINE(HAVE_PROC_NET_IF_INET6)
+  IF_PROC=if_proc.o
+fi
+AC_SUBST(IF_PROC)
+
+dnl -----------------------------
+dnl check ipforward detect method
+dnl -----------------------------
+AC_CACHE_CHECK(ipforward method check, zebra_ipforward_path,
+[for zebra_ipforward_path in /proc/net/snmp /dev/ip /dev/null;
+do
+  test x`ls $zebra_ipforward_path 2>/dev/null` = x"$zebra_ipforward_path" && break
+done
+case $zebra_ipforward_path in
+  "/proc/net/snmp")  IPFORWARD=ipforward_proc.o
+                     zebra_ipforward_path="proc";;
+  "/dev/ip")         
+                     case "$host" in
+                       *-nec-sysv4*)  IPFORWARD=ipforward_ews.o
+                                      zebra_ipforward_path="ews";;
+                       *)             IPFORWARD=ipforward_solaris.o
+                                      zebra_ipforward_path="solaris";;
+                     esac;;
+  *)                 IPFORWARD=ipforward_sysctl.o
+                     zebra_ipforward_path="sysctl";;
+esac])
+AC_SUBST(IPFORWARD)
+
+AC_CHECK_FUNCS(getaddrinfo, [have_getaddrinfo=yes], [have_getaddrinfo=no])
+
+dnl ----------
+dnl IPv6 check
+dnl ----------
+AC_MSG_CHECKING(whether does this OS have IPv6 stack)
+if test "${enable_ipv6}" = "no"; then
+  AC_MSG_RESULT(disabled)
+else
+dnl ----------
+dnl INRIA IPv6
+dnl ----------
+if grep IPV6_INRIA_VERSION /usr/include/netinet/in.h >/dev/null 2>&1; then
+   zebra_cv_ipv6=yes
+   AC_DEFINE(HAVE_IPV6)
+   AC_DEFINE(INRIA_IPV6)
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   LIB_IPV6=""
+   AC_MSG_RESULT(INRIA IPv6)
+fi
+dnl ---------
+dnl KAME IPv6
+dnl ---------
+if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then
+   zebra_cv_ipv6=yes
+   AC_DEFINE(HAVE_IPV6)
+   AC_DEFINE(KAME)
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then
+      LIB_IPV6="-L/usr/local/v6/lib -linet6"
+   fi
+   AC_MSG_RESULT(KAME)
+fi
+dnl ---------
+dnl NRL check
+dnl ---------
+if grep NRL /usr/include/netinet6/in6.h >/dev/null 2>&1; then
+   zebra_cv_ipv6=yes
+   AC_DEFINE(HAVE_IPV6)
+   AC_DEFINE(NRL)
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   if test x"$opsys" = x"bsdi";then
+      AC_DEFINE(BSDI_NRL)
+      AC_MSG_RESULT(BSDI_NRL)
+   else
+      AC_MSG_RESULT(NRL)
+   fi
+fi
+
+dnl ----------
+dnl Linux IPv6
+dnl ----------
+if test "${enable_ipv6}" = "yes"; then
+   AC_EGREP_CPP(yes, [
+   #include <linux/version.h>
+   /* 2.1.128 or later */
+   #if LINUX_VERSION_CODE >= 0x020180
+   yes
+   #endif],
+   [zebra_cv_ipv6=yes; zebra_cv_linux_ipv6=yes;AC_MSG_RESULT(Linux IPv6)])
+else
+   if test x`ls /proc/net/ipv6_route 2>/dev/null` = x"/proc/net/ipv6_route"
+   then
+      zebra_cv_ipv6=yes
+      zebra_cv_linux_ipv6=yes
+      AC_MSG_RESULT(Linux IPv6)
+   fi
+fi
+
+if test "$zebra_cv_linux_ipv6" = "yes";then
+   AC_DEFINE(HAVE_IPV6)
+   AC_MSG_CHECKING(for GNU libc 2.1)
+   AC_EGREP_CPP(yes, [
+#include <features.h>
+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+  yes
+#endif], [glibc=yes; AC_MSG_RESULT(yes)], AC_MSG_RESULT(no))
+   AC_DEFINE(LINUX_IPV6)   
+   RIPNGD="ripngd"
+   OSPF6D="ospf6d"
+   if test "$glibc" != "yes"; then
+      INCLUDES="-I/usr/inet6/include"
+      if test x`ls /usr/inet6/lib/libinet6.a 2>/dev/null` != x;then
+         LIB_IPV6="-L/usr/inet6/lib -linet6"
+      fi
+   fi
+fi
+
+dnl -----------------------
+dnl Set IPv6 related values
+dnl -----------------------
+LIBS="$LIB_IPV6 $LIBS"
+AC_SUBST(LIB_IPV6)
+
+if test x"$RIPNGD" = x""; then
+  AC_MSG_RESULT(IPv4 only)
+fi
+fi
+
+dnl --------------------
+dnl Daemon disable check
+dnl --------------------
+if test "${enable_zebra}" = "no";then
+  ZEBRA=""
+else
+  ZEBRA="zebra"
+fi
+
+if test "${enable_bgpd}" = "no";then
+  BGPD=""
+else
+  BGPD="bgpd"
+fi
+
+if test "${enable_ripd}" = "no";then
+  RIPD=""
+else
+  RIPD="ripd"
+fi
+
+if test "${enable_ospfd}" = "no";then
+  OSPFD=""
+else
+  OSPFD="ospfd"
+fi
+
+case "${enable_ripngd}" in
+  "yes") RIPNGD="ripngd";;
+  "no" ) RIPNGD="";;
+  *    ) ;;
+esac
+
+case "${enable_ospf6d}" in
+  "yes") OSPF6D="ospf6d";;
+  "no" ) OSPF6D="";;
+  *    ) ;;
+esac
+
+case "${enable_isisd}" in
+  "yes") ISISD="isisd";;
+  "no" ) ISISD="";;
+  *    ) ;;
+esac
+
+if test "${enable_bgp_announce}" = "no";then
+  AC_DEFINE(DISABLE_BGP_ANNOUNCE)
+fi
+
+AC_SUBST(ZEBRA)
+AC_SUBST(BGPD)
+AC_SUBST(RIPD)
+AC_SUBST(RIPNGD)
+AC_SUBST(OSPFD)
+AC_SUBST(OSPF6D)
+AC_SUBST(ISISD)
+AC_SUBST(VTYSH)
+AC_SUBST(INCLUDES)
+AC_SUBST(CURSES)
+AC_CHECK_LIB(c, inet_ntop, [AC_DEFINE(HAVE_INET_NTOP)])
+AC_CHECK_LIB(c, inet_pton, [AC_DEFINE(HAVE_INET_PTON)])
+AC_CHECK_LIB(crypt, crypt)
+AC_CHECK_LIB(resolv, res_init)
+AC_CHECK_LIB(m, main)
+
+dnl ---------------------------------------------------
+dnl BSD/OS 4.1 define inet_XtoY function as __inet_XtoY
+dnl ---------------------------------------------------
+AC_CHECK_FUNC(__inet_ntop, AC_DEFINE(HAVE_INET_NTOP))
+AC_CHECK_FUNC(__inet_pton, AC_DEFINE(HAVE_INET_PTON))
+AC_CHECK_FUNC(__inet_aton, AC_DEFINE(HAVE_INET_ATON))
+
+dnl ---------------------------
+dnl check system has GNU regexp
+dnl ---------------------------
+dnl AC_MSG_CHECKING(whether system has GNU regex)
+AC_CHECK_LIB(c, regexec,
+[AC_DEFINE(HAVE_GNU_REGEX)
+ LIB_REGEX=""],
+[LIB_REGEX="regex.o"])
+AC_SUBST(LIB_REGEX)
+
+dnl AC_MSG_CHECKING(whether system has GNU regex)
+dnl if grep RE_NO_GNU_OPS /usr/include/regex.h >/dev/null 2>&1; then
+dnl   AC_MSG_RESULT(yes)
+dnl   AC_DEFINE(HAVE_GNU_REGEX)
+dnl   LIB_REGEX=""
+dnl else
+dnl   AC_MSG_RESULT(no)
+dnl   LIB_REGEX="regex.o"
+dnl fi
+dnl AC_SUBST(LIB_REGEX)
+
+dnl ------------------
+dnl check SNMP library
+dnl ------------------
+if test "${enable_snmp}" = "yes";then
+dnl  AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
+  old_libs="${LIBS}"
+  LIBS="-L/usr/local/lib"
+  unset ac_cv_lib_snmp_asn_parse_int
+  AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes, )
+  if test "${HAVE_SNMP}" = ""; then
+    unset ac_cv_lib_snmp_asn_parse_int
+    AC_CHECK_LIB(crypto, main, [NEED_CRYPTO=yes ], )
+	if test "${NEED_CRYPTO}" = ""; then 
+		AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes ],)
+	else
+	    AC_CHECK_LIB(snmp, asn_parse_int, [HAVE_SNMP=yes; NEED_CRYPTO=yes;LIBS="$LIBS -lcrypto" ],,"-lcrypto")
+	fi
+  fi
+  LIBS="${old_libs}"
+
+  if test "${HAVE_SNMP}" = ""; then
+	old_libs="${LIBS}"
+	LIBS="-L/usr/local/lib"
+	AC_CHECK_LIB(snmp, asn_parse_int, HAVE_SNMP=yes)
+	LIBS="${old_libs}"
+  fi
+  if test "${HAVE_SNMP}" = "yes"; then
+    for ac_snmp in /usr/include/ucd-snmp/asn1.h /usr/local/include/ucd-snmp/asn1.h /dev/null
+    do
+      test -f "${ac_snmp}" && break
+    done
+    case ${ac_snmp} in
+      /usr/include/ucd-snmp/*) 
+                  AC_DEFINE(HAVE_SNMP)
+                  CFLAGS="${CFLAGS} -I/usr/include/ucd-snmp"
+    		  LIBS="${LIBS} -lsnmp"
+                  ;;
+      /usr/local/include/ucd-snmp/*) 
+                  AC_DEFINE(HAVE_SNMP)
+  	          CFLAGS="${CFLAGS} -I/usr/local/include/ucd-snmp"
+  		  LIBS="${LIBS} -L/usr/local/lib -lsnmp"
+                  ;;
+    esac
+    if test "${NEED_CRYPTO}" = "yes"; then
+      LIBS="${LIBS} -lcrypto"
+    fi
+  fi
+fi
+
+dnl ----------------------------
+dnl check sa_len of sockaddr
+dnl ----------------------------
+AC_MSG_CHECKING(whether struct sockaddr has a sa_len field)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+],[static struct sockaddr ac_i;int ac_j = sizeof (ac_i.sa_len);],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SA_LEN)],
+ AC_MSG_RESULT(no))
+
+dnl ----------------------------
+dnl check sin_len of sockaddr_in
+dnl ----------------------------
+AC_MSG_CHECKING(whether struct sockaddr_in has a sin_len field)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>
+],[static struct sockaddr_in ac_i;int ac_j = sizeof (ac_i.sin_len);],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SIN_LEN)],
+ AC_MSG_RESULT(no))
+
+dnl ----------------------------
+dnl check sun_len of sockaddr_un
+dnl ----------------------------
+AC_MSG_CHECKING(whether struct sockaddr_un has a sun_len field)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/un.h>
+],[static struct sockaddr_un ac_i;int ac_j = sizeof (ac_i.sun_len);],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SUN_LEN)],
+ AC_MSG_RESULT(no))
+
+dnl -----------------------------------
+dnl check sin6_scope_id of sockaddr_in6
+dnl -----------------------------------
+if test "$zebra_cv_ipv6" = yes; then
+  AC_MSG_CHECKING(whether struct sockaddr_in6 has a sin6_scope_id field)
+  AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>
+],[static struct sockaddr_in6 ac_i;int ac_j = sizeof (ac_i.sin6_scope_id);],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SIN6_SCOPE_ID)],
+ AC_MSG_RESULT(no))
+fi
+
+dnl ----------------------------
+dnl check socklen_t exist or not
+dnl ----------------------------
+AC_MSG_CHECKING(whther socklen_t is defined)
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+],[socklen_t ac_x;],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SOCKLEN_T)],
+ AC_MSG_RESULT(no))
+
+dnl ------------------------
+dnl check struct sockaddr_dl
+dnl ------------------------
+AC_MSG_CHECKING(whether struct sockaddr_dl exist)
+AC_EGREP_HEADER(sockaddr_dl,
+net/if_dl.h,
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SOCKADDR_DL)],
+ AC_MSG_RESULT(no))
+
+dnl --------------------------
+dnl check structure ifaliasreq
+dnl --------------------------
+AC_MSG_CHECKING(whether struct ifaliasreq exist)
+AC_EGREP_HEADER(ifaliasreq,
+net/if.h,
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IFALIASREQ)],
+ AC_MSG_RESULT(no))
+
+dnl ----------------------------
+dnl check structure in6_aliasreq
+dnl ----------------------------
+AC_MSG_CHECKING(whether struct if6_aliasreq exist)
+AC_EGREP_HEADER(in6_aliasreq,
+netinet6/in6_var.h,
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IN6_ALIASREQ)],
+ AC_MSG_RESULT(no))
+
+dnl ---------------------------
+dnl check structure rt_addrinfo
+dnl ---------------------------
+AC_MSG_CHECKING(whether struct rt_addrinfo exist)
+AC_EGREP_HEADER(rt_addrinfo,
+net/route.h,
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RT_ADDRINFO)],
+ AC_MSG_RESULT(no))
+
+dnl --------------------------
+dnl check structure in_pktinfo
+dnl --------------------------
+AC_MSG_CHECKING(whether struct in_pktinfo exist)
+AC_TRY_COMPILE([#include <netinet/in.h>
+],[struct in_pktinfo ac_x;],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INPKTINFO)],
+ AC_MSG_RESULT(no))
+
+dnl --------------------------------------
+dnl checking for getrusage struct and call
+dnl --------------------------------------
+AC_MSG_CHECKING(whether getrusage is available)
+AC_TRY_COMPILE([#include <sys/resource.h>
+],[struct rusage ac_x; getrusage (RUSAGE_SELF, &ac_x);],
+[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_RUSAGE)],
+ AC_MSG_RESULT(no))
+
+dnl -------------
+dnl check version
+dnl -------------
+file="${srcdir}/lib/version.h"
+VERSION=`sed -ne 's/^#.*ZEBRA_VERSION.*\"\([^\"]*\)\"$/\1/p' $file`
+AC_SUBST(VERSION)
+
+dnl ------------------------------
+dnl set paths for process id files
+dnl ------------------------------
+AC_CACHE_CHECK(pid file directory,ac_piddir,
+[for ZEBRA_PID_DIR in /var/run	dnl
+                   /var/adm	dnl
+                   /etc		dnl
+                   /dev/null;
+do
+  test -d $ZEBRA_PID_DIR && break
+done
+ac_piddir=$ZEBRA_PID_DIR
+if test $ZEBRA_PID_DIR = "/dev/null"; then
+  echo "PID DIRECTORY NOT FOUND!"
+fi])
+AC_DEFINE_UNQUOTED(PATH_ZEBRA_PID, "$ac_piddir/zebra.pid")
+AC_DEFINE_UNQUOTED(PATH_RIPD_PID, "$ac_piddir/ripd.pid")
+AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$ac_piddir/ripngd.pid")
+AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$ac_piddir/bgpd.pid")
+AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$ac_piddir/ospfd.pid")
+AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$ac_piddir/ospf6d.pid")
+AC_DEFINE_UNQUOTED(PATH_ISISD_PID, "$ac_piddir/isisd.pid")
+
+dnl ---------------------------
+dnl Check htonl works correctly
+dnl ---------------------------
+AC_MSG_CHECKING(for working htonl)
+AC_CACHE_VAL(ac_cv_htonl_works, [
+AC_TRY_LINK([#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif],
+[htonl (0);],
+ac_cv_htonl_works=yes,
+ac_cv_htonl_works=no)])
+AC_MSG_RESULT($ac_cv_htonl_works)
+
+AC_OUTPUT(Makefile lib/Makefile zebra/Makefile ripd/Makefile ripngd/Makefile bgpd/Makefile ospfd/Makefile ospf6d/Makefile isisd/Makefile vtysh/Makefile doc/Makefile)
+
+echo "
+zebra configuration
+-------------------
+zebra version           : ${VERSION}
+host operationg system  : ${host_os}
+source code location    : ${srcdir}
+compiler                : ${CC}
+compiler flags          : ${CFLAGS}
+directory for pid files : ${ac_piddir}
+"
diff --git a/isisd/modified/log.c b/isisd/modified/log.c
new file mode 100644
index 0000000..385fb38
--- /dev/null
+++ b/isisd/modified/log.c
@@ -0,0 +1,484 @@
+/* Logging of zebra
+ * Copyright (C) 1997, 1998, 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.  
+ */
+
+#include <zebra.h>
+
+#include "log.h"
+#include "memory.h"
+#include "command.h"
+
+struct zlog *zlog_default = NULL;
+
+const char *zlog_proto_names[] = 
+{
+  "NONE",
+  "DEFAULT",
+  "ZEBRA",
+  "RIP",
+  "BGP",
+  "OSPF",
+  "RIPNG",
+  "OSPF6",
+  "ISIS",
+  "MASC",
+  NULL,
+};
+
+const char *zlog_priority[] =
+{
+  "emergencies",
+  "alerts",
+  "critical",
+  "errors",
+  "warnings",
+  "notifications",
+  "informational",
+  "debugging",
+  NULL,
+};
+  
+
+
+/* For time string format. */
+#define TIME_BUF 27
+
+/* Utility routine for current time printing. */
+static void
+time_print (FILE *fp)
+{
+  int ret;
+  char buf [TIME_BUF];
+  time_t clock;
+  struct tm *tm;
+  
+  time (&clock);
+  tm = localtime (&clock);
+
+  ret = strftime (buf, TIME_BUF, "%Y/%m/%d %H:%M:%S", tm);
+  if (ret == 0) {
+    zlog_warn ("strftime error");
+  }
+
+  fprintf (fp, "%s ", buf);
+}
+
+/* va_list version of zlog. */
+void
+vzlog (struct zlog *zl, int priority, const char *format, va_list *args)
+{
+  /* If zlog is not specified, use default one. */
+  if (zl == NULL)
+    zl = zlog_default;
+
+  /* When zlog_default is also NULL, use stderr for logging. */
+  if (zl == NULL)
+    {
+      time_print (stderr);
+      fprintf (stderr, "%s: ", "unknown");
+      vfprintf (stderr, format, args[ZLOG_NOLOG_INDEX]);
+      fprintf (stderr, "\n");
+      fflush (stderr);
+
+      /* In this case we return at here. */
+      return;
+    }
+
+  /* only log this information if it has not been masked out */
+  if ( priority > zl->maskpri )
+    return ;
+		
+  /* Syslog output */
+  if (zl->flags & ZLOG_SYSLOG)
+    vsyslog (priority, format, args[ZLOG_SYSLOG_INDEX]);
+
+  /* File output. */
+  if (zl->flags & ZLOG_FILE)
+    {
+      time_print (zl->fp);
+      if (zl->record_priority) fprintf (zl->fp, "%s: ", zlog_priority[priority]);
+      fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
+      vfprintf (zl->fp, format, args[ZLOG_FILE_INDEX]);
+      fprintf (zl->fp, "\n");
+      fflush (zl->fp);
+    }
+
+  /* stdout output. */
+  if (zl->flags & ZLOG_STDOUT)
+    {
+      time_print (stdout);
+      if (zl->record_priority) fprintf (stdout, "%s: ", zlog_priority[priority]);
+      fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
+      vfprintf (stdout, format, args[ZLOG_STDOUT_INDEX]);
+      fprintf (stdout, "\n");
+      fflush (stdout);
+    }
+
+  /* stderr output. */
+  if (zl->flags & ZLOG_STDERR)
+    {
+      time_print (stderr);
+      if (zl->record_priority) fprintf (stderr, "%s: ", zlog_priority[priority]);
+      fprintf (stderr, "%s: ", zlog_proto_names[zl->protocol]);
+      vfprintf (stderr, format, args[ZLOG_STDERR_INDEX]);
+      fprintf (stderr, "\n");
+      fflush (stderr);
+    }
+
+  /* Terminal monitor. */
+  vty_log (zlog_proto_names[zl->protocol], format, args[ZLOG_NOLOG_INDEX]);
+}
+
+void
+zlog (struct zlog *zl, int priority, const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (zl, priority, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+zlog_err (const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (NULL, LOG_ERR, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+zlog_warn (const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (NULL, LOG_WARNING, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+zlog_info (const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (NULL, LOG_INFO, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+zlog_notice (const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (NULL, LOG_NOTICE, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+zlog_debug (const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (NULL, LOG_DEBUG, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+plog_err (struct zlog *zl, const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (zl, LOG_ERR, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+plog_warn (struct zlog *zl, const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (zl, LOG_WARNING, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+plog_info (struct zlog *zl, const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (zl, LOG_INFO, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+plog_notice (struct zlog *zl, const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (zl, LOG_NOTICE, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+void
+plog_debug (struct zlog *zl, const char *format, ...)
+{
+  va_list args[ZLOG_MAX_INDEX];
+  int index;
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_start(args[index], format);
+
+  vzlog (zl, LOG_DEBUG, format, args);
+
+  for (index = 0; index < ZLOG_MAX_INDEX; index++)
+    va_end (args[index]);
+}
+
+
+/* Open log stream */
+struct zlog *
+openzlog (const char *progname, int flags, zlog_proto_t protocol,
+	  int syslog_flags, int syslog_facility)
+{
+  struct zlog *zl;
+
+  zl = XMALLOC(MTYPE_ZLOG, sizeof (struct zlog));
+  memset (zl, 0, sizeof (struct zlog));
+
+  zl->ident = progname;
+  zl->flags = flags;
+  zl->protocol = protocol;
+  zl->facility = syslog_facility;
+  zl->maskpri = LOG_DEBUG;
+  zl->record_priority = 0;
+
+  openlog (progname, syslog_flags, zl->facility);
+  
+  return zl;
+}
+
+void
+closezlog (struct zlog *zl)
+{
+  closelog();
+  fclose (zl->fp);
+
+  XFREE (MTYPE_ZLOG, zl);
+}
+
+/* Called from command.c. */
+void
+zlog_set_flag (struct zlog *zl, int flags)
+{
+  if (zl == NULL)
+    zl = zlog_default;
+
+  zl->flags |= flags;
+}
+
+void
+zlog_reset_flag (struct zlog *zl, int flags)
+{
+  if (zl == NULL)
+    zl = zlog_default;
+
+  zl->flags &= ~flags;
+}
+
+int
+zlog_set_file (struct zlog *zl, int flags, char *filename)
+{
+  FILE *fp;
+
+  /* There is opend file.  */
+  zlog_reset_file (zl);
+
+  /* Set default zl. */
+  if (zl == NULL)
+    zl = zlog_default;
+
+  /* Open file. */
+  fp = fopen (filename, "a");
+  if (fp == NULL)
+    return 0;
+
+  /* Set flags. */
+  zl->filename = strdup (filename);
+  zl->flags |= ZLOG_FILE;
+  zl->fp = fp;
+
+  return 1;
+}
+
+/* Reset opend file. */
+int
+zlog_reset_file (struct zlog *zl)
+{
+  if (zl == NULL)
+    zl = zlog_default;
+
+  zl->flags &= ~ZLOG_FILE;
+
+  if (zl->fp)
+    fclose (zl->fp);
+  zl->fp = NULL;
+
+  if (zl->filename)
+    free (zl->filename);
+  zl->filename = NULL;
+
+  return 1;
+}
+
+/* Reopen log file. */
+int
+zlog_rotate (struct zlog *zl)
+{
+  FILE *fp;
+
+  if (zl == NULL)
+    zl = zlog_default;
+
+  if (zl->fp)
+    fclose (zl->fp);
+  zl->fp = NULL;
+
+  if (zl->filename)
+    {
+      fp = fopen (zl->filename, "a");
+      if (fp == NULL)
+	return -1;
+      zl->fp = fp;
+    }
+
+  return 1;
+}
+
+static char *zlog_cwd = NULL;
+
+void
+zlog_save_cwd ()
+{
+  char *cwd;
+
+  cwd = getcwd (NULL, MAXPATHLEN);
+
+  zlog_cwd = XMALLOC (MTYPE_TMP, strlen (cwd) + 1);
+  strcpy (zlog_cwd, cwd);
+}
+
+char *
+zlog_get_cwd ()
+{
+  return zlog_cwd;
+}
+
+void
+zlog_free_cwd ()
+{
+  if (zlog_cwd)
+    XFREE (MTYPE_TMP, zlog_cwd);
+}
+
+/* Message lookup function. */
+char *
+lookup (struct message *mes, int key)
+{
+  struct message *pnt;
+
+  for (pnt = mes; pnt->key != 0; pnt++) 
+    if (pnt->key == key) 
+      return pnt->str;
+
+  return "";
+}
+
+/* Very old hacky version of message lookup function.  Still partly
+   used in bgpd and ospfd. */
+char *
+mes_lookup (struct message *meslist, int max, int index)
+{
+  if (index < 0 || index >= max) 
+    {
+      zlog_err ("message index out of bound: %d", max);
+      return NULL;
+    }
+  return meslist[index].str;
+}
diff --git a/isisd/modified/log.h b/isisd/modified/log.h
new file mode 100644
index 0000000..8948ea0
--- /dev/null
+++ b/isisd/modified/log.h
@@ -0,0 +1,129 @@
+/* Zebra logging funcions.
+ * Copyright (C) 1997, 1998, 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.  
+ */
+
+#ifndef _ZEBRA_LOG_H
+#define _ZEBRA_LOG_H
+
+#include <syslog.h>
+
+#define ZLOG_NOLOG              0x00
+#define ZLOG_FILE		0x01
+#define ZLOG_SYSLOG		0x02
+#define ZLOG_STDOUT             0x04
+#define ZLOG_STDERR             0x08
+
+#define ZLOG_NOLOG_INDEX        0
+#define ZLOG_FILE_INDEX         1
+#define ZLOG_SYSLOG_INDEX       2
+#define ZLOG_STDOUT_INDEX       3
+#define ZLOG_STDERR_INDEX       4
+#define ZLOG_MAX_INDEX          5
+
+typedef enum 
+{
+  ZLOG_NONE,
+  ZLOG_DEFAULT,
+  ZLOG_ZEBRA,
+  ZLOG_RIP,
+  ZLOG_BGP,
+  ZLOG_OSPF,
+  ZLOG_RIPNG,  
+  ZLOG_OSPF6,
+  ZLOG_ISIS,
+  ZLOG_MASC
+} zlog_proto_t;
+
+struct zlog 
+{
+  const char *ident;
+  zlog_proto_t protocol;
+  int flags;
+  FILE *fp;
+  char *filename;
+  int syslog;
+  int stat;
+  int connected;
+  int maskpri;		/* as per syslog setlogmask */
+  int priority;		/* as per syslog priority */
+  int facility;		/* as per syslog facility */
+  int record_priority;
+};
+
+/* Message structure. */
+struct message
+{
+  int key;
+  char *str;
+};
+
+/* Default logging strucutre. */
+extern struct zlog *zlog_default;
+
+/* Open zlog function */
+struct zlog *openzlog (const char *, int, zlog_proto_t, int, int);
+
+/* Close zlog function. */
+void closezlog (struct zlog *zl);
+
+/* GCC have printf type attribute check.  */
+#ifdef __GNUC__
+#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#else
+#define PRINTF_ATTRIBUTE(a,b)
+#endif /* __GNUC__ */
+
+/* Generic function for zlog. */
+void zlog (struct zlog *zl, int priority, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
+
+/* Handy zlog functions. */
+void zlog_err (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
+void zlog_warn (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
+void zlog_info (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
+void zlog_notice (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
+void zlog_debug (const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
+
+/* For bgpd's peer oriented log. */
+void plog_err (struct zlog *, const char *format, ...);
+void plog_warn (struct zlog *, const char *format, ...);
+void plog_info (struct zlog *, const char *format, ...);
+void plog_notice (struct zlog *, const char *format, ...);
+void plog_debug (struct zlog *, const char *format, ...);
+
+/* Set zlog flags. */
+void zlog_set_flag (struct zlog *zl, int flags);
+void zlog_reset_flag (struct zlog *zl, int flags);
+
+/* Set zlog filename. */
+int zlog_set_file (struct zlog *zl, int flags, char *filename);
+int zlog_reset_file (struct zlog *zl);
+
+/* Rotate log. */
+int zlog_rotate ();
+
+/* For hackey massage lookup and check */
+#define LOOKUP(x, y) mes_lookup(x, x ## _max, y)
+
+char *lookup (struct message *, int);
+char *mes_lookup (struct message *meslist, int max, int index);
+
+extern const char *zlog_priority[];
+
+#endif /* _ZEBRA_LOG_H */
diff --git a/isisd/modified/memory.c b/isisd/modified/memory.c
new file mode 100644
index 0000000..49ff321
--- /dev/null
+++ b/isisd/modified/memory.c
@@ -0,0 +1,527 @@
+/*
+ * Memory management routine
+ * Copyright (C) 1998 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.  
+ */
+
+#include <zebra.h>
+
+#include "log.h"
+#include "memory.h"
+
+void alloc_inc (int);
+void alloc_dec (int);
+
+struct message mstr [] =
+{
+  { MTYPE_THREAD, "thread" },
+  { MTYPE_THREAD_MASTER, "thread_master" },
+  { MTYPE_VECTOR, "vector" },
+  { MTYPE_VECTOR_INDEX, "vector_index" },
+  { MTYPE_IF, "interface" },
+  { 0, NULL },
+};
+
+/* Fatal memory allocation error occured. */
+static void
+zerror (const char *fname, int type, size_t size)
+{
+  fprintf (stderr, "%s : can't allocate memory for `%s' size %d\n", 
+	   fname, lookup (mstr, type), (int) size);
+  exit (1);
+}
+
+/* Memory allocation. */
+void *
+zmalloc (int type, size_t size)
+{
+  void *memory;
+
+  memory = malloc (size);
+
+  if (memory == NULL)
+    zerror ("malloc", type, size);
+
+  alloc_inc (type);
+
+  return memory;
+}
+
+/* Memory allocation with num * size with cleared. */
+void *
+zcalloc (int type, size_t size)
+{
+  void *memory;
+
+  memory = calloc (1, size);
+
+  if (memory == NULL)
+    zerror ("calloc", type, size);
+
+  alloc_inc (type);
+
+  return memory;
+}
+
+/* Memory reallocation. */
+void *
+zrealloc (int type, void *ptr, size_t size)
+{
+  void *memory;
+
+  memory = realloc (ptr, size);
+  if (memory == NULL)
+    zerror ("realloc", type, size);
+  return memory;
+}
+
+/* Memory free. */
+void
+zfree (int type, void *ptr)
+{
+  alloc_dec (type);
+  free (ptr);
+}
+
+/* String duplication. */
+char *
+zstrdup (int type, char *str)
+{
+  void *dup;
+
+  dup = strdup (str);
+  if (dup == NULL)
+    zerror ("strdup", type, strlen (str));
+  alloc_inc (type);
+  return dup;
+}
+
+#ifdef MEMORY_LOG
+struct 
+{
+  char *name;
+  unsigned long alloc;
+  unsigned long t_malloc;
+  unsigned long c_malloc;
+  unsigned long t_calloc;
+  unsigned long c_calloc;
+  unsigned long t_realloc;
+  unsigned long t_free;
+  unsigned long c_strdup;
+} mstat [MTYPE_MAX];
+
+void
+mtype_log (char *func, void *memory, const char *file, int line, int type)
+{
+  zlog_info ("%s: %s %p %s %d", func, lookup (mstr, type), memory, file, line);
+}
+
+void *
+mtype_zmalloc (const char *file, int line, int type, size_t size)
+{
+  void *memory;
+
+  mstat[type].c_malloc++;
+  mstat[type].t_malloc++;
+
+  memory = zmalloc (type, size);
+  mtype_log ("zmalloc", memory, file, line, type);
+
+  return memory;
+}
+
+void *
+mtype_zcalloc (const char *file, int line, int type, size_t size)
+{
+  void *memory;
+
+  mstat[type].c_calloc++;
+  mstat[type].t_calloc++;
+
+  memory = zcalloc (type, size);
+  mtype_log ("xcalloc", memory, file, line, type);
+
+  return memory;
+}
+
+void *
+mtype_zrealloc (const char *file, int line, int type, void *ptr, size_t size)
+{
+  void *memory;
+
+  /* Realloc need before allocated pointer. */
+  mstat[type].t_realloc++;
+
+  memory = zrealloc (type, ptr, size);
+
+  mtype_log ("xrealloc", memory, file, line, type);
+
+  return memory;
+}
+
+/* Important function. */
+void 
+mtype_zfree (const char *file, int line, int type, void *ptr)
+{
+  mstat[type].t_free++;
+
+  mtype_log ("xfree", ptr, file, line, type);
+
+  zfree (type, ptr);
+}
+
+char *
+mtype_zstrdup (const char *file, int line, int type, char *str)
+{
+  char *memory;
+
+  mstat[type].c_strdup++;
+
+  memory = zstrdup (type, str);
+  
+  mtype_log ("xstrdup", memory, file, line, type);
+
+  return memory;
+}
+#else
+struct 
+{
+  char *name;
+  unsigned long alloc;
+} mstat [MTYPE_MAX];
+#endif /* MTPYE_LOG */
+
+/* Increment allocation counter. */
+void
+alloc_inc (int type)
+{
+  mstat[type].alloc++;
+}
+
+/* Decrement allocation counter. */
+void
+alloc_dec (int type)
+{
+  mstat[type].alloc--;
+}
+
+/* Looking up memory status from vty interface. */
+#include "vector.h"
+#include "vty.h"
+#include "command.h"
+
+/* For pretty printng of memory allocate information. */
+struct memory_list
+{
+  int index;
+  char *format;
+};
+
+struct memory_list memory_list_lib[] =
+{
+  { MTYPE_TMP,                "Temporary memory" },
+  { MTYPE_ROUTE_TABLE,        "Route table     " },
+  { MTYPE_ROUTE_NODE,         "Route node      " },
+  { MTYPE_RIB,                "RIB             " },
+  { MTYPE_NEXTHOP,            "Nexthop         " },
+  { MTYPE_LINK_LIST,          "Link List       " },
+  { MTYPE_LINK_NODE,          "Link Node       " },
+  { MTYPE_HASH,               "Hash            " },
+  { MTYPE_HASH_BACKET,        "Hash Bucket     " },
+  { MTYPE_ACCESS_LIST,        "Access List     " },
+  { MTYPE_ACCESS_LIST_STR,    "Access List Str " },
+  { MTYPE_ACCESS_FILTER,      "Access Filter   " },
+  { MTYPE_PREFIX_LIST,        "Prefix List     " },
+  { MTYPE_PREFIX_LIST_STR,    "Prefix List Str " },
+  { MTYPE_PREFIX_LIST_ENTRY,  "Prefix List Entry "},
+  { MTYPE_ROUTE_MAP,          "Route map       " },
+  { MTYPE_ROUTE_MAP_NAME,     "Route map name  " },
+  { MTYPE_ROUTE_MAP_INDEX,    "Route map index " },
+  { MTYPE_ROUTE_MAP_RULE,     "Route map rule  " },
+  { MTYPE_ROUTE_MAP_RULE_STR, "Route map rule str" },
+  { MTYPE_DESC,               "Command desc    " },
+  { MTYPE_BUFFER,             "Buffer          " },
+  { MTYPE_BUFFER_DATA,        "Buffer data     " },
+  { MTYPE_STREAM,             "Stream          " },
+  { MTYPE_KEYCHAIN,           "Key chain       " },
+  { MTYPE_KEY,                "Key             " },
+  { MTYPE_VTY,                "VTY             " },
+  { -1, NULL }
+};
+
+struct memory_list memory_list_bgp[] =
+{
+  { MTYPE_BGP_PEER,               "BGP peer" },
+  { MTYPE_ATTR,                   "BGP attribute" },
+  { MTYPE_AS_PATH,                "BGP aspath" },
+  { MTYPE_AS_SEG,                 "BGP aspath seg" },
+  { MTYPE_AS_STR,                 "BGP aspath str" },
+  { 0, NULL },
+  { MTYPE_BGP_TABLE,              "BGP table" },
+  { MTYPE_BGP_NODE,               "BGP node" },
+  { MTYPE_BGP_ADVERTISE_ATTR,     "BGP adv attr" },
+  { MTYPE_BGP_ADVERTISE,          "BGP adv" },
+  { MTYPE_BGP_ADJ_IN,             "BGP adj in" },
+  { MTYPE_BGP_ADJ_OUT,            "BGP adj out" },
+  { 0, NULL },
+  { MTYPE_AS_LIST,                "BGP AS list" },
+  { MTYPE_AS_FILTER,              "BGP AS filter" },
+  { MTYPE_AS_FILTER_STR,          "BGP AS filter str" },
+  { 0, NULL },
+  { MTYPE_COMMUNITY,              "community" },
+  { MTYPE_COMMUNITY_VAL,          "community val" },
+  { MTYPE_COMMUNITY_STR,          "community str" },
+  { 0, NULL },
+  { MTYPE_ECOMMUNITY,             "extcommunity" },
+  { MTYPE_ECOMMUNITY_VAL,         "extcommunity val" },
+  { MTYPE_ECOMMUNITY_STR,         "extcommunity str" },
+  { 0, NULL },
+  { MTYPE_COMMUNITY_LIST,         "community-list" },
+  { MTYPE_COMMUNITY_LIST_NAME,    "community-list name" },
+  { MTYPE_COMMUNITY_LIST_ENTRY,   "community-list entry" },
+  { MTYPE_COMMUNITY_LIST_CONFIG,  "community-list config" },
+  { 0, NULL },
+  { MTYPE_CLUSTER,                "Cluster list" },
+  { MTYPE_CLUSTER_VAL,            "Cluster list val" },
+  { 0, NULL },
+  { MTYPE_TRANSIT,                "BGP transit attr" },
+  { MTYPE_TRANSIT_VAL,            "BGP transit val" },
+  { 0, NULL },
+  { MTYPE_BGP_DISTANCE,           "BGP distance" },
+  { MTYPE_BGP_NEXTHOP_CACHE,      "BGP nexthop" },
+  { MTYPE_BGP_CONFED_LIST,        "BGP confed list" },
+  { MTYPE_PEER_UPDATE_SOURCE,     "peer update if" },
+  { MTYPE_BGP_DAMP_INFO,          "Dampening info" },
+  { MTYPE_BGP_REGEXP,             "BGP regexp" },
+  { -1, NULL }
+};
+
+struct memory_list memory_list_rip[] =
+{
+  { MTYPE_RIP,                "RIP structure   " },
+  { MTYPE_RIP_INFO,           "RIP route info  " },
+  { MTYPE_RIP_INTERFACE,      "RIP interface   " },
+  { MTYPE_RIP_PEER,           "RIP peer        " },
+  { MTYPE_RIP_OFFSET_LIST,    "RIP offset list " },
+  { MTYPE_RIP_DISTANCE,       "RIP distance    " },
+  { -1, NULL }
+};
+
+struct memory_list memory_list_ospf[] =
+{
+  { MTYPE_OSPF_TOP,           "OSPF top        " },
+  { MTYPE_OSPF_AREA,          "OSPF area       " },
+  { MTYPE_OSPF_AREA_RANGE,    "OSPF area range " },
+  { MTYPE_OSPF_NETWORK,       "OSPF network    " },
+#ifdef NBMA_ENABLE
+  { MTYPE_OSPF_NEIGHBOR_STATIC,"OSPF static nbr " },
+#endif  /* NBMA_ENABLE */
+  { MTYPE_OSPF_IF,            "OSPF interface  " },
+  { MTYPE_OSPF_NEIGHBOR,      "OSPF neighbor   " },
+  { MTYPE_OSPF_ROUTE,         "OSPF route      " },
+  { MTYPE_OSPF_TMP,           "OSPF tmp mem    " },
+  { MTYPE_OSPF_LSA,           "OSPF LSA        " },
+  { MTYPE_OSPF_LSA_DATA,      "OSPF LSA data   " },
+  { MTYPE_OSPF_LSDB,          "OSPF LSDB       " },
+  { MTYPE_OSPF_PACKET,        "OSPF packet     " },
+  { MTYPE_OSPF_FIFO,          "OSPF FIFO queue " },
+  { MTYPE_OSPF_VERTEX,        "OSPF vertex     " },
+  { MTYPE_OSPF_NEXTHOP,       "OSPF nexthop    " },
+  { MTYPE_OSPF_PATH,	      "OSPF path       " },
+  { MTYPE_OSPF_VL_DATA,       "OSPF VL data    " },
+  { MTYPE_OSPF_CRYPT_KEY,     "OSPF crypt key  " },
+  { MTYPE_OSPF_EXTERNAL_INFO, "OSPF ext. info  " },
+  { MTYPE_OSPF_DISTANCE,      "OSPF distance   " },
+  { MTYPE_OSPF_IF_INFO,       "OSPF if info    " },
+  { MTYPE_OSPF_IF_PARAMS,     "OSPF if params  " },
+  { -1, NULL },
+};
+
+struct memory_list memory_list_ospf6[] =
+{
+  { MTYPE_OSPF6_TOP,          "OSPF6 top         " },
+  { MTYPE_OSPF6_AREA,         "OSPF6 area        " },
+  { MTYPE_OSPF6_IF,           "OSPF6 interface   " },
+  { MTYPE_OSPF6_NEIGHBOR,     "OSPF6 neighbor    " },
+  { MTYPE_OSPF6_ROUTE,        "OSPF6 route       " },
+  { MTYPE_OSPF6_PREFIX,       "OSPF6 prefix      " },
+  { MTYPE_OSPF6_MESSAGE,      "OSPF6 message     " },
+  { MTYPE_OSPF6_LSA,          "OSPF6 LSA         " },
+  { MTYPE_OSPF6_LSA_SUMMARY,  "OSPF6 LSA summary " },
+  { MTYPE_OSPF6_LSDB,         "OSPF6 LSA database" },
+  { MTYPE_OSPF6_VERTEX,       "OSPF6 vertex      " },
+  { MTYPE_OSPF6_SPFTREE,      "OSPF6 SPF tree    " },
+  { MTYPE_OSPF6_NEXTHOP,      "OSPF6 nexthop     " },
+  { MTYPE_OSPF6_EXTERNAL_INFO,"OSPF6 ext. info   " },
+  { MTYPE_OSPF6_OTHER,        "OSPF6 other       " },
+  { -1, NULL },
+};
+
+
+struct memory_list memory_list_isis[] =
+{
+  { MTYPE_ISIS,               "ISIS             : %ld\r\n" },
+  { MTYPE_ISIS_TMP,           "ISIS TMP         : %ld\r\n" },
+  { MTYPE_ISIS_CIRCUIT,       "ISIS circuit     : %ld\r\n" },
+  { MTYPE_ISIS_LSP,           "ISIS LSP         : %ld\r\n" },
+  { MTYPE_ISIS_ADJACENCY,     "ISIS adjacency   : %ld\r\n" },
+  { MTYPE_ISIS_AREA,          "ISIS area        : %ld\r\n" },
+  { MTYPE_ISIS_AREA_ADDR,     "ISIS area address: %ld\r\n" },
+  { MTYPE_ISIS_TLV,           "ISIS TLV         : %ld\r\n" },
+  { MTYPE_ISIS_DYNHN,         "ISIS dyn hostname: %ld\r\n" },
+  { MTYPE_ISIS_SPFTREE,       "ISIS SPFtree     : %ld\r\n" },
+  { MTYPE_ISIS_VERTEX,        "ISIS vertex      : %ld\r\n" },
+  { MTYPE_ISIS_ROUTE_INFO,    "ISIS route info  : %ld\r\n" },
+  { MTYPE_ISIS_NEXTHOP,       "ISIS nexthop     : %ld\r\n" },
+  { MTYPE_ISIS_NEXTHOP6,      "ISIS nexthop6    : %ld\r\n" },
+  { -1, NULL },
+};
+
+struct memory_list memory_list_separator[] =
+{
+  { 0, NULL},
+  {-1, NULL}
+};
+
+void
+show_memory_vty (struct vty *vty, struct memory_list *list)
+{
+  struct memory_list *m;
+
+  for (m = list; m->index >= 0; m++)
+    if (m->index == 0)
+      vty_out (vty, "-----------------------------\r\n");
+    else
+      vty_out (vty, "%-22s: %5ld\r\n", m->format, mstat[m->index].alloc);
+}
+
+DEFUN (show_memory_all,
+       show_memory_all_cmd,
+       "show memory all",
+       "Show running system information\n"
+       "Memory statistics\n"
+       "All memory statistics\n")
+{
+  show_memory_vty (vty, memory_list_lib);
+  show_memory_vty (vty, memory_list_separator);
+  show_memory_vty (vty, memory_list_rip);
+  show_memory_vty (vty, memory_list_separator);
+  show_memory_vty (vty, memory_list_ospf);
+  show_memory_vty (vty, memory_list_separator);
+  show_memory_vty (vty, memory_list_ospf6);
+  show_memory_vty (vty, memory_list_separator);
+  show_memory_vty (vty, memory_list_bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (show_memory_all,
+       show_memory_cmd,
+       "show memory",
+       "Show running system information\n"
+       "Memory statistics\n")
+
+DEFUN (show_memory_lib,
+       show_memory_lib_cmd,
+       "show memory lib",
+       SHOW_STR
+       "Memory statistics\n"
+       "Library memory\n")
+{
+  show_memory_vty (vty, memory_list_lib);
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_memory_rip,
+       show_memory_rip_cmd,
+       "show memory rip",
+       SHOW_STR
+       "Memory statistics\n"
+       "RIP memory\n")
+{
+  show_memory_vty (vty, memory_list_rip);
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_memory_bgp,
+       show_memory_bgp_cmd,
+       "show memory bgp",
+       SHOW_STR
+       "Memory statistics\n"
+       "BGP memory\n")
+{
+  show_memory_vty (vty, memory_list_bgp);
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_memory_ospf,
+       show_memory_ospf_cmd,
+       "show memory ospf",
+       SHOW_STR
+       "Memory statistics\n"
+       "OSPF memory\n")
+{
+  show_memory_vty (vty, memory_list_ospf);
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_memory_ospf6,
+       show_memory_ospf6_cmd,
+       "show memory ospf6",
+       SHOW_STR
+       "Memory statistics\n"
+       "OSPF6 memory\n")
+{
+  show_memory_vty (vty, memory_list_ospf6);
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (show_memory_isis,
+       show_memory_isis_cmd,
+       "show memory isis",
+       SHOW_STR
+       "Memory statistics\n"
+       "ISIS memory\n")
+{
+  show_memory_vty (vty, memory_list_isis);
+  return CMD_SUCCESS;
+}
+
+void
+memory_init ()
+{
+  install_element (VIEW_NODE, &show_memory_cmd);
+  install_element (VIEW_NODE, &show_memory_all_cmd);
+  install_element (VIEW_NODE, &show_memory_lib_cmd);
+  install_element (VIEW_NODE, &show_memory_rip_cmd);
+  install_element (VIEW_NODE, &show_memory_bgp_cmd);
+  install_element (VIEW_NODE, &show_memory_ospf_cmd);
+  install_element (VIEW_NODE, &show_memory_ospf6_cmd);
+  install_element (VIEW_NODE, &show_memory_isis_cmd);
+
+  install_element (ENABLE_NODE, &show_memory_cmd);
+  install_element (ENABLE_NODE, &show_memory_all_cmd);
+  install_element (ENABLE_NODE, &show_memory_lib_cmd);
+  install_element (ENABLE_NODE, &show_memory_rip_cmd);
+  install_element (ENABLE_NODE, &show_memory_bgp_cmd);
+  install_element (ENABLE_NODE, &show_memory_ospf_cmd);
+  install_element (ENABLE_NODE, &show_memory_ospf6_cmd);
+  install_element (ENABLE_NODE, &show_memory_isis_cmd);
+}
diff --git a/isisd/modified/memory.h b/isisd/modified/memory.h
new file mode 100644
index 0000000..d80cdf5
--- /dev/null
+++ b/isisd/modified/memory.h
@@ -0,0 +1,257 @@
+/* Memory management routine
+   Copyright (C) 1998 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.  */
+
+#ifndef _ZEBRA_MEMORY_H
+#define _ZEBRA_MEMORY_H
+
+/* #define MEMORY_LOG */
+
+/* For tagging memory, below is the type of the memory. */
+enum
+{
+  MTYPE_TMP = 1,
+  MTYPE_STRVEC,
+  MTYPE_VECTOR,
+  MTYPE_VECTOR_INDEX,
+  MTYPE_LINK_LIST,
+  MTYPE_LINK_NODE,
+  MTYPE_THREAD,
+  MTYPE_THREAD_MASTER,
+  MTYPE_VTY,
+  MTYPE_VTY_HIST,
+  MTYPE_VTY_OUT_BUF,
+  MTYPE_IF,
+  MTYPE_CONNECTED,
+  MTYPE_AS_SEG,
+  MTYPE_AS_STR,
+  MTYPE_AS_PATH,
+  MTYPE_CLUSTER,
+  MTYPE_CLUSTER_VAL,
+  MTYPE_ATTR,
+  MTYPE_TRANSIT,
+  MTYPE_TRANSIT_VAL,
+  MTYPE_BUFFER,
+  MTYPE_BUFFER_DATA,
+  MTYPE_STREAM,
+  MTYPE_STREAM_DATA,
+  MTYPE_STREAM_FIFO,
+  MTYPE_PREFIX,
+  MTYPE_PREFIX_IPV4,
+  MTYPE_PREFIX_IPV6,
+  MTYPE_HASH,
+  MTYPE_HASH_INDEX,
+  MTYPE_HASH_BACKET,
+  MTYPE_RIPNG_ROUTE,
+  MTYPE_RIPNG_AGGREGATE,
+  MTYPE_ROUTE_TABLE,
+  MTYPE_ROUTE_NODE,
+  MTYPE_ACCESS_LIST,
+  MTYPE_ACCESS_LIST_STR,
+  MTYPE_ACCESS_FILTER,
+  MTYPE_PREFIX_LIST,
+  MTYPE_PREFIX_LIST_STR,
+  MTYPE_PREFIX_LIST_ENTRY,
+  MTYPE_ROUTE_MAP,
+  MTYPE_ROUTE_MAP_NAME,
+  MTYPE_ROUTE_MAP_INDEX,
+  MTYPE_ROUTE_MAP_RULE,
+  MTYPE_ROUTE_MAP_RULE_STR,
+  MTYPE_ROUTE_MAP_COMPILED,
+
+  MTYPE_RIB,
+  MTYPE_DISTRIBUTE,
+  MTYPE_ZLOG,
+  MTYPE_ZCLIENT,
+  MTYPE_NEXTHOP,
+  MTYPE_RTADV_PREFIX,
+  MTYPE_IF_RMAP,
+  MTYPE_SOCKUNION,
+  MTYPE_STATIC_IPV4,
+  MTYPE_STATIC_IPV6,
+
+  MTYPE_DESC,
+  MTYPE_OSPF_TOP,
+  MTYPE_OSPF_AREA,
+  MTYPE_OSPF_AREA_RANGE,
+  MTYPE_OSPF_NETWORK,
+  MTYPE_OSPF_NEIGHBOR_STATIC,
+  MTYPE_OSPF_IF,
+  MTYPE_OSPF_NEIGHBOR,
+  MTYPE_OSPF_ROUTE,
+  MTYPE_OSPF_TMP,
+  MTYPE_OSPF_LSA,
+  MTYPE_OSPF_LSA_DATA,
+  MTYPE_OSPF_LSDB,
+  MTYPE_OSPF_PACKET,
+  MTYPE_OSPF_FIFO,
+  MTYPE_OSPF_VERTEX,
+  MTYPE_OSPF_NEXTHOP,
+  MTYPE_OSPF_PATH,
+  MTYPE_OSPF_VL_DATA,
+  MTYPE_OSPF_CRYPT_KEY,
+  MTYPE_OSPF_EXTERNAL_INFO,
+  MTYPE_OSPF_MESSAGE,
+  MTYPE_OSPF_DISTANCE,
+  MTYPE_OSPF_IF_INFO,
+  MTYPE_OSPF_IF_PARAMS,
+
+  MTYPE_OSPF6_TOP,
+  MTYPE_OSPF6_AREA,
+  MTYPE_OSPF6_IF,
+  MTYPE_OSPF6_NEIGHBOR,
+  MTYPE_OSPF6_ROUTE,
+  MTYPE_OSPF6_PREFIX,
+  MTYPE_OSPF6_MESSAGE,
+  MTYPE_OSPF6_LSA,
+  MTYPE_OSPF6_LSA_SUMMARY,
+  MTYPE_OSPF6_LSDB,
+  MTYPE_OSPF6_VERTEX,
+  MTYPE_OSPF6_SPFTREE,
+  MTYPE_OSPF6_NEXTHOP,
+  MTYPE_OSPF6_EXTERNAL_INFO,
+  MTYPE_OSPF6_OTHER,
+  
+  MTYPE_ISIS,
+  MTYPE_ISIS_TMP,
+  MTYPE_ISIS_CIRCUIT,
+  MTYPE_ISIS_LSP,
+  MTYPE_ISIS_ADJACENCY,
+  MTYPE_ISIS_AREA,
+  MTYPE_ISIS_AREA_ADDR,
+  MTYPE_ISIS_TLV,
+  MTYPE_ISIS_DYNHN,
+  MTYPE_ISIS_SPFTREE,
+  MTYPE_ISIS_VERTEX,
+  MTYPE_ISIS_ROUTE_INFO,
+  MTYPE_ISIS_NEXTHOP,
+  MTYPE_ISIS_NEXTHOP6,
+
+  MTYPE_BGP,
+  MTYPE_BGP_PEER,
+  MTYPE_PEER_GROUP,
+  MTYPE_PEER_DESC,
+  MTYPE_PEER_UPDATE_SOURCE,
+  MTYPE_BGP_STATIC,
+  MTYPE_BGP_AGGREGATE,
+  MTYPE_BGP_CONFED_LIST,
+  MTYPE_BGP_NEXTHOP_CACHE,
+  MTYPE_BGP_DAMP_INFO,
+  MTYPE_BGP_DAMP_ARRAY,
+  MTYPE_BGP_ANNOUNCE,
+  MTYPE_BGP_ATTR_QUEUE,
+  MTYPE_BGP_ROUTE_QUEUE,
+  MTYPE_BGP_DISTANCE,
+  MTYPE_BGP_ROUTE,
+  MTYPE_BGP_TABLE,
+  MTYPE_BGP_NODE,
+  MTYPE_BGP_ADVERTISE_ATTR,
+  MTYPE_BGP_ADVERTISE,
+  MTYPE_BGP_ADJ_IN,
+  MTYPE_BGP_ADJ_OUT,
+  MTYPE_BGP_REGEXP,
+  MTYPE_AS_FILTER,
+  MTYPE_AS_FILTER_STR,
+  MTYPE_AS_LIST,
+
+  MTYPE_COMMUNITY,
+  MTYPE_COMMUNITY_VAL,
+  MTYPE_COMMUNITY_STR,
+
+  MTYPE_ECOMMUNITY,
+  MTYPE_ECOMMUNITY_VAL,
+  MTYPE_ECOMMUNITY_STR,
+
+  /* community-list and extcommunity-list.  */
+  MTYPE_COMMUNITY_LIST_HANDLER,
+  MTYPE_COMMUNITY_LIST,
+  MTYPE_COMMUNITY_LIST_NAME,
+  MTYPE_COMMUNITY_LIST_ENTRY,
+  MTYPE_COMMUNITY_LIST_CONFIG,
+
+  MTYPE_RIP,
+  MTYPE_RIP_INTERFACE,
+  MTYPE_RIP_DISTANCE,
+  MTYPE_RIP_OFFSET_LIST,
+  MTYPE_RIP_INFO,
+  MTYPE_RIP_PEER,
+  MTYPE_KEYCHAIN,
+  MTYPE_KEY,
+
+  MTYPE_VTYSH_CONFIG,
+  MTYPE_VTYSH_CONFIG_LINE,
+
+  MTYPE_MAX
+};
+
+#ifdef MEMORY_LOG
+#define XMALLOC(mtype, size) \
+  mtype_zmalloc (__FILE__, __LINE__, (mtype), (size))
+#define XCALLOC(mtype, size) \
+  mtype_zcalloc (__FILE__, __LINE__, (mtype), (size))
+#define XREALLOC(mtype, ptr, size)  \
+  mtype_zrealloc (__FILE__, __LINE__, (mtype), (ptr), (size))
+#define XFREE(mtype, ptr) \
+  mtype_zfree (__FILE__, __LINE__, (mtype), (ptr))
+#define XSTRDUP(mtype, str) \
+  mtype_zstrdup (__FILE__, __LINE__, (mtype), (str))
+#else
+#define XMALLOC(mtype, size)       zmalloc ((mtype), (size))
+#define XCALLOC(mtype, size)       zcalloc ((mtype), (size))
+#define XREALLOC(mtype, ptr, size) zrealloc ((mtype), (ptr), (size))
+#define XFREE(mtype, ptr)          zfree ((mtype), (ptr))
+#define XSTRDUP(mtype, str)        zstrdup ((mtype), (str))
+#endif /* MEMORY_LOG */
+
+/* Prototypes of memory function. */
+void *zmalloc (int type, size_t size);
+void *zcalloc (int type, size_t size);
+void *zrealloc (int type, void *ptr, size_t size);
+void  zfree (int type, void *ptr);
+char *zstrdup (int type, char *str);
+
+void *mtype_zmalloc (const char *file,
+		     int line,
+		     int type,
+		     size_t size);
+
+void *mtype_zcalloc (const char *file,
+		     int line,
+		     int type,
+		     size_t num,
+		     size_t size);
+
+void *mtype_zrealloc (const char *file,
+		     int line,
+		     int type, 
+		     void *ptr,
+		     size_t size);
+
+void mtype_zfree (const char *file,
+		  int line,
+		  int type,
+		  void *ptr);
+
+char *mtype_zstrdup (const char *file,
+		     int line,
+		     int type,
+		     char *str);
+void memory_init ();
+
+#endif /* _ZEBRA_MEMORY_H */
diff --git a/isisd/modified/rib.c b/isisd/modified/rib.c
new file mode 100644
index 0000000..39a7690
--- /dev/null
+++ b/isisd/modified/rib.c
@@ -0,0 +1,3321 @@
+/* Routing Information Base.
+ * Copyright (C) 1997, 98, 99, 2001 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.  
+ */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "table.h"
+#include "memory.h"
+#include "vty.h"
+#include "str.h"
+#include "command.h"
+#include "linklist.h"
+#include "if.h"
+#include "log.h"
+#include "sockunion.h"
+
+#include "zebra/rib.h"
+#include "zebra/rt.h"
+#include "zebra/zserv.h"
+#include "zebra/redistribute.h"
+#include "zebra/debug.h"
+
+/* Routing information base and static table for IPv4. */
+struct route_table *rib_table_ipv4;
+struct route_table *static_table_ipv4;
+
+/* Routing information base and static table for IPv6. */
+#ifdef HAVE_IPV6
+struct route_table *rib_table_ipv6;
+struct route_table *static_table_ipv6;
+#endif /* HAVE_IPV6 */
+
+/* Default rtm_table for all clients */
+extern int rtm_table_default;
+
+/* Each route type's string and default distance value. */
+struct
+{  
+  int key;
+  char c;
+  char *str;
+  int distance;
+} route_info[] =
+{
+  {ZEBRA_ROUTE_SYSTEM,  'X', "system",      0},
+  {ZEBRA_ROUTE_KERNEL,  'K', "kernel",      0},
+  {ZEBRA_ROUTE_CONNECT, 'C', "connected",   0},
+  {ZEBRA_ROUTE_STATIC,  'S', "static",      1},
+  {ZEBRA_ROUTE_RIP,     'R', "rip",       120},
+  {ZEBRA_ROUTE_RIPNG,   'R', "ripng",     120},
+  {ZEBRA_ROUTE_OSPF,    'O', "ospf",      110},
+  {ZEBRA_ROUTE_OSPF6,   'O', "ospf6",     110},
+  {ZEBRA_ROUTE_ISIS,    'I', "isis",      115},
+  {ZEBRA_ROUTE_BGP,     'B', "bgp",        20  /* IBGP is 200. */}
+};
+
+/* Add nexthop to the end of the list.  */
+void
+nexthop_add (struct rib *rib, struct nexthop *nexthop)
+{
+  struct nexthop *last;
+
+  for (last = rib->nexthop; last && last->next; last = last->next)
+    ;
+  if (last)
+    last->next = nexthop;
+  else
+    rib->nexthop = nexthop;
+  nexthop->prev = last;
+
+  rib->nexthop_num++;
+}
+
+/* Delete specified nexthop from the list. */
+void
+nexthop_delete (struct rib *rib, struct nexthop *nexthop)
+{
+  if (nexthop->next)
+    nexthop->next->prev = nexthop->prev;
+  if (nexthop->prev)
+    nexthop->prev->next = nexthop->next;
+  else
+    rib->nexthop = nexthop->next;
+  rib->nexthop_num--;
+}
+
+/* Free nexthop. */
+void
+nexthop_free (struct nexthop *nexthop)
+{
+  if (nexthop->type == NEXTHOP_TYPE_IFNAME && nexthop->ifname)
+    free (nexthop->ifname);
+  XFREE (MTYPE_NEXTHOP, nexthop);
+}
+
+struct nexthop *
+nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
+{
+  struct nexthop *nexthop;
+
+  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+  memset (nexthop, 0, sizeof (struct nexthop));
+  nexthop->type = NEXTHOP_TYPE_IFINDEX;
+  nexthop->ifindex = ifindex;
+
+  nexthop_add (rib, nexthop);
+
+  return nexthop;
+}
+
+struct nexthop *
+nexthop_ifname_add (struct rib *rib, char *ifname)
+{
+  struct nexthop *nexthop;
+
+  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+  memset (nexthop, 0, sizeof (struct nexthop));
+  nexthop->type = NEXTHOP_TYPE_IFNAME;
+  nexthop->ifname = strdup (ifname);
+
+  nexthop_add (rib, nexthop);
+
+  return nexthop;
+}
+
+struct nexthop *
+nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4)
+{
+  struct nexthop *nexthop;
+
+  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+  memset (nexthop, 0, sizeof (struct nexthop));
+  nexthop->type = NEXTHOP_TYPE_IPV4;
+  nexthop->gate.ipv4 = *ipv4;
+
+  nexthop_add (rib, nexthop);
+
+  return nexthop;
+}
+
+struct nexthop *
+nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, 
+			  unsigned int ifindex)
+{
+  struct nexthop *nexthop;
+
+  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+  memset (nexthop, 0, sizeof (struct nexthop));
+  nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+  nexthop->gate.ipv4 = *ipv4;
+  nexthop->ifindex = ifindex;
+
+  nexthop_add (rib, nexthop);
+
+  return nexthop;
+}
+
+#ifdef HAVE_IPV6
+struct nexthop *
+nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
+{
+  struct nexthop *nexthop;
+
+  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+  memset (nexthop, 0, sizeof (struct nexthop));
+  nexthop->type = NEXTHOP_TYPE_IPV6;
+  nexthop->gate.ipv6 = *ipv6;
+
+  nexthop_add (rib, nexthop);
+
+  return nexthop;
+}
+
+struct nexthop *
+nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
+			 char *ifname)
+{
+  struct nexthop *nexthop;
+
+  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+  memset (nexthop, 0, sizeof (struct nexthop));
+  nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
+  nexthop->gate.ipv6 = *ipv6;
+  nexthop->ifname = XSTRDUP (0, ifname);
+
+  nexthop_add (rib, nexthop);
+
+  return nexthop;
+}
+
+struct nexthop *
+nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
+			  unsigned int ifindex)
+{
+  struct nexthop *nexthop;
+
+  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+  memset (nexthop, 0, sizeof (struct nexthop));
+  nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+  nexthop->gate.ipv6 = *ipv6;
+  nexthop->ifindex = ifindex;
+
+  nexthop_add (rib, nexthop);
+
+  return nexthop;
+}
+#endif /* HAVE_IPV6 */
+
+/* If force flag is not set, do not modify falgs at all for uninstall
+   the route from FIB. */
+int
+nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
+		     struct route_node *top)
+{
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+  struct rib *match;
+  struct nexthop *newhop;
+
+  if (nexthop->type == NEXTHOP_TYPE_IPV4)
+    nexthop->ifindex = 0;
+
+  if (set)
+    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
+
+  /* Make lookup prefix. */
+  memset (&p, 0, sizeof (struct prefix_ipv4));
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+  p.prefix = nexthop->gate.ipv4;
+
+  rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
+  while (rn)
+    {
+      route_unlock_node (rn);
+      
+      /* If lookup self prefix return immidiately. */
+      if (rn == top)
+	return 0;
+
+      /* Pick up selected route. */
+      for (match = rn->info; match; match = match->next)
+	if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+	  break;
+
+      /* If there is no selected route or matched route is EGP, go up
+         tree. */
+      if (! match 
+	  || match->type == ZEBRA_ROUTE_BGP)
+	{
+	  do {
+	    rn = rn->parent;
+	  } while (rn && rn->info == NULL);
+	  if (rn)
+	    route_lock_node (rn);
+	}
+      else
+	{
+	  if (match->type == ZEBRA_ROUTE_CONNECT)
+	    {
+	      /* Directly point connected route. */
+	      newhop = match->nexthop;
+	      if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
+		nexthop->ifindex = newhop->ifindex;
+	      
+	      return 1;
+	    }
+	  else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
+	    {
+	      for (newhop = match->nexthop; newhop; newhop = newhop->next)
+		if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
+		    && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
+		  {
+		    if (set)
+		      {
+			SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
+			nexthop->rtype = newhop->type;
+			if (newhop->type == NEXTHOP_TYPE_IPV4 ||
+			    newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
+			  nexthop->rgate.ipv4 = newhop->gate.ipv4;
+			if (newhop->type == NEXTHOP_TYPE_IFINDEX
+			    || newhop->type == NEXTHOP_TYPE_IFNAME
+			    || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
+			  nexthop->rifindex = newhop->ifindex;
+		      }
+		    return 1;
+		  }
+	      return 0;
+	    }
+	  else
+	    {
+	      return 0;
+	    }
+	}
+    }
+  return 0;
+}
+
+#ifdef HAVE_IPV6
+/* If force flag is not set, do not modify falgs at all for uninstall
+   the route from FIB. */
+int
+nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
+		     struct route_node *top)
+{
+  struct prefix_ipv6 p;
+  struct route_node *rn;
+  struct rib *match;
+  struct nexthop *newhop;
+
+  if (nexthop->type == NEXTHOP_TYPE_IPV6)
+    nexthop->ifindex = 0;
+
+  if (set)
+    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
+
+  /* Make lookup prefix. */
+  memset (&p, 0, sizeof (struct prefix_ipv6));
+  p.family = AF_INET6;
+  p.prefixlen = IPV6_MAX_PREFIXLEN;
+  p.prefix = nexthop->gate.ipv6;
+
+  rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
+  while (rn)
+    {
+      route_unlock_node (rn);
+      
+      /* If lookup self prefix return immidiately. */
+      if (rn == top)
+	return 0;
+
+      /* Pick up selected route. */
+      for (match = rn->info; match; match = match->next)
+	if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+	  break;
+
+      /* If there is no selected route or matched route is EGP, go up
+         tree. */
+      if (! match
+	  || match->type == ZEBRA_ROUTE_BGP)
+	{
+	  do {
+	    rn = rn->parent;
+	  } while (rn && rn->info == NULL);
+	  if (rn)
+	    route_lock_node (rn);
+	}
+      else
+	{
+	  if (match->type == ZEBRA_ROUTE_CONNECT)
+	    {
+	      /* Directly point connected route. */
+	      newhop = match->nexthop;
+
+	      if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
+		nexthop->ifindex = newhop->ifindex;
+	      
+	      return 1;
+	    }
+	  else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
+	    {
+	      for (newhop = match->nexthop; newhop; newhop = newhop->next)
+		if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
+		    && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
+		  {
+		    if (set)
+		      {
+			SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
+			nexthop->rtype = newhop->type;
+			if (newhop->type == NEXTHOP_TYPE_IPV6
+			    || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
+			    || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
+			  nexthop->rgate.ipv6 = newhop->gate.ipv6;
+			if (newhop->type == NEXTHOP_TYPE_IFINDEX
+			    || newhop->type == NEXTHOP_TYPE_IFNAME
+			    || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
+			    || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
+			  nexthop->rifindex = newhop->ifindex;
+		      }
+		    return 1;
+		  }
+	      return 0;
+	    }
+	  else
+	    {
+	      return 0;
+	    }
+	}
+    }
+  return 0;
+}
+#endif /* HAVE_IPV6 */
+
+struct rib *
+rib_match_ipv4 (struct in_addr addr)
+{
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+  struct rib *match;
+  struct nexthop *newhop;
+
+  memset (&p, 0, sizeof (struct prefix_ipv4));
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+  p.prefix = addr;
+
+  rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
+
+  while (rn)
+    {
+      route_unlock_node (rn);
+      
+      /* Pick up selected route. */
+      for (match = rn->info; match; match = match->next)
+	if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+	  break;
+
+      /* If there is no selected route or matched route is EGP, go up
+         tree. */
+      if (! match 
+	  || match->type == ZEBRA_ROUTE_BGP)
+	{
+	  do {
+	    rn = rn->parent;
+	  } while (rn && rn->info == NULL);
+	  if (rn)
+	    route_lock_node (rn);
+	}
+      else
+	{
+	  if (match->type == ZEBRA_ROUTE_CONNECT)
+	    /* Directly point connected route. */
+	    return match;
+	  else
+	    {
+	      for (newhop = match->nexthop; newhop; newhop = newhop->next)
+		if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
+		  return match;
+	      return NULL;
+	    }
+	}
+    }
+  return NULL;
+}
+
+struct rib *
+rib_lookup_ipv4 (struct prefix_ipv4 *p)
+{
+  struct route_node *rn;
+  struct rib *match;
+  struct nexthop *nexthop;
+
+  rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
+
+  /* No route for this prefix. */
+  if (! rn)
+    return NULL;
+
+  /* Unlock node. */
+  route_unlock_node (rn);
+
+  /* Pick up selected route. */
+  for (match = rn->info; match; match = match->next)
+    if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+      break;
+
+  if (! match || match->type == ZEBRA_ROUTE_BGP)
+    return NULL;
+
+  if (match->type == ZEBRA_ROUTE_CONNECT)
+    return match;
+  
+  for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
+    if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+      return match;
+
+  return NULL;
+}
+
+#ifdef HAVE_IPV6
+struct rib *
+rib_match_ipv6 (struct in6_addr *addr)
+{
+  struct prefix_ipv6 p;
+  struct route_node *rn;
+  struct rib *match;
+  struct nexthop *newhop;
+
+  memset (&p, 0, sizeof (struct prefix_ipv6));
+  p.family = AF_INET6;
+  p.prefixlen = IPV6_MAX_PREFIXLEN;
+  IPV6_ADDR_COPY (&p.prefix, addr);
+
+  rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
+
+  while (rn)
+    {
+      route_unlock_node (rn);
+      
+      /* Pick up selected route. */
+      for (match = rn->info; match; match = match->next)
+	if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
+	  break;
+
+      /* If there is no selected route or matched route is EGP, go up
+         tree. */
+      if (! match 
+	  || match->type == ZEBRA_ROUTE_BGP)
+	{
+	  do {
+	    rn = rn->parent;
+	  } while (rn && rn->info == NULL);
+	  if (rn)
+	    route_lock_node (rn);
+	}
+      else
+	{
+	  if (match->type == ZEBRA_ROUTE_CONNECT)
+	    /* Directly point connected route. */
+	    return match;
+	  else
+	    {
+	      for (newhop = match->nexthop; newhop; newhop = newhop->next)
+		if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
+		  return match;
+	      return NULL;
+	    }
+	}
+    }
+  return NULL;
+}
+#endif /* HAVE_IPV6 */
+
+int
+nexthop_active_check (struct route_node *rn, struct rib *rib,
+		      struct nexthop *nexthop, int set)
+{
+  struct interface *ifp;
+
+  switch (nexthop->type)
+    {
+    case NEXTHOP_TYPE_IFINDEX:
+      ifp = if_lookup_by_index (nexthop->ifindex);
+      if (ifp && if_is_up (ifp))
+	SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+      else
+	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+      break;
+    case NEXTHOP_TYPE_IFNAME:
+    case NEXTHOP_TYPE_IPV6_IFNAME:
+      ifp = if_lookup_by_name (nexthop->ifname);
+      if (ifp && if_is_up (ifp))
+	{
+	  if (set)
+	    nexthop->ifindex = ifp->ifindex;
+	  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+	}
+      else
+	{
+	  if (set)
+	    nexthop->ifindex = 0;
+	  UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+	}
+      break;
+    case NEXTHOP_TYPE_IPV4:
+    case NEXTHOP_TYPE_IPV4_IFINDEX:
+      if (nexthop_active_ipv4 (rib, nexthop, set, rn))
+	SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+      else
+	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+      break;
+#ifdef HAVE_IPV6
+    case NEXTHOP_TYPE_IPV6:
+      if (nexthop_active_ipv6 (rib, nexthop, set, rn))
+	SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+      else
+	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+      break;
+    case NEXTHOP_TYPE_IPV6_IFINDEX:
+      if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
+	{
+	  ifp = if_lookup_by_index (nexthop->ifindex);
+	  if (ifp && if_is_up (ifp))
+	    SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+	  else
+	    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+	}
+      else
+	{
+	  if (nexthop_active_ipv6 (rib, nexthop, set, rn))
+	    SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+	  else
+	    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+	}
+      break;
+#endif /* HAVE_IPV6 */
+    default:
+      break;
+    }
+  return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+}
+
+int
+nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
+{
+  struct nexthop *nexthop;
+  int active;
+
+  rib->nexthop_active_num = 0;
+  UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+
+  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+    {
+      active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+      rib->nexthop_active_num += nexthop_active_check (rn, rib, nexthop, set);
+      if (active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+	SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+    }
+  return rib->nexthop_active_num;
+}
+
+#define RIB_SYSTEM_ROUTE(R) \
+        ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
+
+void
+newrib_free (struct rib *rib)
+{
+  struct nexthop *nexthop;
+  struct nexthop *next;
+
+  for (nexthop = rib->nexthop; nexthop; nexthop = next)
+    {
+      next = nexthop->next;
+      nexthop_free (nexthop);
+    }
+  XFREE (MTYPE_RIB, rib);
+}
+
+void
+rib_install_kernel (struct route_node *rn, struct rib *rib)
+{
+  int ret = 0;
+  struct nexthop *nexthop;
+
+  switch (PREFIX_FAMILY (&rn->p))
+    {
+    case AF_INET:
+      ret = kernel_add_ipv4 (&rn->p, rib);
+      break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      ret = kernel_add_ipv6 (&rn->p, rib);
+      break;
+#endif /* HAVE_IPV6 */
+    }
+
+  if (ret < 0)
+    {
+      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+	UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+    }
+}
+
+/* Uninstall the route from kernel. */
+int
+rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
+{
+  int ret = 0;
+  struct nexthop *nexthop;
+
+  switch (PREFIX_FAMILY (&rn->p))
+    {
+    case AF_INET:
+      ret = kernel_delete_ipv4 (&rn->p, rib);
+      break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      ret = kernel_delete_ipv6 (&rn->p, rib);
+      break;
+#endif /* HAVE_IPV6 */
+    }
+
+  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+
+  return ret;
+}
+
+/* Uninstall the route from kernel. */
+void
+rib_uninstall (struct route_node *rn, struct rib *rib)
+{
+  if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+    {
+      redistribute_delete (&rn->p, rib);
+      if (! RIB_SYSTEM_ROUTE (rib))
+	rib_uninstall_kernel (rn, rib);
+      UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
+    }
+}
+
+/* Core function for processing routing information base. */
+void
+rib_process (struct route_node *rn, struct rib *del)
+{
+  struct rib *rib;
+  struct rib *next;
+  struct rib *fib = NULL;
+  struct rib *select = NULL;
+
+  for (rib = rn->info; rib; rib = next)
+    {
+      next = rib->next;
+
+      /* Currently installed rib. */
+      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+	fib = rib;
+
+      /* Skip unreachable nexthop. */
+      if (! nexthop_active_update (rn, rib, 0))
+	continue;
+
+      /* Infinit distance. */
+      if (rib->distance == DISTANCE_INFINITY)
+	continue;
+
+      /* Newly selected rib. */
+      if (! select || rib->distance < select->distance 
+	  || rib->type == ZEBRA_ROUTE_CONNECT)
+	select = rib;
+    }
+
+  /* Deleted route check. */
+  if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
+    fib = del;
+
+  /* Same route is selected. */
+  if (select && select == fib)
+    {
+      if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
+	{
+	  redistribute_delete (&rn->p, select);
+	  if (! RIB_SYSTEM_ROUTE (select))
+	    rib_uninstall_kernel (rn, select);
+
+	  /* Set real nexthop. */
+	  nexthop_active_update (rn, select, 1);
+  
+	  if (! RIB_SYSTEM_ROUTE (select))
+	    rib_install_kernel (rn, select);
+	  redistribute_add (&rn->p, select);
+	}
+      return;
+    }
+
+  /* Uninstall old rib from forwarding table. */
+  if (fib)
+    {
+      redistribute_delete (&rn->p, fib);
+      if (! RIB_SYSTEM_ROUTE (fib))
+	rib_uninstall_kernel (rn, fib);
+      UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
+
+      /* Set real nexthop. */
+      nexthop_active_update (rn, fib, 1);
+    }
+
+  /* Install new rib into forwarding table. */
+  if (select)
+    {
+      /* Set real nexthop. */
+      nexthop_active_update (rn, select, 1);
+
+      if (! RIB_SYSTEM_ROUTE (select))
+	rib_install_kernel (rn, select);
+      SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
+      redistribute_add (&rn->p, select);
+    }
+}
+
+/* Add RIB to head of the route node. */
+void
+rib_addnode (struct route_node *rn, struct rib *rib)
+{
+  struct rib *head;
+
+  head = rn->info;
+  if (head)
+    head->prev = rib;
+  rib->next = head;
+  rn->info = rib;
+}
+
+void
+rib_delnode (struct route_node *rn, struct rib *rib)
+{
+  if (rib->next)
+    rib->next->prev = rib->prev;
+  if (rib->prev)
+    rib->prev->next = rib->next;
+  else
+    rn->info = rib->next;
+}
+
+int
+rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, 
+	      struct in_addr *gate, unsigned int ifindex, int table,
+	      u_int32_t metric, u_char distance)
+{
+  struct rib *rib;
+  struct rib *same = NULL;
+  struct route_node *rn;
+  struct nexthop *nexthop;
+
+  /* Make it sure prefixlen is applied to the prefix. */
+  apply_mask_ipv4 (p);
+
+  /* Set default distance by route type. */
+  if (distance == 0)
+    {
+      distance = route_info[type].distance;
+
+      /* iBGP distance is 200. */
+      if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
+	distance = 200;
+    }
+
+  /* Lookup route node.*/
+  rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
+
+  /* If same type of route are installed, treat it as a implicit
+     withdraw. */
+  for (rib = rn->info; rib; rib = rib->next)
+    {
+      if (rib->type == ZEBRA_ROUTE_CONNECT)
+	{
+	  nexthop = rib->nexthop;
+
+	  /* Duplicate connected route comes in. */
+	  if (rib->type == type
+	      && (! table || rib->table == table)
+	      && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
+	      && nexthop->ifindex == ifindex)
+	    {
+	      rib->refcnt++;
+	      return 0 ;
+	    }
+	}
+      else if (rib->type == type
+	       && (! table || rib->table == table))
+	{
+	  same = rib;
+	  rib_delnode (rn, same);
+	  route_unlock_node (rn);
+	  break;
+	}
+    }
+
+  /* Allocate new rib structure. */
+  rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
+  memset (rib, 0, sizeof (struct rib));
+  rib->type = type;
+  rib->distance = distance;
+  rib->flags = flags;
+  rib->metric = metric;
+  rib->table = table;
+  rib->nexthop_num = 0;
+  rib->uptime = time (NULL);
+
+  /* Nexthop settings. */
+  if (gate)
+    {
+      if (ifindex)
+	nexthop_ipv4_ifindex_add (rib, gate, ifindex);
+      else
+	nexthop_ipv4_add (rib, gate);
+    }
+  else
+    nexthop_ifindex_add (rib, ifindex);
+
+  /* If this route is kernel route, set FIB flag to the route. */
+  if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
+    for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+
+  /* Link new rib to node.*/
+  rib_addnode (rn, rib);
+
+  /* Process this route node. */
+  rib_process (rn, same);
+
+  /* Free implicit route.*/
+  if (same)
+    newrib_free (same);
+
+  return 0;
+}
+
+int
+rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
+{
+  struct route_node *rn;
+  struct rib *same;
+  struct nexthop *nexthop;
+
+  /* Make it sure prefixlen is applied to the prefix. */
+  apply_mask_ipv4 (p);
+
+  /* Set default distance by route type. */
+  if (rib->distance == 0)
+    {
+      rib->distance = route_info[rib->type].distance;
+
+      /* iBGP distance is 200. */
+      if (rib->type == ZEBRA_ROUTE_BGP 
+	  && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
+	rib->distance = 200;
+    }
+
+  /* Lookup route node.*/
+  rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
+
+  /* If same type of route are installed, treat it as a implicit
+     withdraw. */
+  for (same = rn->info; same; same = same->next)
+    {
+      if (same->type == rib->type && same->table == rib->table
+	  && same->type != ZEBRA_ROUTE_CONNECT)
+	{
+	  rib_delnode (rn, same);
+	  route_unlock_node (rn);
+	  break;
+	}
+    }
+
+  /* If this route is kernel route, set FIB flag to the route. */
+  if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
+    for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+
+  /* Link new rib to node.*/
+  rib_addnode (rn, rib);
+
+  /* Process this route node. */
+  rib_process (rn, same);
+
+  /* Free implicit route.*/
+  if (same)
+    newrib_free (same);
+
+  return 0;
+}
+
+int
+rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
+		 struct in_addr *gate, unsigned int ifindex, int table)
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct rib *fib = NULL;
+  struct rib *same = NULL;
+  struct nexthop *nexthop;
+  char buf1[BUFSIZ];
+  char buf2[BUFSIZ];
+
+  /* Apply mask. */
+  apply_mask_ipv4 (p);
+
+  /* Lookup route node. */
+  rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
+  if (! rn)
+    {
+      if (IS_ZEBRA_DEBUG_KERNEL)
+	{
+	  if (gate)
+	    zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
+		       inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+		       p->prefixlen,
+		       inet_ntop (AF_INET, gate, buf2, BUFSIZ),
+		       ifindex);
+	  else
+	    zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
+		       inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+		       p->prefixlen,
+		       ifindex);
+	}
+      return ZEBRA_ERR_RTNOEXIST;
+    }
+
+  /* Lookup same type route. */
+  for (rib = rn->info; rib; rib = rib->next)
+    {
+      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+	fib = rib;
+
+      if (rib->type == ZEBRA_ROUTE_CONNECT)
+	{
+	  nexthop = rib->nexthop;
+
+	  if (rib->type == type
+	      && (! table || rib->table == table)
+	      && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
+	      && nexthop->ifindex == ifindex)
+	    {
+	      if (rib->refcnt)
+		{
+		  rib->refcnt--;
+		  route_unlock_node (rn);
+		  route_unlock_node (rn);
+		  return 0;
+		}
+	      same = rib;
+	      break;
+	    }
+	}
+      else
+	{
+	  if (rib->type == type
+	      && (!table || rib->table == table))
+	    {
+	      same = rib;
+	      break;
+	    }
+	}
+    }
+
+  /* If same type of route can't be found and this message is from
+     kernel. */
+  if (! same)
+    {
+      if (fib && type == ZEBRA_ROUTE_KERNEL)
+	{
+	  /* Unset flags. */
+	  for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
+	    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+
+	  UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
+	}
+      else
+	{
+	  if (IS_ZEBRA_DEBUG_KERNEL)
+	    {
+	      if (gate)
+		zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
+			   inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+			   p->prefixlen,
+			   inet_ntop (AF_INET, gate, buf2, BUFSIZ),
+			   ifindex,
+			   type);
+	      else
+		zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
+			   inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
+			   p->prefixlen,
+			   ifindex,
+			   type);
+	    }
+	  route_unlock_node (rn);
+	  return ZEBRA_ERR_RTNOEXIST;
+	}
+    }
+
+  if (same)
+    rib_delnode (rn, same);
+
+  /* Process changes. */
+  rib_process (rn, same);
+
+  if (same)
+    {
+      newrib_free (same);
+      route_unlock_node (rn);
+    }
+
+  route_unlock_node (rn);
+
+  return 0;
+}
+
+/* Delete all added route and close rib. */
+void
+rib_close_ipv4 ()
+{
+  struct route_node *rn;
+  struct rib *rib;
+
+  for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      if (! RIB_SYSTEM_ROUTE (rib)
+	  && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+	rib_uninstall_kernel (rn, rib);
+}
+
+/* Install static route into rib. */
+void
+static_ipv4_install (struct prefix_ipv4 *p, struct static_ipv4 *si)
+{
+  struct rib *rib;
+  struct route_node *rn;
+
+  /* Lookup existing route */
+  rn = route_node_get (rib_table_ipv4, (struct prefix *) p);
+  for (rib = rn->info; rib; rib = rib->next)
+    if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
+      break;
+
+  if (rib)
+    {
+      /* Same distance static route is there.  Update it with new
+         nexthop. */
+      rib_uninstall (rn, rib);
+      route_unlock_node (rn);
+
+      switch (si->type)
+	{
+	case STATIC_IPV4_GATEWAY:
+	  nexthop_ipv4_add (rib, &si->gate.ipv4);
+	  break;
+	case STATIC_IPV4_IFNAME:
+	  nexthop_ifname_add (rib, si->gate.ifname);
+	  break;
+	}
+      rib_process (rn, NULL);
+    }
+  else
+    {
+      /* This is new static route. */
+      rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
+      memset (rib, 0, sizeof (struct rib));
+
+      rib->type = ZEBRA_ROUTE_STATIC;
+      rib->distance = si->distance;
+      rib->metric = 0;
+      rib->nexthop_num = 0;
+
+      switch (si->type)
+	{
+	case STATIC_IPV4_GATEWAY:
+	  nexthop_ipv4_add (rib, &si->gate.ipv4);
+	  break;
+	case STATIC_IPV4_IFNAME:
+	  nexthop_ifname_add (rib, si->gate.ifname);
+	  break;
+	}
+
+      /* Link this rib to the tree. */
+      rib_addnode (rn, rib);
+
+      /* Process this prefix. */
+      rib_process (rn, NULL);
+    }
+}
+
+int
+static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
+{
+  if (nexthop->type == NEXTHOP_TYPE_IPV4
+      && si->type == STATIC_IPV4_GATEWAY
+      && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
+    return 1;
+  if (nexthop->type == NEXTHOP_TYPE_IFNAME
+      && si->type == STATIC_IPV4_IFNAME
+      && strcmp (nexthop->ifname, si->gate.ifname) == 0)
+    return 1;
+  return 0;;
+}
+
+/* Uninstall static route from RIB. */
+void
+static_ipv4_uninstall (struct prefix_ipv4 *p, struct static_ipv4 *si)
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct nexthop *nexthop;
+
+  /* Lookup existing route with type and distance. */
+  rn = route_node_lookup (rib_table_ipv4, (struct prefix *) p);
+  if (! rn)
+    return;
+
+  for (rib = rn->info; rib; rib = rib->next)
+    if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
+      break;
+  if (! rib)
+    {
+      route_unlock_node (rn);
+      return;
+    }
+
+  /* Lookup nexthop. */
+  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+    if (static_ipv4_nexthop_same (nexthop, si))
+      break;
+
+  /* Can't find nexthop. */
+  if (! nexthop)
+    {
+      route_unlock_node (rn);
+      return;
+    }
+  
+  /* Check nexthop. */
+  if (rib->nexthop_num == 1)
+    {
+      rib_delnode (rn, rib);
+      rib_process (rn, rib);
+      newrib_free (rib);
+      route_unlock_node (rn);
+    }
+  else
+    {
+      rib_uninstall (rn, rib);
+      nexthop_delete (rib, nexthop);
+      nexthop_free (nexthop);
+      rib_process (rn, rib);
+    }
+
+  /* Unlock node. */
+  route_unlock_node (rn);
+}
+
+/* Add static route into static route configuration. */
+int
+static_ipv4_add (struct prefix_ipv4 *p, struct in_addr *gate, char *ifname,
+		 u_char distance, int table)
+{
+  u_char type = 0;
+  struct route_node *rn;
+  struct static_ipv4 *si;
+  struct static_ipv4 *pp;
+  struct static_ipv4 *cp;
+  
+  /* Lookup static route prefix. */
+  rn = route_node_get (static_table_ipv4, (struct prefix *) p);
+
+  /* Make flags. */
+  if (gate)
+    type = STATIC_IPV4_GATEWAY;
+  if (ifname)
+    type = STATIC_IPV4_IFNAME;
+
+  /* Do nothing if there is a same static route.  */
+  for (si = rn->info; si; si = si->next)
+    {
+      if (distance == si->distance 
+	  && type == si->type
+	  && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
+	  && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
+	{
+	  route_unlock_node (rn);
+	  return 0;
+	}
+    }
+
+  /* Make new static route structure. */
+  si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
+  memset (si, 0, sizeof (struct static_ipv4));
+
+  si->type = type;
+  si->distance = distance;
+
+  if (gate)
+    si->gate.ipv4 = *gate;
+  if (ifname)
+    si->gate.ifname = XSTRDUP (0, ifname);
+
+  /* Add new static route information to the tree with sort by
+     distance value and gateway address. */
+  for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
+    {
+      if (si->distance < cp->distance)
+	break;
+      if (si->distance > cp->distance)
+	continue;
+      if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
+	{
+	  if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
+	    break;
+	  if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
+	    continue;
+	}
+    }
+
+  /* Make linked list. */
+  if (pp)
+    pp->next = si;
+  else
+    rn->info = si;
+  if (cp)
+    cp->prev = si;
+  si->prev = pp;
+  si->next = cp;
+
+  /* Install into rib. */
+  static_ipv4_install (p, si);
+
+  return 1;
+}
+
+/* Delete static route from static route configuration. */
+int
+static_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *gate, char *ifname,
+		    u_char distance, int table)
+{
+  u_char type = 0;
+  struct route_node *rn;
+  struct static_ipv4 *si;
+
+  /* Lookup static route prefix. */
+  rn = route_node_lookup (static_table_ipv4, (struct prefix *) p);
+  if (! rn)
+    return 0;
+
+  /* Make flags. */
+  if (gate)
+    type = STATIC_IPV4_GATEWAY;
+  if (ifname)
+    type = STATIC_IPV4_IFNAME;
+
+  /* Find same static route is the tree */
+  for (si = rn->info; si; si = si->next)
+    if (distance == si->distance 
+	&& type == si->type
+	&& (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
+	&& (! ifname || strcmp (ifname, si->gate.ifname) == 0))
+      break;
+
+  /* Can't find static route. */
+  if (! si)
+    {
+      route_unlock_node (rn);
+      return 0;
+    }
+
+  /* Install into rib. */
+  static_ipv4_uninstall (p, si);
+
+  /* Unlink static route from linked list. */
+  if (si->prev)
+    si->prev->next = si->next;
+  else
+    rn->info = si->next;
+  if (si->next)
+    si->next->prev = si->prev;
+  
+  /* Free static route configuration. */
+  XFREE (MTYPE_STATIC_IPV4, si);
+
+  return 1;
+}
+
+/* Write IPv4 static route configuration. */
+int
+static_ipv4_write (struct vty *vty)
+{
+  struct route_node *rn;
+  struct static_ipv4 *si;  
+  int write;
+
+  write = 0;
+
+  for (rn = route_top (static_table_ipv4); rn; rn = route_next (rn))
+    for (si = rn->info; si; si = si->next)
+      {
+	vty_out (vty, "ip route %s/%d", inet_ntoa (rn->p.u.prefix4),
+		 rn->p.prefixlen);
+
+	switch (si->type)
+	  {
+	  case STATIC_IPV4_GATEWAY:
+	    vty_out (vty, " %s", inet_ntoa (si->gate.ipv4));
+	    break;
+	  case STATIC_IPV4_IFNAME:
+	    vty_out (vty, " %s", si->gate.ifname);
+	    break;
+	  }
+
+	if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
+	  vty_out (vty, " %d", si->distance);
+	vty_out (vty, "%s", VTY_NEWLINE);
+
+	write = 1;
+      }
+  return write;
+}
+
+/* General fucntion for static route. */
+int
+static_ipv4_func (struct vty *vty, int add_cmd,
+		  char *dest_str, char *mask_str, char *gate_str,
+		  char *distance_str)
+{
+  int ret;
+  u_char distance;
+  struct prefix_ipv4 p;
+  struct in_addr gate;
+  struct in_addr mask;
+  char *ifname;
+  int table = rtm_table_default;
+  
+  ret = str2prefix_ipv4 (dest_str, &p);
+  if (ret <= 0)
+    {
+      vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Cisco like mask notation. */
+  if (mask_str)
+    {
+      ret = inet_aton (mask_str, &mask);
+      if (ret == 0)
+	{
+	  vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+      p.prefixlen = ip_masklen (mask);
+    }
+
+  /* Apply mask for given prefix. */
+  apply_mask_ipv4 (&p);
+
+  /* Administrative distance. */
+  if (distance_str)
+    distance = atoi (distance_str);
+  else
+    distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
+
+  /* When gateway is A.B.C.D format, gate is treated as nexthop
+     address other case gate is treated as interface name. */
+  ret = inet_aton (gate_str, &gate);
+  if (ret)
+    ifname = NULL;
+  else
+    ifname = gate_str;
+
+  if (add_cmd)
+    static_ipv4_add (&p, ifname ? NULL : &gate, ifname, distance, table);
+  else
+    static_ipv4_delete (&p, ifname ? NULL : &gate, ifname, distance, table);
+
+  return CMD_SUCCESS;
+}
+
+/* Static route configuration. */
+DEFUN (ip_route, 
+       ip_route_cmd,
+       "ip route A.B.C.D/M (A.B.C.D|INTERFACE)",
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix (e.g. 10.0.0.0/8)\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n")
+{
+  return static_ipv4_func (vty, 1, argv[0], NULL, argv[1], NULL);
+}
+
+DEFUN (ip_route_mask,
+       ip_route_mask_cmd,
+       "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE)",
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix\n"
+       "IP destination prefix mask\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n")
+{
+  return static_ipv4_func (vty, 1, argv[0], argv[1], argv[2], NULL);
+}
+
+DEFUN (ip_route_pref,
+       ip_route_pref_cmd,
+       "ip route A.B.C.D/M (A.B.C.D|INTERFACE) <1-255>",
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix (e.g. 10.0.0.0/8)\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n"
+       "Distance value for this route\n")
+{
+  return static_ipv4_func (vty, 1, argv[0], NULL, argv[1], argv[2]);
+}
+
+DEFUN (ip_route_mask_pref,
+       ip_route_mask_pref_cmd,
+       "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) <1-255>",
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix\n"
+       "IP destination prefix mask\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n"
+       "Distance value for this route\n")
+{
+  return static_ipv4_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
+}
+
+DEFUN (no_ip_route, 
+       no_ip_route_cmd,
+       "no ip route A.B.C.D/M (A.B.C.D|INTERFACE)",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix (e.g. 10.0.0.0/8)\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n")
+{
+  return static_ipv4_func (vty, 0, argv[0], NULL, argv[1], NULL);
+}
+
+DEFUN (no_ip_route_mask,
+       no_ip_route_mask_cmd,
+       "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE)",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix\n"
+       "IP destination prefix mask\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n")
+{
+  return static_ipv4_func (vty, 0, argv[0], argv[1], argv[2], NULL);
+}
+
+DEFUN (no_ip_route_pref,
+       no_ip_route_pref_cmd,
+       "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) <1-255>",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix (e.g. 10.0.0.0/8)\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n"
+       "Distance value for this route\n")
+{
+  return static_ipv4_func (vty, 0, argv[0], NULL, argv[1], argv[2]);
+}
+
+DEFUN (no_ip_route_mask_pref,
+       no_ip_route_mask_pref_cmd,
+       "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) <1-255>",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix\n"
+       "IP destination prefix mask\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n"
+       "Distance value for this route\n")
+{
+  return static_ipv4_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
+}
+
+/* New RIB.  Detailed information for IPv4 route. */
+void
+vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
+{
+  struct rib *rib;
+  struct nexthop *nexthop;
+
+  for (rib = rn->info; rib; rib = rib->next)
+    {
+      vty_out (vty, "Routing entry for %s/%d%s", 
+	       inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
+	       VTY_NEWLINE);
+      vty_out (vty, "  Known via \"%s\"", route_info[rib->type].str);
+      vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
+      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+	vty_out (vty, ", best");
+      if (rib->refcnt)
+	vty_out (vty, ", refcnt %ld", rib->refcnt);
+      vty_out (vty, "%s", VTY_NEWLINE);
+
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+      if (rib->type == ZEBRA_ROUTE_RIP
+	  || rib->type == ZEBRA_ROUTE_OSPF
+	  || rib->type == ZEBRA_ROUTE_ISIS
+	  || rib->type == ZEBRA_ROUTE_BGP)
+	{
+	  time_t uptime;
+	  struct tm *tm;
+
+	  uptime = time (NULL);
+	  uptime -= rib->uptime;
+	  tm = gmtime (&uptime);
+
+	  vty_out (vty, "  Last update ");
+
+	  if (uptime < ONE_DAY_SECOND)
+	    vty_out (vty,  "%02d:%02d:%02d", 
+		     tm->tm_hour, tm->tm_min, tm->tm_sec);
+	  else if (uptime < ONE_WEEK_SECOND)
+	    vty_out (vty, "%dd%02dh%02dm", 
+		     tm->tm_yday, tm->tm_hour, tm->tm_min);
+	  else
+	    vty_out (vty, "%02dw%dd%02dh", 
+		     tm->tm_yday/7,
+		     tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+	  vty_out (vty, " ago%s", VTY_NEWLINE);
+	}
+
+      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+	{
+	  vty_out (vty, "  %c",
+		   CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
+
+	  switch (nexthop->type)
+	    {
+	    case NEXTHOP_TYPE_IPV4:
+	    case NEXTHOP_TYPE_IPV4_IFINDEX:
+	      vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4));
+	      if (nexthop->ifindex)
+		vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
+	      break;
+	    case NEXTHOP_TYPE_IFINDEX:
+	      vty_out (vty, " directly connected, %s",
+		       ifindex2ifname (nexthop->ifindex));
+	      break;
+	    case NEXTHOP_TYPE_IFNAME:
+	      vty_out (vty, " directly connected, %s",
+		       nexthop->ifname);
+	      break;
+	    default:
+	      break;
+	    }
+	  if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+	    vty_out (vty, " inactive");
+
+	  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+	    {
+	      vty_out (vty, " (recursive");
+		
+	      switch (nexthop->rtype)
+		{
+		case NEXTHOP_TYPE_IPV4:
+		case NEXTHOP_TYPE_IPV4_IFINDEX:
+		  vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
+		  break;
+		case NEXTHOP_TYPE_IFINDEX:
+		case NEXTHOP_TYPE_IFNAME:
+		  vty_out (vty, " is directly connected, %s)",
+			   ifindex2ifname (nexthop->rifindex));
+		  break;
+		default:
+		  break;
+		}
+	    }
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+}
+
+void
+vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
+{
+  struct nexthop *nexthop;
+  int len = 0;
+  char buf[BUFSIZ];
+
+  /* Nexthop information. */
+  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+    {
+      if (nexthop == rib->nexthop)
+	{
+	  /* Prefix information. */
+	  len = vty_out (vty, "%c%c%c %s/%d",
+			 route_info[rib->type].c,
+			 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
+			 ? '>' : ' ',
+			 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+			 ? '*' : ' ',
+			 inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ),
+			 rn->p.prefixlen);
+		
+	  /* Distance and metric display. */
+	  if (rib->type != ZEBRA_ROUTE_CONNECT 
+	      && rib->type != ZEBRA_ROUTE_KERNEL)
+	    len += vty_out (vty, " [%d/%d]", rib->distance,
+			    rib->metric);
+	}
+      else
+	vty_out (vty, "  %c%*c",
+		 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+		 ? '*' : ' ',
+		 len - 3, ' ');
+
+      switch (nexthop->type)
+	{
+	case NEXTHOP_TYPE_IPV4:
+	case NEXTHOP_TYPE_IPV4_IFINDEX:
+	  vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4));
+	  if (nexthop->ifindex)
+	    vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
+	  break;
+	case NEXTHOP_TYPE_IFINDEX:
+	  vty_out (vty, " is directly connected, %s",
+		   ifindex2ifname (nexthop->ifindex));
+	  break;
+	case NEXTHOP_TYPE_IFNAME:
+	  vty_out (vty, " is directly connected, %s",
+		   nexthop->ifname);
+	  break;
+	default:
+	  break;
+	}
+      if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+	vty_out (vty, " inactive");
+
+      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+	{
+	  vty_out (vty, " (recursive");
+		
+	  switch (nexthop->rtype)
+	    {
+	    case NEXTHOP_TYPE_IPV4:
+	    case NEXTHOP_TYPE_IPV4_IFINDEX:
+	      vty_out (vty, " via %s)", inet_ntoa (nexthop->rgate.ipv4));
+	      break;
+	    case NEXTHOP_TYPE_IFINDEX:
+	    case NEXTHOP_TYPE_IFNAME:
+	      vty_out (vty, " is directly connected, %s)",
+		       ifindex2ifname (nexthop->rifindex));
+	      break;
+	    default:
+	      break;
+	    }
+	}
+
+      if (rib->type == ZEBRA_ROUTE_RIP
+	  || rib->type == ZEBRA_ROUTE_OSPF
+	  || rib->type == ZEBRA_ROUTE_ISIS
+	  || rib->type == ZEBRA_ROUTE_BGP)
+	{
+	  time_t uptime;
+	  struct tm *tm;
+
+	  uptime = time (NULL);
+	  uptime -= rib->uptime;
+	  tm = gmtime (&uptime);
+
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+
+	  if (uptime < ONE_DAY_SECOND)
+	    vty_out (vty,  ", %02d:%02d:%02d", 
+		     tm->tm_hour, tm->tm_min, tm->tm_sec);
+	  else if (uptime < ONE_WEEK_SECOND)
+	    vty_out (vty, ", %dd%02dh%02dm", 
+		     tm->tm_yday, tm->tm_hour, tm->tm_min);
+	  else
+	    vty_out (vty, ", %02dw%dd%02dh", 
+		     tm->tm_yday/7,
+		     tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+}
+
+#define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,%s I - IS-IS, %s       B - BGP, > - selected route, * - FIB route%s%s"
+
+DEFUN (show_ip_route,
+       show_ip_route_cmd,
+       "show ip route",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n")
+{
+  struct route_node *rn;
+  struct rib *rib;
+  int first = 1;
+
+  /* Show all IPv4 routes. */
+  for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      {
+	if (first)
+	  {
+	    vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+	    first = 0;
+	  }
+	vty_show_ip_route (vty, rn, rib);
+      }
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_route_prefix_longer,
+       show_ip_route_prefix_longer_cmd,
+       "show ip route A.B.C.D/M longer-prefixes",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Show route matching the specified Network/Mask pair only\n")
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct prefix p;
+  int ret;
+  int first = 1;
+
+  ret = str2prefix (argv[0], &p);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  /* Show matched type IPv4 routes. */
+  for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      if (prefix_match (&p, &rn->p))
+	{
+	  if (first)
+	    {
+	      vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+	      first = 0;
+	    }
+	  vty_show_ip_route (vty, rn, rib);
+	}
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_route_supernets,
+       show_ip_route_supernets_cmd,
+       "show ip route supernets-only",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n"
+       "Show supernet entries only\n")
+{
+  struct route_node *rn;
+  struct rib *rib;
+  u_int32_t addr; 
+  int first = 1;
+
+
+  /* Show matched type IPv4 routes. */
+  for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      {
+	addr = ntohl (rn->p.u.prefix4.s_addr);
+
+	if ((IN_CLASSC (addr) && rn->p.prefixlen < 24)
+	   || (IN_CLASSB (addr) && rn->p.prefixlen < 16)
+	   || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) 
+	  {
+	    if (first)
+	      {
+		vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, 
+                         VTY_NEWLINE, VTY_NEWLINE);
+		first = 0;
+	      }
+	    vty_show_ip_route (vty, rn, rib);
+	  }
+      }
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (show_ip_route_protocol,
+       show_ip_route_protocol_cmd,
+       "show ip route (bgp|connected|kernel|ospf|isis|rip|static)",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n"
+       "Border Gateway Protocol (BGP)\n"
+       "Connected\n"
+       "Kernel\n"
+       "Open Shortest Path First (OSPF)\n"
+       "ISO IS-IS (ISIS)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n")
+{
+  int type;
+  struct route_node *rn;
+  struct rib *rib;
+  int first = 1;
+
+  if (strncmp (argv[0], "b", 1) == 0)
+    type = ZEBRA_ROUTE_BGP;
+  else if (strncmp (argv[0], "c", 1) == 0)
+    type = ZEBRA_ROUTE_CONNECT;
+  else if (strncmp (argv[0], "k", 1) ==0)
+    type = ZEBRA_ROUTE_KERNEL;
+  else if (strncmp (argv[0], "o", 1) == 0)
+    type = ZEBRA_ROUTE_OSPF;
+  else if (strncmp (argv[0], "i", 1) == 0)
+    type = ZEBRA_ROUTE_ISIS;
+  else if (strncmp (argv[0], "r", 1) == 0)
+    type = ZEBRA_ROUTE_RIP;
+  else if (strncmp (argv[0], "s", 1) == 0)
+    type = ZEBRA_ROUTE_STATIC;
+  else 
+    {
+      vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  /* Show matched type IPv4 routes. */
+  for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      if (rib->type == type)
+	{
+	  if (first)
+	    {
+	      vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, 
+                       VTY_NEWLINE, VTY_NEWLINE);
+	      first = 0;
+	    }
+	  vty_show_ip_route (vty, rn, rib);
+	}
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_route_addr,
+       show_ip_route_addr_cmd,
+       "show ip route A.B.C.D",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n"
+       "Network in the IP routing table to display\n")
+{
+  int ret;
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+
+  ret = str2prefix_ipv4 (argv[0], &p);
+  if (ret <= 0)
+    {
+      vty_out (vty, "Malformed IPv4 address%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
+  if (! rn)
+    {
+      vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty_show_ip_route_detail (vty, rn);
+
+  route_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_route_prefix,
+       show_ip_route_prefix_cmd,
+       "show ip route A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  int ret;
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+
+  ret = str2prefix_ipv4 (argv[0], &p);
+  if (ret <= 0)
+    {
+      vty_out (vty, "Malformed IPv4 address%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  rn = route_node_match (rib_table_ipv4, (struct prefix *) &p);
+  if (! rn || rn->p.prefixlen != p.prefixlen)
+    {
+      vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty_show_ip_route_detail (vty, rn);
+
+  route_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+#ifdef HAVE_IPV6
+int
+rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
+		struct in6_addr *gate, unsigned int ifindex, int table)
+{
+  if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix))
+    return 1;
+  if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
+      && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
+    {
+      kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
+      return 1;
+    }
+  return 0;
+}
+
+int
+rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
+	      struct in6_addr *gate, unsigned int ifindex, int table)
+{
+  struct rib *rib;
+  struct rib *same = NULL;
+  struct route_node *rn;
+  struct nexthop *nexthop;
+
+  int distance;
+  u_int32_t metric = 0;
+
+  /* Make sure mask is applied. */
+  apply_mask_ipv6 (p);
+
+  /* Set default distance by route type. */
+  distance = route_info[type].distance;
+  
+  if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
+    distance = 200;
+
+  /* Make new rib. */
+  if (!table)
+    table = RT_TABLE_MAIN;
+
+  /* Filter bogus route. */
+  if (rib_bogus_ipv6 (type, p, gate, ifindex, table))
+    return 0;
+
+  /* Lookup route node.*/
+  rn = route_node_get (rib_table_ipv6, (struct prefix *) p);
+
+  /* If same type of route are installed, treat it as a implicit
+     withdraw. */
+  for (rib = rn->info; rib; rib = rib->next)
+    {
+      if (rib->type == ZEBRA_ROUTE_CONNECT)
+	{
+	  nexthop = rib->nexthop;
+
+	  if (rib->type == type
+	      && (! table || rib->table == table)
+	      && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
+	      && nexthop->ifindex == ifindex)
+	  {
+	    rib->refcnt++;
+	    return 0;
+	  }
+	}
+      else if (rib->type == type
+	       && (! table || (rib->table == table)))
+	{
+	  same = rib;
+	  rib_delnode (rn, same);
+	  route_unlock_node (rn);
+	  break;
+	}
+    }
+
+  /* Allocate new rib structure. */
+  rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
+  memset (rib, 0, sizeof (struct rib));
+  rib->type = type;
+  rib->distance = distance;
+  rib->flags = flags;
+  rib->metric = metric;
+  rib->table = table;
+  rib->nexthop_num = 0;
+  rib->uptime = time (NULL);
+
+  /* Nexthop settings. */
+  if (gate)
+    {
+      if (ifindex)
+	nexthop_ipv6_ifindex_add (rib, gate, ifindex);
+      else
+	nexthop_ipv6_add (rib, gate);
+    }
+  else
+    nexthop_ifindex_add (rib, ifindex);
+
+  /* If this route is kernel route, set FIB flag to the route. */
+  if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
+    for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+
+  /* Link new rib to node.*/
+  rib_addnode (rn, rib);
+
+  /* Process this route node. */
+  rib_process (rn, same);
+
+  /* Free implicit route.*/
+  if (same)
+    newrib_free (same);
+
+  return 0;
+}
+
+int
+rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
+		 struct in6_addr *gate, unsigned int ifindex, int table)
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct rib *fib = NULL;
+  struct rib *same = NULL;
+  struct nexthop *nexthop;
+  char buf1[BUFSIZ];
+  char buf2[BUFSIZ];
+
+  /* Apply mask. */
+  apply_mask_ipv6 (p);
+
+  /* Lookup route node. */
+  rn = route_node_lookup (rib_table_ipv6, (struct prefix *) p);
+  if (! rn)
+    {
+      if (IS_ZEBRA_DEBUG_KERNEL)
+	{
+	  if (gate)
+	    zlog_info ("route %s/%d via %s ifindex %d doesn't exist in rib",
+		       inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
+		       p->prefixlen,
+		       inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
+		       ifindex);
+	  else
+	    zlog_info ("route %s/%d ifindex %d doesn't exist in rib",
+		       inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
+		       p->prefixlen,
+		       ifindex);
+	}
+      return ZEBRA_ERR_RTNOEXIST;
+    }
+
+  /* Lookup same type route. */
+  for (rib = rn->info; rib; rib = rib->next)
+    {
+      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+	fib = rib;
+
+      if (rib->type == ZEBRA_ROUTE_CONNECT)
+	{
+	  nexthop = rib->nexthop;
+
+	  if (rib->type == type
+	      && (! table || rib->table == table)
+	      && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
+	      && nexthop->ifindex == ifindex)
+	    {
+	      if (rib->refcnt)
+		{
+		  rib->refcnt--;
+		  route_unlock_node (rn);
+		  route_unlock_node (rn);
+		  return 0;
+		}
+	      same = rib;
+	      break;
+	    }
+	}
+      else
+	{
+	  if (rib->type == type
+	      && (! table || rib->table == table))
+	    {
+	      same = rib;
+	      break;
+	    }
+	}
+    }
+
+  /* If same type of route can't be found and this message is from
+     kernel. */
+  if (! same)
+    {
+      if (fib && type == ZEBRA_ROUTE_KERNEL)
+	{
+	  /* Unset flags. */
+	  for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
+	    UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+
+	  UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
+	}
+      else
+	{
+	  if (IS_ZEBRA_DEBUG_KERNEL)
+	    {
+	      if (gate)
+		zlog_info ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
+			   inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
+			   p->prefixlen,
+			   inet_ntop (AF_INET6, gate, buf2, BUFSIZ),
+			   ifindex,
+			   type);
+	      else
+		zlog_info ("route %s/%d ifindex %d type %d doesn't exist in rib",
+			   inet_ntop (AF_INET6, &p->prefix, buf1, BUFSIZ),
+			   p->prefixlen,
+			   ifindex,
+			   type);
+	    }
+	  route_unlock_node (rn);
+	  return ZEBRA_ERR_RTNOEXIST;
+	}
+    }
+
+  if (same)
+    rib_delnode (rn, same);
+
+  /* Process changes. */
+  rib_process (rn, same);
+
+  if (same)
+    {
+      newrib_free (same);
+      route_unlock_node (rn);
+    }
+
+  route_unlock_node (rn);
+
+  return 0;
+}
+
+/* Delete non system routes. */
+void
+rib_close_ipv6 ()
+{
+  struct route_node *rn;
+  struct rib *rib;
+
+  for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      if (! RIB_SYSTEM_ROUTE (rib)
+	  && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+	rib_uninstall_kernel (rn, rib);
+}
+
+/* Install static route into rib. */
+void
+static_ipv6_install (struct prefix_ipv6 *p, struct static_ipv6 *si)
+{
+  struct rib *rib;
+  struct route_node *rn;
+
+  /* Lookup existing route */
+  rn = route_node_get (rib_table_ipv6, (struct prefix *) p);
+  for (rib = rn->info; rib; rib = rib->next)
+    if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
+      break;
+
+  if (rib)
+    {
+      /* Same distance static route is there.  Update it with new
+         nexthop. */
+      rib_uninstall (rn, rib);
+      route_unlock_node (rn);
+
+      switch (si->type)
+	{
+	case STATIC_IPV6_GATEWAY:
+	  nexthop_ipv6_add (rib, &si->ipv6);
+	  break;
+	case STATIC_IPV6_IFNAME:
+	  nexthop_ifname_add (rib, si->ifname);
+	  break;
+	case STATIC_IPV6_GATEWAY_IFNAME:
+	  nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
+	  break;
+	}
+      rib_process (rn, NULL);
+    }
+  else
+    {
+      /* This is new static route. */
+      rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
+      memset (rib, 0, sizeof (struct rib));
+
+      rib->type = ZEBRA_ROUTE_STATIC;
+      rib->distance = si->distance;
+      rib->metric = 0;
+      rib->nexthop_num = 0;
+
+      switch (si->type)
+	{
+	case STATIC_IPV6_GATEWAY:
+	  nexthop_ipv6_add (rib, &si->ipv6);
+	  break;
+	case STATIC_IPV6_IFNAME:
+	  nexthop_ifname_add (rib, si->ifname);
+	  break;
+	case STATIC_IPV6_GATEWAY_IFNAME:
+	  nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
+	  break;
+	}
+
+      /* Link this rib to the tree. */
+      rib_addnode (rn, rib);
+
+      /* Process this prefix. */
+      rib_process (rn, NULL);
+    }
+}
+
+int
+static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
+{
+  if (nexthop->type == NEXTHOP_TYPE_IPV6
+      && si->type == STATIC_IPV6_GATEWAY
+      && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
+    return 1;
+  if (nexthop->type == NEXTHOP_TYPE_IFNAME
+      && si->type == STATIC_IPV6_IFNAME
+      && strcmp (nexthop->ifname, si->ifname) == 0)
+    return 1;
+  if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
+      && si->type == STATIC_IPV6_GATEWAY_IFNAME
+      && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
+      && strcmp (nexthop->ifname, si->ifname) == 0)
+    return 1;
+  return 0;;
+}
+
+void
+static_ipv6_uninstall (struct prefix_ipv6 *p, struct static_ipv6 *si)
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct nexthop *nexthop;
+
+  /* Lookup existing route with type and distance. */
+  rn = route_node_lookup (rib_table_ipv6, (struct prefix *) p);
+  if (! rn)
+    return;
+
+  for (rib = rn->info; rib; rib = rib->next)
+    if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
+      break;
+  if (! rib)
+    {
+      route_unlock_node (rn);
+      return;
+    }
+
+  /* Lookup nexthop. */
+  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+    if (static_ipv6_nexthop_same (nexthop, si))
+      break;
+
+  /* Can't find nexthop. */
+  if (! nexthop)
+    {
+      route_unlock_node (rn);
+      return;
+    }
+  
+  /* Check nexthop. */
+  if (rib->nexthop_num == 1)
+    {
+      rib_delnode (rn, rib);
+      rib_process (rn, rib);
+      newrib_free (rib);
+      route_unlock_node (rn);
+    }
+  else
+    {
+      rib_uninstall (rn, rib);
+      nexthop_delete (rib, nexthop);
+      nexthop_free (nexthop);
+      rib_process (rn, rib);
+    }
+
+  /* Unlock node. */
+  route_unlock_node (rn);
+}
+
+/* Add static route into static route configuration. */
+int
+static_ipv6_add (struct prefix_ipv6 *p, u_char type, struct in6_addr *gate,
+		 char *ifname, u_char distance, int table)
+{
+  struct route_node *rn;
+  struct static_ipv6 *si;
+  struct static_ipv6 *pp;
+  struct static_ipv6 *cp;
+  
+  /* Lookup static route prefix. */
+  rn = route_node_get (static_table_ipv6, (struct prefix *) p);
+
+  /* Do nothing if there is a same static route.  */
+  for (si = rn->info; si; si = si->next)
+    {
+      if (distance == si->distance 
+	  && type == si->type
+	  && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
+	  && (! ifname || strcmp (ifname, si->ifname) == 0))
+	{
+	  route_unlock_node (rn);
+	  return 0;
+	}
+    }
+
+  /* Make new static route structure. */
+  si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
+  memset (si, 0, sizeof (struct static_ipv6));
+
+  si->type = type;
+  si->distance = distance;
+
+  switch (type)
+    {
+    case STATIC_IPV6_GATEWAY:
+      si->ipv6 = *gate;
+      break;
+    case STATIC_IPV6_IFNAME:
+      si->ifname = XSTRDUP (0, ifname);
+      break;
+    case STATIC_IPV6_GATEWAY_IFNAME:
+      si->ipv6 = *gate;
+      si->ifname = XSTRDUP (0, ifname);
+      break;
+    }
+
+  /* Add new static route information to the tree with sort by
+     distance value and gateway address. */
+  for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
+    {
+      if (si->distance < cp->distance)
+	break;
+      if (si->distance > cp->distance)
+	continue;
+    }
+
+  /* Make linked list. */
+  if (pp)
+    pp->next = si;
+  else
+    rn->info = si;
+  if (cp)
+    cp->prev = si;
+  si->prev = pp;
+  si->next = cp;
+
+  /* Install into rib. */
+  static_ipv6_install (p, si);
+
+  return 1;
+}
+
+/* Delete static route from static route configuration. */
+int
+static_ipv6_delete (struct prefix_ipv6 *p, u_char type, struct in6_addr *gate,
+		    char *ifname, u_char distance, int table)
+{
+  struct route_node *rn;
+  struct static_ipv6 *si;
+
+  /* Lookup static route prefix. */
+  rn = route_node_lookup (static_table_ipv6, (struct prefix *) p);
+  if (! rn)
+    return 0;
+
+  /* Find same static route is the tree */
+  for (si = rn->info; si; si = si->next)
+    if (distance == si->distance 
+	&& type == si->type
+	&& (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
+	&& (! ifname || strcmp (ifname, si->ifname) == 0))
+      break;
+
+  /* Can't find static route. */
+  if (! si)
+    {
+      route_unlock_node (rn);
+      return 0;
+    }
+
+  /* Install into rib. */
+  static_ipv6_uninstall (p, si);
+
+  /* Unlink static route from linked list. */
+  if (si->prev)
+    si->prev->next = si->next;
+  else
+    rn->info = si->next;
+  if (si->next)
+    si->next->prev = si->prev;
+  
+  /* Free static route configuration. */
+  XFREE (MTYPE_STATIC_IPV6, si);
+
+  return 1;
+}
+
+/* General fucntion for IPv6 static route. */
+int
+static_ipv6_func (struct vty *vty, int add_cmd, char *dest_str,
+		  char *gate_str, char *ifname, char *distance_str)
+{
+  int ret;
+  u_char distance;
+  struct prefix_ipv6 p;
+  struct in6_addr *gate = NULL;
+  struct in6_addr gate_addr;
+  u_char type = 0;
+  int table = rtm_table_default;
+  
+  ret = str2prefix_ipv6 (dest_str, &p);
+  if (ret <= 0)
+    {
+      vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Apply mask for given prefix. */
+  apply_mask_ipv6 (&p);
+
+  /* Administrative distance. */
+  if (distance_str)
+    distance = atoi (distance_str);
+  else
+    distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
+
+  /* When gateway is valid IPv6 addrees, then gate is treated as
+     nexthop address other case gate is treated as interface name. */
+  ret = inet_pton (AF_INET6, gate_str, &gate_addr);
+
+  if (ifname)
+    {
+      /* When ifname is specified.  It must be come with gateway
+         address. */
+      if (ret != 1)
+	{
+	  vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+      type = STATIC_IPV6_GATEWAY_IFNAME;
+      gate = &gate_addr;
+    }
+  else
+    {
+      if (ret == 1)
+	{
+	  type = STATIC_IPV6_GATEWAY;
+	  gate = &gate_addr;
+	}
+      else
+	{
+	  type = STATIC_IPV6_IFNAME;
+	  ifname = gate_str;
+	}
+    }
+
+  if (add_cmd)
+    static_ipv6_add (&p, type, gate, ifname, distance, table);
+  else
+    static_ipv6_delete (&p, type, gate, ifname, distance, table);
+
+  return CMD_SUCCESS;
+}
+
+/* Write IPv6 static route configuration. */
+int
+static_ipv6_write (struct vty *vty)
+{
+  struct route_node *rn;
+  struct static_ipv6 *si;  
+  int write;
+  char buf[BUFSIZ];
+
+  write = 0;
+
+  for (rn = route_top (static_table_ipv6); rn; rn = route_next (rn))
+    for (si = rn->info; si; si = si->next)
+      {
+	vty_out (vty, "ipv6 route %s/%d",
+		 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
+		 rn->p.prefixlen);
+
+	switch (si->type)
+	  {
+	  case STATIC_IPV6_GATEWAY:
+	    vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ));
+	    break;
+	  case STATIC_IPV6_IFNAME:
+	    vty_out (vty, " %s", si->ifname);
+	    break;
+	  case STATIC_IPV6_GATEWAY_IFNAME:
+	    vty_out (vty, " %s %s",
+		     inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname);
+	    break;
+	  }
+
+	if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
+	  vty_out (vty, " %d", si->distance);
+	vty_out (vty, "%s", VTY_NEWLINE);
+
+	write = 1;
+      }
+  return write;
+}
+
+DEFUN (ipv6_route,
+       ipv6_route_cmd,
+       "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n")
+{
+  return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL);
+}
+
+DEFUN (ipv6_route_ifname,
+       ipv6_route_ifname_cmd,
+       "ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n")
+{
+  return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL);
+}
+
+DEFUN (ipv6_route_pref,
+       ipv6_route_pref_cmd,
+       "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n"
+       "Distance value for this prefix\n")
+{
+  return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2]);
+}
+
+DEFUN (ipv6_route_ifname_pref,
+       ipv6_route_ifname_pref_cmd,
+       "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n"
+       "Distance value for this prefix\n")
+{
+  return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3]);
+}
+
+DEFUN (no_ipv6_route,
+       no_ipv6_route_cmd,
+       "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n")
+{
+  return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL);
+}
+
+DEFUN (no_ipv6_route_ifname,
+       no_ipv6_route_ifname_cmd,
+       "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n")
+{
+  return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL);
+}
+
+DEFUN (no_ipv6_route_pref,
+       no_ipv6_route_pref_cmd,
+       "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n"
+       "Distance value for this prefix\n")
+{
+  return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2]);
+}
+
+DEFUN (no_ipv6_route_ifname_pref,
+       no_ipv6_route_ifname_pref_cmd,
+       "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+       "IPv6 gateway address\n"
+       "IPv6 gateway interface name\n"
+       "Distance value for this prefix\n")
+{
+  return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3]);
+}
+
+/* New RIB.  Detailed information for IPv4 route. */
+void
+vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
+{
+  struct rib *rib;
+  struct nexthop *nexthop;
+  char buf[BUFSIZ];
+
+  for (rib = rn->info; rib; rib = rib->next)
+    {
+      vty_out (vty, "Routing entry for %s/%d%s", 
+	       inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
+	       rn->p.prefixlen,
+	       VTY_NEWLINE);
+      vty_out (vty, "  Known via \"%s\"", route_info[rib->type].str);
+      vty_out (vty, ", distance %d, metric %d", rib->distance, rib->metric);
+      if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+	vty_out (vty, ", best");
+      if (rib->refcnt)
+	vty_out (vty, ", refcnt %ld", rib->refcnt);
+      vty_out (vty, "%s", VTY_NEWLINE);
+
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+      if (rib->type == ZEBRA_ROUTE_RIPNG
+	  || rib->type == ZEBRA_ROUTE_OSPF6
+	  || rib->type == ZEBRA_ROUTE_ISIS
+	  || rib->type == ZEBRA_ROUTE_BGP)
+	{
+	  time_t uptime;
+	  struct tm *tm;
+
+	  uptime = time (NULL);
+	  uptime -= rib->uptime;
+	  tm = gmtime (&uptime);
+
+	  vty_out (vty, "  Last update ");
+
+	  if (uptime < ONE_DAY_SECOND)
+	    vty_out (vty,  "%02d:%02d:%02d", 
+		     tm->tm_hour, tm->tm_min, tm->tm_sec);
+	  else if (uptime < ONE_WEEK_SECOND)
+	    vty_out (vty, "%dd%02dh%02dm", 
+		     tm->tm_yday, tm->tm_hour, tm->tm_min);
+	  else
+	    vty_out (vty, "%02dw%dd%02dh", 
+		     tm->tm_yday/7,
+		     tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+	  vty_out (vty, " ago%s", VTY_NEWLINE);
+	}
+
+      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+	{
+	  vty_out (vty, "  %c",
+		   CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
+
+	  switch (nexthop->type)
+	    {
+	    case NEXTHOP_TYPE_IPV6:
+	    case NEXTHOP_TYPE_IPV6_IFINDEX:
+	    case NEXTHOP_TYPE_IPV6_IFNAME:
+	      vty_out (vty, " %s",
+		       inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
+	      if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
+		vty_out (vty, ", %s", nexthop->ifname);
+	      else if (nexthop->ifindex)
+		vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex));
+	      break;
+	    case NEXTHOP_TYPE_IFINDEX:
+	      vty_out (vty, " directly connected, %s",
+		       ifindex2ifname (nexthop->ifindex));
+	      break;
+	    case NEXTHOP_TYPE_IFNAME:
+	      vty_out (vty, " directly connected, %s",
+		       nexthop->ifname);
+	      break;
+	    default:
+	      break;
+	    }
+	  if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+	    vty_out (vty, " inactive");
+
+	  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+	    {
+	      vty_out (vty, " (recursive");
+		
+	      switch (nexthop->rtype)
+		{
+		case NEXTHOP_TYPE_IPV6:
+		case NEXTHOP_TYPE_IPV6_IFINDEX:
+		case NEXTHOP_TYPE_IPV6_IFNAME:
+		  vty_out (vty, " via %s)",
+			   inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
+				      buf, BUFSIZ));
+		  if (nexthop->rifindex)
+		    vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
+		  break;
+		case NEXTHOP_TYPE_IFINDEX:
+		case NEXTHOP_TYPE_IFNAME:
+		  vty_out (vty, " is directly connected, %s)",
+			   ifindex2ifname (nexthop->rifindex));
+		  break;
+		default:
+		  break;
+		}
+	    }
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+}
+
+void
+vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
+		     struct rib *rib)
+{
+  struct nexthop *nexthop;
+  int len = 0;
+  char buf[BUFSIZ];
+
+  /* Nexthop information. */
+  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+    {
+      if (nexthop == rib->nexthop)
+	{
+	  /* Prefix information. */	  
+	  len = vty_out (vty, "%c%c%c %s/%d",
+			 route_info[rib->type].c,
+			 CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)
+			 ? '>' : ' ',
+			 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+			 ? '*' : ' ',
+			 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
+			 rn->p.prefixlen);
+
+	  /* Distance and metric display. */
+	  if (rib->type != ZEBRA_ROUTE_CONNECT 
+	      && rib->type != ZEBRA_ROUTE_KERNEL)
+	    len += vty_out (vty, " [%d/%d]", rib->distance,
+			    rib->metric);
+	}
+      else
+	vty_out (vty, "  %c%*c",
+		 CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+		 ? '*' : ' ',
+		 len - 3, ' ');
+
+      switch (nexthop->type)
+	{
+	case NEXTHOP_TYPE_IPV6:
+	case NEXTHOP_TYPE_IPV6_IFINDEX:
+	case NEXTHOP_TYPE_IPV6_IFNAME:
+	  vty_out (vty, " via %s",
+		   inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
+	  if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
+	    vty_out (vty, ", %s", nexthop->ifname);
+	  else if (nexthop->ifindex)
+	    vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex));
+	  break;
+	case NEXTHOP_TYPE_IFINDEX:
+	  vty_out (vty, " is directly connected, %s",
+		   ifindex2ifname (nexthop->ifindex));
+	  break;
+	case NEXTHOP_TYPE_IFNAME:
+	  vty_out (vty, " is directly connected, %s",
+		   nexthop->ifname);
+	  break;
+	default:
+	  break;
+	}
+      if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+	vty_out (vty, " inactive");
+
+      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+	{
+	  vty_out (vty, " (recursive");
+		
+	  switch (nexthop->rtype)
+	    {
+	    case NEXTHOP_TYPE_IPV6:
+	    case NEXTHOP_TYPE_IPV6_IFINDEX:
+	    case NEXTHOP_TYPE_IPV6_IFNAME:
+	      vty_out (vty, " via %s)",
+		       inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
+				  buf, BUFSIZ));
+	      if (nexthop->rifindex)
+		vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
+	      break;
+	    case NEXTHOP_TYPE_IFINDEX:
+	    case NEXTHOP_TYPE_IFNAME:
+	      vty_out (vty, " is directly connected, %s)",
+		       ifindex2ifname (nexthop->rifindex));
+	      break;
+	    default:
+	      break;
+	    }
+	}
+
+      if (rib->type == ZEBRA_ROUTE_RIPNG
+	  || rib->type == ZEBRA_ROUTE_OSPF6
+	  || rib->type == ZEBRA_ROUTE_ISIS
+	  || rib->type == ZEBRA_ROUTE_BGP)
+	{
+	  time_t uptime;
+	  struct tm *tm;
+
+	  uptime = time (NULL);
+	  uptime -= rib->uptime;
+	  tm = gmtime (&uptime);
+
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+
+	  if (uptime < ONE_DAY_SECOND)
+	    vty_out (vty,  ", %02d:%02d:%02d", 
+		     tm->tm_hour, tm->tm_min, tm->tm_sec);
+	  else if (uptime < ONE_WEEK_SECOND)
+	    vty_out (vty, ", %dd%02dh%02dm", 
+		     tm->tm_yday, tm->tm_hour, tm->tm_min);
+	  else
+	    vty_out (vty, ", %02dw%dd%02dh", 
+		     tm->tm_yday/7,
+		     tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+}
+
+#define SHOW_ROUTE_V6_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS,%s       B - BGP, * - FIB route.%s%s"
+
+DEFUN (show_ipv6_route,
+       show_ipv6_route_cmd,
+       "show ipv6 route",
+       SHOW_STR
+       IP_STR
+       "IPv6 routing table\n")
+{
+  struct route_node *rn;
+  struct rib *rib;
+  int first = 1;
+
+  /* Show all IPv6 route. */
+  for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      {
+	if (first)
+	  {
+	    vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+	    first = 0;
+	  }
+	vty_show_ipv6_route (vty, rn, rib);
+      }
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_route_prefix_longer,
+       show_ipv6_route_prefix_longer_cmd,
+       "show ipv6 route X:X::X:X/M longer-prefixes",
+       SHOW_STR
+       IP_STR
+       "IPv6 routing table\n"
+       "IPv6 prefix\n"
+       "Show route matching the specified Network/Mask pair only\n")
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct prefix p;
+  int ret;
+  int first = 1;
+
+  ret = str2prefix (argv[0], &p);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Show matched type IPv6 routes. */
+  for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      if (prefix_match (&p, &rn->p))
+	{
+	  if (first)
+	    {
+	      vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+	      first = 0;
+	    }
+	  vty_show_ipv6_route (vty, rn, rib);
+	}
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_route_protocol,
+       show_ipv6_route_protocol_cmd,
+       "show ipv6 route (bgp|connected|kernel|ospf6|isis|ripng|static)",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n"
+       "Border Gateway Protocol (BGP)\n"
+       "Connected\n"
+       "Kernel\n"
+       "Open Shortest Path First (OSPFv3)\n"
+       "ISO IS-IS (ISIS)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n")
+{
+  int type;
+  struct route_node *rn;
+  struct rib *rib;
+  int first = 1;
+
+  if (strncmp (argv[0], "b", 1) == 0)
+    type = ZEBRA_ROUTE_BGP;
+  else if (strncmp (argv[0], "c", 1) == 0)
+    type = ZEBRA_ROUTE_CONNECT;
+  else if (strncmp (argv[0], "k", 1) ==0)
+    type = ZEBRA_ROUTE_KERNEL;
+  else if (strncmp (argv[0], "o", 1) == 0)
+    type = ZEBRA_ROUTE_OSPF6;
+  else if (strncmp (argv[0], "i", 1) == 0)
+    type = ZEBRA_ROUTE_ISIS;
+  else if (strncmp (argv[0], "r", 1) == 0)
+    type = ZEBRA_ROUTE_RIPNG;
+  else if (strncmp (argv[0], "s", 1) == 0)
+    type = ZEBRA_ROUTE_STATIC;
+  else 
+    {
+      vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  /* Show matched type IPv6 routes. */
+  for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = rib->next)
+      if (rib->type == type)
+	{
+	  if (first)
+	    {
+	      vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+	      first = 0;
+	    }
+	  vty_show_ipv6_route (vty, rn, rib);
+	}
+  return CMD_SUCCESS;
+}
+
+
+DEFUN (show_ipv6_route_addr,
+       show_ipv6_route_addr_cmd,
+       "show ipv6 route X:X::X:X",
+       SHOW_STR
+       IP_STR
+       "IPv6 routing table\n"
+       "IPv6 Address\n")
+{
+  int ret;
+  struct prefix_ipv6 p;
+  struct route_node *rn;
+
+  ret = str2prefix_ipv6 (argv[0], &p);
+  if (ret <= 0)
+    {
+      vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
+  if (! rn)
+    {
+      vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty_show_ipv6_route_detail (vty, rn);
+
+  route_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_route_prefix,
+       show_ipv6_route_prefix_cmd,
+       "show ipv6 route X:X::X:X/M",
+       SHOW_STR
+       IP_STR
+       "IPv6 routing table\n"
+       "IPv6 prefix\n")
+{
+  int ret;
+  struct prefix_ipv6 p;
+  struct route_node *rn;
+
+  ret = str2prefix_ipv6 (argv[0], &p);
+  if (ret <= 0)
+    {
+      vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  rn = route_node_match (rib_table_ipv6, (struct prefix *) &p);
+  if (! rn || rn->p.prefixlen != p.prefixlen)
+    {
+      vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty_show_ipv6_route_detail (vty, rn);
+
+  route_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+#endif /* HAVE_IPV6 */
+
+/* RIB update function. */
+void
+rib_update ()
+{
+  struct route_node *rn;
+
+  for (rn = route_top (rib_table_ipv4); rn; rn = route_next (rn))
+    /* Update reachability. */
+    rib_process (rn, NULL);
+
+#ifdef HAVE_IPV6
+  for (rn = route_top (rib_table_ipv6); rn; rn = route_next (rn))
+    rib_process (rn, NULL);
+#endif /* HAVE_IPV6 */
+}
+
+/* Interface goes up. */
+void
+rib_if_up (struct interface *ifp)
+{
+  rib_update ();
+}
+
+/* Interface goes down. */
+void
+rib_if_down (struct interface *ifp)
+{
+  rib_update ();
+}
+
+/* Clean up routines. */
+void
+rib_weed_table (struct route_table *rib_table)
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct rib *next;
+
+  for (rn = route_top (rib_table); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = next)
+      {
+	next = rib->next;
+
+        if (rib->table != rtm_table_default &&
+	    rib->table != RT_TABLE_MAIN)
+	  {
+	    rib_delnode (rn, rib);
+	    newrib_free (rib);
+	    route_unlock_node (rn);
+	  }
+      }
+}
+
+/* Delete all routes from unmanaged tables. */
+void
+rib_weed_tables ()
+{
+  rib_weed_table (rib_table_ipv4);
+#ifdef HAVE_IPV6
+  rib_weed_table (rib_table_ipv6);
+#endif /* HAVE_IPV6 */
+}
+
+void
+rib_sweep_table (struct route_table *rib_table)
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct rib *next;
+  int ret = 0;
+
+  for (rn = route_top (rib_table); rn; rn = route_next (rn))
+    for (rib = rn->info; rib; rib = next)
+      {
+	next = rib->next;
+
+        if ((rib->type == ZEBRA_ROUTE_KERNEL) && 
+	    CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
+          {
+	    ret = rib_uninstall_kernel (rn, rib);
+
+	    if (! ret)
+	      {
+		rib_delnode (rn, rib);
+		newrib_free (rib);
+		route_unlock_node (rn);
+	      }
+          }
+      }
+}
+
+void
+rib_sweep_route ()
+{
+  rib_sweep_table (rib_table_ipv4);
+#ifdef HAVE_IPV6  
+  rib_sweep_table (rib_table_ipv6);
+#endif /* HAVE_IPV6 */
+}
+
+/* Close rib when zebra terminates. */
+void
+rib_close ()
+{
+  rib_close_ipv4 ();
+#ifdef HAVE_IPV6
+  rib_close_ipv6 ();
+#endif /* HAVE_IPV6 */
+}
+
+/* Static ip route configuration write function. */
+int
+config_write_ip (struct vty *vty)
+{
+  int write = 0;
+
+  write += static_ipv4_write (vty);
+#ifdef HAVE_IPV6
+  write += static_ipv6_write (vty);
+#endif /* HAVE_IPV6 */
+
+  return write;
+}
+
+/* IP node for static routes. */
+struct cmd_node ip_node =
+{
+  IP_NODE,
+  "",				/* This node has no interface. */
+  1
+};
+
+/* Routing information base initialize. */
+void
+rib_init ()
+{
+  install_node (&ip_node, config_write_ip);
+
+  rib_table_ipv4 = route_table_init ();
+  static_table_ipv4 = route_table_init ();
+
+  install_element (VIEW_NODE, &show_ip_route_cmd);
+  install_element (VIEW_NODE, &show_ip_route_addr_cmd);
+  install_element (VIEW_NODE, &show_ip_route_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_route_prefix_longer_cmd);
+  install_element (VIEW_NODE, &show_ip_route_protocol_cmd);
+  install_element (VIEW_NODE, &show_ip_route_supernets_cmd);
+  install_element (ENABLE_NODE, &show_ip_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_route_addr_cmd);
+  install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_route_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_ip_route_protocol_cmd);
+  install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
+  install_element (CONFIG_NODE, &ip_route_cmd);
+  install_element (CONFIG_NODE, &ip_route_mask_cmd);
+  install_element (CONFIG_NODE, &no_ip_route_cmd);
+  install_element (CONFIG_NODE, &no_ip_route_mask_cmd);
+  install_element (CONFIG_NODE, &ip_route_pref_cmd);
+  install_element (CONFIG_NODE, &ip_route_mask_pref_cmd);
+  install_element (CONFIG_NODE, &no_ip_route_pref_cmd);
+  install_element (CONFIG_NODE, &no_ip_route_mask_pref_cmd);
+
+#ifdef HAVE_IPV6
+  rib_table_ipv6 = route_table_init ();
+  static_table_ipv6 = route_table_init ();
+
+  install_element (CONFIG_NODE, &ipv6_route_cmd);
+  install_element (CONFIG_NODE, &ipv6_route_ifname_cmd);
+  install_element (CONFIG_NODE, &no_ipv6_route_cmd);
+  install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd);
+  install_element (CONFIG_NODE, &ipv6_route_pref_cmd);
+  install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd);
+  install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd);
+  install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd);
+  install_element (VIEW_NODE, &show_ipv6_route_cmd);
+  install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
+  install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
+  install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd);
+  install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_route_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_route_protocol_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_route_addr_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
+#endif /* HAVE_IPV6 */
+}
diff --git a/isisd/modified/thread.c b/isisd/modified/thread.c
new file mode 100644
index 0000000..af954b8
--- /dev/null
+++ b/isisd/modified/thread.c
@@ -0,0 +1,713 @@
+/* Thread management routine
+ * Copyright (C) 1998, 2000 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.  
+ */
+
+/* #define DEBUG */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "log.h"
+
+/* Struct timeval's tv_usec one second value.  */
+#define TIMER_SECOND_MICRO 1000000L
+
+struct timeval
+timeval_adjust (struct timeval a)
+{
+  while (a.tv_usec >= TIMER_SECOND_MICRO)
+    {
+      a.tv_usec -= TIMER_SECOND_MICRO;
+      a.tv_sec++;
+    }
+
+  while (a.tv_usec < 0)
+    {
+      a.tv_usec += TIMER_SECOND_MICRO;
+      a.tv_sec--;
+    }
+
+  if (a.tv_sec < 0)
+    {
+      a.tv_sec = 0;
+      a.tv_usec = 10;
+    }
+
+  if (a.tv_sec > TIMER_SECOND_MICRO)
+    a.tv_sec = TIMER_SECOND_MICRO;    
+
+  return a;
+}
+
+static struct timeval
+timeval_subtract (struct timeval a, struct timeval b)
+{
+  struct timeval ret;
+
+  ret.tv_usec = a.tv_usec - b.tv_usec;
+  ret.tv_sec = a.tv_sec - b.tv_sec;
+
+  return timeval_adjust (ret);
+}
+
+static int
+timeval_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);
+}
+
+static unsigned long
+timeval_elapsed (struct timeval a, struct timeval b)
+{
+  return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)
+	  + (a.tv_usec - b.tv_usec));
+}
+
+/* List allocation and head/tail print out. */
+static void
+thread_list_debug (struct thread_list *list)
+{
+  printf ("count [%d] head [%p] tail [%p]\n",
+	  list->count, list->head, list->tail);
+}
+
+/* Debug print for thread_master. */
+void
+thread_master_debug (struct thread_master *m)
+{
+  printf ("-----------\n");
+  printf ("readlist  : ");
+  thread_list_debug (&m->read);
+  printf ("writelist : ");
+  thread_list_debug (&m->write);
+  printf ("timerlist : ");
+  thread_list_debug (&m->timer);
+  printf ("eventlist : ");
+  thread_list_debug (&m->event);
+  printf ("unuselist : ");
+  thread_list_debug (&m->unuse);
+  printf ("total alloc: [%ld]\n", m->alloc);
+  printf ("-----------\n");
+}
+
+/* Allocate new thread master.  */
+struct thread_master *
+thread_master_create ()
+{
+  return (struct thread_master *) XCALLOC (MTYPE_THREAD_MASTER,
+					   sizeof (struct thread_master));
+}
+
+/* Add a new thread to the list.  */
+static void
+thread_list_add (struct thread_list *list, struct thread *thread)
+{
+  thread->next = NULL;
+  thread->prev = list->tail;
+  if (list->tail)
+    list->tail->next = thread;
+  else
+    list->head = thread;
+  list->tail = thread;
+  list->count++;
+}
+
+/* Add a new thread just before the point.  */
+static void
+thread_list_add_before (struct thread_list *list, 
+			struct thread *point, 
+			struct thread *thread)
+{
+  thread->next = point;
+  thread->prev = point->prev;
+  if (point->prev)
+    point->prev->next = thread;
+  else
+    list->head = thread;
+  point->prev = thread;
+  list->count++;
+}
+
+/* Delete a thread from the list. */
+static struct thread *
+thread_list_delete (struct thread_list *list, struct thread *thread)
+{
+  if (thread->next)
+    thread->next->prev = thread->prev;
+  else
+    list->tail = thread->prev;
+  if (thread->prev)
+    thread->prev->next = thread->next;
+  else
+    list->head = thread->next;
+  thread->next = thread->prev = NULL;
+  list->count--;
+  return thread;
+}
+
+/* Move thread to unuse list. */
+static void
+thread_add_unuse (struct thread_master *m, struct thread *thread)
+{
+  assert (m != NULL);
+  assert (thread->next == NULL);
+  assert (thread->prev == NULL);
+  assert (thread->type == THREAD_UNUSED);
+  thread_list_add (&m->unuse, thread);
+}
+
+/* Free all unused thread. */
+static void
+thread_list_free (struct thread_master *m, struct thread_list *list)
+{
+  struct thread *t;
+  struct thread *next;
+
+  for (t = list->head; t; t = next)
+    {
+      next = t->next;
+      XFREE (MTYPE_THREAD, t);
+      list->count--;
+      m->alloc--;
+    }
+}
+
+/* Stop thread scheduler. */
+void
+thread_master_free (struct thread_master *m)
+{
+  thread_list_free (m, &m->read);
+  thread_list_free (m, &m->write);
+  thread_list_free (m, &m->timer);
+  thread_list_free (m, &m->event);
+  thread_list_free (m, &m->ready);
+  thread_list_free (m, &m->unuse);
+
+  XFREE (MTYPE_THREAD_MASTER, m);
+}
+
+/* Delete top of the list and return it. */
+static struct thread *
+thread_trim_head (struct thread_list *list)
+{
+  if (list->head)
+    return thread_list_delete (list, list->head);
+  return NULL;
+}
+
+/* Thread list is empty or not.  */
+int
+thread_empty (struct thread_list *list)
+{
+  return  list->head ? 0 : 1;
+}
+
+/* Return remain time in second. */
+unsigned long
+thread_timer_remain_second (struct thread *thread)
+{
+  struct timeval timer_now;
+
+  gettimeofday (&timer_now, NULL);
+
+  if (thread->u.sands.tv_sec - timer_now.tv_sec > 0)
+    return thread->u.sands.tv_sec - timer_now.tv_sec;
+  else
+    return 0;
+}
+
+/* Get new thread.  */
+static struct thread *
+thread_get (struct thread_master *m, u_char type,
+	    int (*func) (struct thread *), void *arg)
+{
+  struct thread *thread;
+
+  if (m->unuse.head)
+    thread = thread_trim_head (&m->unuse);
+  else
+    {
+      thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
+      m->alloc++;
+    }
+  thread->type = type;
+  thread->master = m;
+  thread->func = func;
+  thread->arg = arg;
+
+  return thread;
+}
+
+/* Add new read thread. */
+struct thread *
+thread_add_read (struct thread_master *m, 
+		 int (*func) (struct thread *), void *arg, int fd)
+{
+  struct thread *thread;
+
+  assert (m != NULL);
+
+  if (FD_ISSET (fd, &m->readfd))
+    {
+      zlog (NULL, LOG_WARNING, "There is already read fd [%d]", fd);
+      return NULL;
+    }
+
+  thread = thread_get (m, THREAD_READ, func, arg);
+  FD_SET (fd, &m->readfd);
+  thread->u.fd = fd;
+  thread_list_add (&m->read, thread);
+
+  return thread;
+}
+
+/* Add new write thread. */
+struct thread *
+thread_add_write (struct thread_master *m,
+		 int (*func) (struct thread *), void *arg, int fd)
+{
+  struct thread *thread;
+
+  assert (m != NULL);
+
+  if (FD_ISSET (fd, &m->writefd))
+    {
+      zlog (NULL, LOG_WARNING, "There is already write fd [%d]", fd);
+      return NULL;
+    }
+
+  thread = thread_get (m, THREAD_WRITE, func, arg);
+  FD_SET (fd, &m->writefd);
+  thread->u.fd = fd;
+  thread_list_add (&m->write, thread);
+
+  return thread;
+}
+
+/* Add timer event thread. */
+struct thread *
+thread_add_timer (struct thread_master *m,
+		  int (*func) (struct thread *), void *arg, long timer)
+{
+  struct timeval timer_now;
+  struct thread *thread;
+#ifndef TIMER_NO_SORT
+  struct thread *tt;
+#endif /* TIMER_NO_SORT */
+
+  assert (m != NULL);
+
+  thread = thread_get (m, THREAD_TIMER, func, arg);
+
+  /* Do we need jitter here? */
+  gettimeofday (&timer_now, NULL);
+  timer_now.tv_sec += timer;
+  thread->u.sands = timer_now;
+
+  /* Sort by timeval. */
+#ifdef TIMER_NO_SORT
+  thread_list_add (&m->timer, thread);
+#else
+  for (tt = m->timer.head; tt; tt = tt->next)
+    if (timeval_cmp (thread->u.sands, tt->u.sands) <= 0)
+      break;
+
+  if (tt)
+    thread_list_add_before (&m->timer, tt, thread);
+  else
+    thread_list_add (&m->timer, thread);
+#endif /* TIMER_NO_SORT */
+
+  return thread;
+}
+
+/* Add timer event thread with "millisecond" resolution */
+struct thread *
+thread_add_timer_msec (struct thread_master *m,
+                       int (*func)(struct thread *),
+                       void *arg, long timer)
+{
+  struct timeval timer_now;
+  struct thread *thread;
+#ifndef TIMER_NO_SORT
+  struct thread *tt;
+#endif /* TIMER_NO_SORT */
+
+  assert (m != NULL);
+
+  thread = thread_get (m, THREAD_TIMER, func, arg);
+
+  timer = 1000*timer; /* milli -> micro */
+
+  gettimeofday (&timer_now, NULL);
+  timer_now.tv_sec += timer / TIMER_SECOND_MICRO;
+  timer_now.tv_usec += (timer % TIMER_SECOND_MICRO);
+  thread->u.sands = timer_now;
+
+
+  /* Sort by timeval. */
+#ifdef TIMER_NO_SORT
+  thread_list_add (&m->timer, thread);
+#else
+  for (tt = m->timer.head; tt; tt = tt->next)
+    if (timeval_cmp (thread->u.sands, tt->u.sands) <= 0)
+      break;
+
+  if (tt)
+    thread_list_add_before (&m->timer, tt, thread);
+  else
+    thread_list_add (&m->timer, thread);
+#endif /* TIMER_NO_SORT */
+
+  return thread;
+}
+
+
+/* Add simple event thread. */
+struct thread *
+thread_add_event (struct thread_master *m,
+		  int (*func) (struct thread *), void *arg, int val)
+{
+  struct thread *thread;
+
+  assert (m != NULL);
+
+  thread = thread_get (m, THREAD_EVENT, func, arg);
+  thread->u.val = val;
+  thread_list_add (&m->event, thread);
+
+  return thread;
+}
+
+/* Cancel thread from scheduler. */
+void
+thread_cancel (struct thread *thread)
+{
+  switch (thread->type)
+    {
+    case THREAD_READ:
+      assert (FD_ISSET (thread->u.fd, &thread->master->readfd));
+      FD_CLR (thread->u.fd, &thread->master->readfd);
+      thread_list_delete (&thread->master->read, thread);
+      break;
+    case THREAD_WRITE:
+      assert (FD_ISSET (thread->u.fd, &thread->master->writefd));
+      FD_CLR (thread->u.fd, &thread->master->writefd);
+      thread_list_delete (&thread->master->write, thread);
+      break;
+    case THREAD_TIMER:
+      thread_list_delete (&thread->master->timer, thread);
+      break;
+    case THREAD_EVENT:
+      thread_list_delete (&thread->master->event, thread);
+      break;
+    case THREAD_READY:
+      thread_list_delete (&thread->master->ready, thread);
+      break;
+    case THREAD_UNUSED:
+      thread_list_delete (&thread->master->unuse, thread);
+      break;
+    default:
+      break;
+    }
+  thread->type = THREAD_UNUSED;
+  thread_add_unuse (thread->master, thread);
+}
+
+/* Delete all events which has argument value arg. */
+void
+thread_cancel_event (struct thread_master *m, void *arg)
+{
+  struct thread *thread;
+
+  thread = m->event.head;
+  while (thread)
+    {
+      struct thread *t;
+
+      t = thread;
+      thread = t->next;
+
+      if (t->arg == arg)
+	{
+	  thread_list_delete (&m->event, t);
+	  t->type = THREAD_UNUSED;
+	  thread_add_unuse (m, t);
+	}
+    }
+}
+
+#ifdef TIMER_NO_SORT
+struct timeval *
+thread_timer_wait (struct thread_master *m, struct timeval *timer_val)
+{
+  struct timeval timer_now;
+  struct timeval timer_min;
+  struct timeval *timer_wait;
+
+  gettimeofday (&timer_now, NULL);
+
+  timer_wait = NULL;
+  for (thread = m->timer.head; thread; thread = thread->next)
+    {
+      if (! timer_wait)
+	timer_wait = &thread->u.sands;
+      else if (timeval_cmp (thread->u.sands, *timer_wait) < 0)
+	timer_wait = &thread->u.sands;
+    }
+
+  if (m->timer.head)
+    {
+      timer_min = *timer_wait;
+      timer_min = timeval_subtract (timer_min, timer_now);
+      if (timer_min.tv_sec < 0)
+	{
+	  timer_min.tv_sec = 0;
+	  timer_min.tv_usec = 10;
+	}
+      timer_wait = &timer_min;
+    }
+  else
+    timer_wait = NULL;
+
+  if (timer_wait)
+    {
+      *timer_val = timer_wait;
+      return timer_val;
+    }
+  return NULL;
+}
+#else /* ! TIMER_NO_SORT */
+struct timeval *
+thread_timer_wait (struct thread_master *m, struct timeval *timer_val)
+{
+  struct timeval timer_now;
+  struct timeval timer_min;
+
+  if (m->timer.head)
+    {
+      gettimeofday (&timer_now, NULL);
+      timer_min = m->timer.head->u.sands;
+      timer_min = timeval_subtract (timer_min, timer_now);
+      if (timer_min.tv_sec < 0)
+	{
+	  timer_min.tv_sec = 0;
+	  timer_min.tv_usec = 10;
+	}
+      *timer_val = timer_min;
+      return timer_val;
+    }
+  return NULL;
+}
+#endif /* TIMER_NO_SORT */
+
+struct thread *
+thread_run (struct thread_master *m, struct thread *thread,
+	    struct thread *fetch)
+{
+  *fetch = *thread;
+  thread->type = THREAD_UNUSED;
+  thread_add_unuse (m, thread);
+  return fetch;
+}
+
+int
+thread_process_fd (struct thread_master *m, struct thread_list *list,
+		   fd_set *fdset, fd_set *mfdset)
+{
+  struct thread *thread;
+  struct thread *next;
+  int ready = 0;
+
+  for (thread = list->head; thread; thread = next)
+    {
+      next = thread->next;
+
+      if (FD_ISSET (THREAD_FD (thread), fdset))
+	{
+	  assert (FD_ISSET (THREAD_FD (thread), mfdset));
+	  FD_CLR(THREAD_FD (thread), mfdset);
+	  thread_list_delete (list, thread);
+	  thread_list_add (&m->ready, thread);
+	  thread->type = THREAD_READY;
+	  ready++;
+	}
+    }
+  return ready;
+}
+
+/* Fetch next ready thread. */
+struct thread *
+thread_fetch (struct thread_master *m, struct thread *fetch)
+{
+  int num;
+  int ready;
+  struct thread *thread;
+  fd_set readfd;
+  fd_set writefd;
+  fd_set exceptfd;
+  struct timeval timer_now;
+  struct timeval timer_val;
+  struct timeval *timer_wait;
+  struct timeval timer_nowait;
+
+  timer_nowait.tv_sec = 0;
+  timer_nowait.tv_usec = 0;
+
+  while (1)
+    {
+      /* Normal event is the highest priority.  */
+      if ((thread = thread_trim_head (&m->event)) != NULL)
+	return thread_run (m, thread, fetch);
+
+      /* Execute timer.  */
+      gettimeofday (&timer_now, NULL);
+
+      for (thread = m->timer.head; thread; thread = thread->next)
+	if (timeval_cmp (timer_now, thread->u.sands) >= 0)
+	  {
+	    thread_list_delete (&m->timer, thread);
+	    return thread_run (m, thread, fetch);
+	  }
+
+      /* If there are any ready threads, process top of them.  */
+      if ((thread = thread_trim_head (&m->ready)) != NULL)
+	return thread_run (m, thread, fetch);
+
+      /* Structure copy.  */
+      readfd = m->readfd;
+      writefd = m->writefd;
+      exceptfd = m->exceptfd;
+
+      /* Calculate select wait timer. */
+      timer_wait = thread_timer_wait (m, &timer_val);
+
+      num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
+
+      if (num == 0)
+	continue;
+
+      if (num < 0)
+	{
+	  if (errno == EINTR)
+	    continue;
+
+	  zlog_warn ("select() error: %s", strerror (errno));
+	  return NULL;
+	}
+
+      /* Normal priority read thead. */
+      ready = thread_process_fd (m, &m->read, &readfd, &m->readfd);
+
+      /* Write thead. */
+      ready = thread_process_fd (m, &m->write, &writefd, &m->writefd);
+
+      if ((thread = thread_trim_head (&m->ready)) != NULL)
+	return thread_run (m, thread, fetch);
+    }
+}
+
+static unsigned long
+thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start)
+{
+  unsigned long thread_time;
+
+#ifdef HAVE_RUSAGE
+  /* This is 'user + sys' time.  */
+  thread_time = timeval_elapsed (now->ru_utime, start->ru_utime);
+  thread_time += timeval_elapsed (now->ru_stime, start->ru_stime);
+#else
+  /* When rusage is not available, simple elapsed time is used.  */
+  thread_time = timeval_elapsed (*now, *start);
+#endif /* HAVE_RUSAGE */
+
+  return thread_time;
+}
+
+/* We should aim to yield after THREAD_YIELD_TIME_SLOT
+   milliseconds.  */
+int
+thread_should_yield (struct thread *thread)
+{
+  RUSAGE_T ru;
+
+  GETRUSAGE (&ru);
+
+  if (thread_consumed_time (&ru, &thread->ru) > THREAD_YIELD_TIME_SLOT)
+    return 1;
+  else
+    return 0;
+}
+
+/* We check thread consumed time. If the system has getrusage, we'll
+   use that to get indepth stats on the performance of the thread.  If
+   not - we'll use gettimeofday for some guestimation.  */
+void
+thread_call (struct thread *thread)
+{
+  unsigned long thread_time;
+  RUSAGE_T ru;
+
+  GETRUSAGE (&thread->ru);
+
+  (*thread->func) (thread);
+
+  GETRUSAGE (&ru);
+
+  thread_time = thread_consumed_time (&ru, &thread->ru);
+
+#ifdef THREAD_CONSUMED_TIME_CHECK
+  if (thread_time > 200000L)
+    {
+      /*
+       * We have a CPU Hog on our hands.
+       * Whinge about it now, so we're aware this is yet another task
+       * to fix.
+       */
+      zlog_err ("CPU HOG task %lx ran for %ldms",
+                /* FIXME: report the name of the function somehow */
+		(unsigned long) thread->func,
+		thread_time / 1000L);
+    }
+#endif /* THREAD_CONSUMED_TIME_CHECK */
+}
+
+/* Execute thread */
+struct thread *
+thread_execute (struct thread_master *m,
+                int (*func)(struct thread *), 
+                void *arg,
+                int val)
+{
+  struct thread dummy; 
+
+  memset (&dummy, 0, sizeof (struct thread));
+
+  dummy.type = THREAD_EVENT;
+  dummy.master = NULL;
+  dummy.func = func;
+  dummy.arg = arg;
+  dummy.u.val = val;
+  thread_call (&dummy);
+
+  return NULL;
+}
diff --git a/isisd/modified/thread.h b/isisd/modified/thread.h
new file mode 100644
index 0000000..c3fac43
--- /dev/null
+++ b/isisd/modified/thread.h
@@ -0,0 +1,141 @@
+/* Thread management routine header.
+ * Copyright (C) 1998 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.  
+ */
+
+#ifndef _ZEBRA_THREAD_H
+#define _ZEBRA_THREAD_H
+
+#ifdef HAVE_RUSAGE
+#define RUSAGE_T        struct rusage
+#define GETRUSAGE(X)    getrusage (RUSAGE_SELF, X);
+#else
+#define RUSAGE_T        struct timeval
+#define GETRUSAGE(X)    gettimeofday (X, NULL);
+#endif /* HAVE_RUSAGE */
+
+/* Linked list of thread. */
+struct thread_list
+{
+  struct thread *head;
+  struct thread *tail;
+  int count;
+};
+
+/* Master of the theads. */
+struct thread_master
+{
+  struct thread_list read;
+  struct thread_list write;
+  struct thread_list timer;
+  struct thread_list event;
+  struct thread_list ready;
+  struct thread_list unuse;
+  fd_set readfd;
+  fd_set writefd;
+  fd_set exceptfd;
+  unsigned long alloc;
+};
+
+/* Thread itself. */
+struct thread
+{
+  unsigned char type;		/* thread type */
+  struct thread *next;		/* next pointer of the thread */
+  struct thread *prev;		/* previous pointer of the thread */
+  struct thread_master *master;	/* pointer to the struct thread_master. */
+  int (*func) (struct thread *); /* event function */
+  void *arg;			/* event argument */
+  union {
+    int val;			/* second argument of the event. */
+    int fd;			/* file descriptor in case of read/write. */
+    struct timeval sands;	/* rest of time sands value. */
+  } u;
+  RUSAGE_T ru;			/* Indepth usage info.  */
+};
+
+/* Thread types. */
+#define THREAD_READ           0
+#define THREAD_WRITE          1
+#define THREAD_TIMER          2
+#define THREAD_EVENT          3
+#define THREAD_READY          4
+#define THREAD_UNUSED         5
+
+/* Thread yield time.  */
+#define THREAD_YIELD_TIME_SLOT     100 * 1000L /* 100ms */
+
+/* Macros. */
+#define THREAD_ARG(X) ((X)->arg)
+#define THREAD_FD(X)  ((X)->u.fd)
+#define THREAD_VAL(X) ((X)->u.val)
+
+#define THREAD_READ_ON(master,thread,func,arg,sock) \
+  do { \
+    if (! thread) \
+      thread = thread_add_read (master, func, arg, sock); \
+  } while (0)
+
+#define THREAD_WRITE_ON(master,thread,func,arg,sock) \
+  do { \
+    if (! thread) \
+      thread = thread_add_write (master, func, arg, sock); \
+  } while (0)
+
+#define THREAD_TIMER_ON(master,thread,func,arg,time) \
+  do { \
+    if (! thread) \
+      thread = thread_add_timer (master, func, arg, time); \
+  } while (0)
+
+#define THREAD_OFF(thread) \
+  do { \
+    if (thread) \
+      { \
+        thread_cancel (thread); \
+        thread = NULL; \
+      } \
+  } while (0)
+
+#define THREAD_READ_OFF(thread)  THREAD_OFF(thread)
+#define THREAD_WRITE_OFF(thread)  THREAD_OFF(thread)
+#define THREAD_TIMER_OFF(thread)  THREAD_OFF(thread)
+
+/* Prototypes. */
+struct thread_master *thread_master_create ();
+struct thread *thread_add_read (struct thread_master *, 
+				int (*)(struct thread *), void *, int);
+struct thread *thread_add_write (struct thread_master *,
+				 int (*)(struct thread *), void *, int);
+struct thread *thread_add_timer (struct thread_master *,
+				 int (*)(struct thread *), void *, long);
+struct thread *thread_add_timer_msec (struct thread_master *,
+                                       int (*)(struct thread *), void *, long);
+struct thread *thread_add_event (struct thread_master *,
+				 int (*)(struct thread *), void *, int );
+void thread_cancel (struct thread *);
+void thread_cancel_event (struct thread_master *, void *);
+
+struct thread *thread_fetch (struct thread_master *, struct thread *);
+struct thread *thread_execute (struct thread_master *,
+			       int (*)(struct thread *), void *, int);
+void thread_call (struct thread *);
+unsigned long thread_timer_remain_second (struct thread *);
+
+#endif /* _ZEBRA_THREAD_H */
diff --git a/isisd/modified/vty.c b/isisd/modified/vty.c
new file mode 100644
index 0000000..6de0e0d
--- /dev/null
+++ b/isisd/modified/vty.c
@@ -0,0 +1,2786 @@
+/*
+ * Virtual terminal [aka TeletYpe] interface routine.
+ * Copyright (C) 1997, 98 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.  
+ */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "buffer.h"
+#include "version.h"
+#include "command.h"
+#include "sockunion.h"
+#include "thread.h"
+#include "memory.h"
+#include "str.h"
+#include "log.h"
+#include "prefix.h"
+#include "filter.h"
+
+/* Vty events */
+enum event 
+{
+  VTY_SERV,
+  VTY_READ,
+  VTY_WRITE,
+  VTY_TIMEOUT_RESET,
+#ifdef VTYSH
+  VTYSH_SERV,
+  VTYSH_READ
+#endif /* VTYSH */
+};
+
+static void vty_event (enum event, int, struct vty *);
+
+/* Extern host structure from command.c */
+extern struct host host;
+
+/* Vector which store each vty structure. */
+static vector vtyvec;
+
+/* Vty timeout value. */
+static unsigned long vty_timeout_val = VTY_TIMEOUT_DEFAULT;
+
+/* Vty access-class command */
+static char *vty_accesslist_name = NULL;
+
+/* Vty access-calss for IPv6. */
+static char *vty_ipv6_accesslist_name = NULL;
+
+/* VTY server thread. */
+vector Vvty_serv_thread;
+
+/* Current directory. */
+char *vty_cwd = NULL;
+
+/* Configure lock. */
+static int vty_config;
+
+/* Login password check. */
+static int no_password_check = 0;
+
+/* Integrated configuration file path */
+char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
+
+
+/* VTY standard output function. */
+int
+vty_out (struct vty *vty, const char *format, ...)
+{
+  va_list args;
+  int len = 0;
+  int size = 1024;
+  char buf[1024];
+  char *p = NULL;
+  
+  va_start (args, format);
+
+  if (vty_shell (vty))
+    vprintf (format, args);
+  else
+    {
+      /* Try to write to initial buffer.  */
+      len = vsnprintf (buf, sizeof buf, format, args);
+
+      /* Initial buffer is not enough.  */
+      if (len < 0 || len >= size)
+	{
+	  while (1)
+	    {
+	      if (len > -1)
+		size = len + 1;
+	      else
+		size = size * 2;
+
+	      p = XREALLOC (MTYPE_VTY_OUT_BUF, p, size);
+	      if (! p)
+		return -1;
+
+	      len = vsnprintf (p, size, format, args);
+
+	      if (len > -1 && len < size)
+		break;
+	    }
+	}
+
+      /* When initial buffer is enough to store all output.  */
+      if (! p)
+	p = buf;
+
+      /* Pointer p must point out buffer. */
+      if (vty_shell_serv (vty))
+	write (vty->fd, (u_char *) p, len);
+      else
+	buffer_write (vty->obuf, (u_char *) p, len);
+
+      /* If p is not different with buf, it is allocated buffer.  */
+      if (p != buf)
+	XFREE (MTYPE_VTY_OUT_BUF, p);
+    }
+
+  va_end (args);
+
+  return len;
+}
+
+int
+vty_log_out (struct vty *vty, const char *proto_str, const char *format,
+	     va_list va)
+{
+  int len;
+  char buf[1024];
+
+  snprintf (buf, sizeof buf, "%s: ", proto_str);
+  write (vty->fd, buf, strlen (proto_str) + 2);
+
+  len = vsnprintf (buf, sizeof buf, format, va);
+  if (len < 0)
+    return -1;
+  write (vty->fd, (u_char *)buf, len);
+
+  snprintf (buf, sizeof buf, "\r\n");
+  write (vty->fd, buf, 2);
+
+  return len;
+}
+
+/* Output current time to the vty. */
+void
+vty_time_print (struct vty *vty, int cr)
+{
+  time_t clock;
+  struct tm *tm;
+#define TIME_BUF 25
+  char buf [TIME_BUF];
+  int ret;
+  
+  time (&clock);
+  tm = localtime (&clock);
+
+  ret = strftime (buf, TIME_BUF, "%Y/%m/%d %H:%M:%S", tm);
+  if (ret == 0)
+    {
+      zlog (NULL, LOG_INFO, "strftime error");
+      return;
+    }
+  if (cr)
+    vty_out (vty, "%s\n", buf);
+  else
+    vty_out (vty, "%s ", buf);
+
+  return;
+}
+
+/* Say hello to vty interface. */
+void
+vty_hello (struct vty *vty)
+{
+  if (host.motd)
+    vty_out (vty, host.motd);
+}
+
+/* Put out prompt and wait input from user. */
+static void
+vty_prompt (struct vty *vty)
+{
+  struct utsname names;
+  const char*hostname;
+
+  if (vty->type == VTY_TERM)
+    {
+      hostname = host.name;
+      if (!hostname)
+	{
+	  uname (&names);
+	  hostname = names.nodename;
+	}
+      vty_out (vty, cmd_prompt (vty->node), hostname);
+    }
+}
+
+/* Send WILL TELOPT_ECHO to remote server. */
+void
+vty_will_echo (struct vty *vty)
+{
+  char cmd[] = { IAC, WILL, TELOPT_ECHO, '\0' };
+  vty_out (vty, "%s", cmd);
+}
+
+/* Make suppress Go-Ahead telnet option. */
+static void
+vty_will_suppress_go_ahead (struct vty *vty)
+{
+  char cmd[] = { IAC, WILL, TELOPT_SGA, '\0' };
+  vty_out (vty, "%s", cmd);
+}
+
+/* Make don't use linemode over telnet. */
+static void
+vty_dont_linemode (struct vty *vty)
+{
+  char cmd[] = { IAC, DONT, TELOPT_LINEMODE, '\0' };
+  vty_out (vty, "%s", cmd);
+}
+
+/* Use window size. */
+static void
+vty_do_window_size (struct vty *vty)
+{
+  char cmd[] = { IAC, DO, TELOPT_NAWS, '\0' };
+  vty_out (vty, "%s", cmd);
+}
+
+#if 0 /* Currently not used. */
+/* Make don't use lflow vty interface. */
+static void
+vty_dont_lflow_ahead (struct vty *vty)
+{
+  char cmd[] = { IAC, DONT, TELOPT_LFLOW, '\0' };
+  vty_out (vty, "%s", cmd);
+}
+#endif /* 0 */
+
+/* Allocate new vty struct. */
+struct vty *
+vty_new ()
+{
+  struct vty *new = XCALLOC (MTYPE_VTY, sizeof (struct vty));
+
+  new->obuf = (struct buffer *) buffer_new (100);
+  new->buf = XCALLOC (MTYPE_VTY, VTY_BUFSIZ);
+  new->max = VTY_BUFSIZ;
+  new->sb_buffer = NULL;
+
+  return new;
+}
+
+/* Authentication of vty */
+static void
+vty_auth (struct vty *vty, char *buf)
+{
+  char *passwd = NULL;
+  enum node_type next_node = 0;
+  int fail;
+  char *crypt (const char *, const char *);
+
+  switch (vty->node)
+    {
+    case AUTH_NODE:
+      if (host.encrypt)
+	passwd = host.password_encrypt;
+      else
+	passwd = host.password;
+      if (host.advanced)
+	next_node = host.enable ? VIEW_NODE : ENABLE_NODE;
+      else
+	next_node = VIEW_NODE;
+      break;
+    case AUTH_ENABLE_NODE:
+      if (host.encrypt)
+	passwd = host.enable_encrypt;
+      else
+	passwd = host.enable;
+      next_node = ENABLE_NODE;
+      break;
+    }
+
+  if (passwd)
+    {
+      if (host.encrypt)
+	fail = strcmp (crypt(buf, passwd), passwd);
+      else
+	fail = strcmp (buf, passwd);
+    }
+  else
+    fail = 1;
+
+  if (! fail)
+    {
+      vty->fail = 0;
+      vty->node = next_node;	/* Success ! */
+    }
+  else
+    {
+      vty->fail++;
+      if (vty->fail >= 3)
+	{
+	  if (vty->node == AUTH_NODE)
+	    {
+	      vty_out (vty, "%% Bad passwords, too many failures!%s", VTY_NEWLINE);
+	      vty->status = VTY_CLOSE;
+	    }
+	  else			
+	    {
+	      /* AUTH_ENABLE_NODE */
+	      vty->fail = 0;
+	      vty_out (vty, "%% Bad enable passwords, too many failures!%s", VTY_NEWLINE);
+	      vty->node = VIEW_NODE;
+	    }
+	}
+    }
+}
+
+/* Command execution over the vty interface. */
+int
+vty_command (struct vty *vty, char *buf)
+{
+  int ret;
+  vector vline;
+
+  /* Split readline string up into the vector */
+  vline = cmd_make_strvec (buf);
+
+  if (vline == NULL)
+    return CMD_SUCCESS;
+
+  ret = cmd_execute_command (vline, vty, NULL);
+
+  if (ret != CMD_SUCCESS)
+    switch (ret)
+      {
+      case CMD_WARNING:
+	if (vty->type == VTY_FILE)
+	  vty_out (vty, "Warning...%s", VTY_NEWLINE);
+	break;
+      case CMD_ERR_AMBIGUOUS:
+	vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
+	break;
+      case CMD_ERR_NO_MATCH:
+	vty_out (vty, "%% Unknown command.%s", VTY_NEWLINE);
+	break;
+      case CMD_ERR_INCOMPLETE:
+	vty_out (vty, "%% Command incomplete.%s", VTY_NEWLINE);
+	break;
+      }
+  cmd_free_strvec (vline);
+
+  return ret;
+}
+
+char telnet_backward_char = 0x08;
+char telnet_space_char = ' ';
+
+/* Basic function to write buffer to vty. */
+static void
+vty_write (struct vty *vty, char *buf, size_t nbytes)
+{
+  if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
+    return;
+
+  /* Should we do buffering here ?  And make vty_flush (vty) ? */
+  buffer_write (vty->obuf, (u_char *)buf, nbytes);
+}
+
+/* Ensure length of input buffer.  Is buffer is short, double it. */
+static void
+vty_ensure (struct vty *vty, int length)
+{
+  if (vty->max <= length)
+    {
+      vty->max *= 2;
+      vty->buf = XREALLOC (MTYPE_VTY, vty->buf, vty->max);
+    }
+}
+
+/* Basic function to insert character into vty. */
+static void
+vty_self_insert (struct vty *vty, char c)
+{
+  int i;
+  int length;
+
+  vty_ensure (vty, vty->length + 1);
+  length = vty->length - vty->cp;
+  memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
+  vty->buf[vty->cp] = c;
+
+  vty_write (vty, &vty->buf[vty->cp], length + 1);
+  for (i = 0; i < length; i++)
+    vty_write (vty, &telnet_backward_char, 1);
+
+  vty->cp++;
+  vty->length++;
+}
+
+/* Self insert character 'c' in overwrite mode. */
+static void
+vty_self_insert_overwrite (struct vty *vty, char c)
+{
+  vty_ensure (vty, vty->length + 1);
+  vty->buf[vty->cp++] = c;
+
+  if (vty->cp > vty->length)
+    vty->length++;
+
+  if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
+    return;
+
+  vty_write (vty, &c, 1);
+}
+
+/* Insert a word into vty interface with overwrite mode. */
+static void
+vty_insert_word_overwrite (struct vty *vty, char *str)
+{
+  int len = strlen (str);
+  vty_write (vty, str, len);
+  strcpy (&vty->buf[vty->cp], str);
+  vty->cp += len;
+  vty->length = vty->cp;
+}
+
+/* Forward character. */
+static void
+vty_forward_char (struct vty *vty)
+{
+  if (vty->cp < vty->length)
+    {
+      vty_write (vty, &vty->buf[vty->cp], 1);
+      vty->cp++;
+    }
+}
+
+/* Backward character. */
+static void
+vty_backward_char (struct vty *vty)
+{
+  if (vty->cp > 0)
+    {
+      vty->cp--;
+      vty_write (vty, &telnet_backward_char, 1);
+    }
+}
+
+/* Move to the beginning of the line. */
+static void
+vty_beginning_of_line (struct vty *vty)
+{
+  while (vty->cp)
+    vty_backward_char (vty);
+}
+
+/* Move to the end of the line. */
+static void
+vty_end_of_line (struct vty *vty)
+{
+  while (vty->cp < vty->length)
+    vty_forward_char (vty);
+}
+
+static void vty_kill_line_from_beginning (struct vty *);
+static void vty_redraw_line (struct vty *);
+
+/* Print command line history.  This function is called from
+   vty_next_line and vty_previous_line. */
+static void
+vty_history_print (struct vty *vty)
+{
+  int length;
+
+  vty_kill_line_from_beginning (vty);
+
+  /* Get previous line from history buffer */
+  length = strlen (vty->hist[vty->hp]);
+  memcpy (vty->buf, vty->hist[vty->hp], length);
+  vty->cp = vty->length = length;
+
+  /* Redraw current line */
+  vty_redraw_line (vty);
+}
+
+/* Show next command line history. */
+void
+vty_next_line (struct vty *vty)
+{
+  int try_index;
+
+  if (vty->hp == vty->hindex)
+    return;
+
+  /* Try is there history exist or not. */
+  try_index = vty->hp;
+  if (try_index == (VTY_MAXHIST - 1))
+    try_index = 0;
+  else
+    try_index++;
+
+  /* If there is not history return. */
+  if (vty->hist[try_index] == NULL)
+    return;
+  else
+    vty->hp = try_index;
+
+  vty_history_print (vty);
+}
+
+/* Show previous command line history. */
+void
+vty_previous_line (struct vty *vty)
+{
+  int try_index;
+
+  try_index = vty->hp;
+  if (try_index == 0)
+    try_index = VTY_MAXHIST - 1;
+  else
+    try_index--;
+
+  if (vty->hist[try_index] == NULL)
+    return;
+  else
+    vty->hp = try_index;
+
+  vty_history_print (vty);
+}
+
+/* This function redraw all of the command line character. */
+static void
+vty_redraw_line (struct vty *vty)
+{
+  vty_write (vty, vty->buf, vty->length);
+  vty->cp = vty->length;
+}
+
+/* Forward word. */
+static void
+vty_forward_word (struct vty *vty)
+{
+  while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
+    vty_forward_char (vty);
+  
+  while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
+    vty_forward_char (vty);
+}
+
+/* Backward word without skipping training space. */
+static void
+vty_backward_pure_word (struct vty *vty)
+{
+  while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
+    vty_backward_char (vty);
+}
+
+/* Backward word. */
+static void
+vty_backward_word (struct vty *vty)
+{
+  while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
+    vty_backward_char (vty);
+
+  while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
+    vty_backward_char (vty);
+}
+
+/* When '^D' is typed at the beginning of the line we move to the down
+   level. */
+static void
+vty_down_level (struct vty *vty)
+{
+  vty_out (vty, "%s", VTY_NEWLINE);
+  config_exit (NULL, vty, 0, NULL);
+  vty_prompt (vty);
+  vty->cp = 0;
+}
+
+/* When '^Z' is received from vty, move down to the enable mode. */
+void
+vty_end_config (struct vty *vty)
+{
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  switch (vty->node)
+    {
+    case VIEW_NODE:
+    case ENABLE_NODE:
+      /* Nothing to do. */
+      break;
+    case CONFIG_NODE:
+    case INTERFACE_NODE:
+    case ZEBRA_NODE:
+    case RIP_NODE:
+    case RIPNG_NODE:
+    case BGP_NODE:
+    case BGP_VPNV4_NODE:
+    case BGP_IPV4_NODE:
+    case BGP_IPV4M_NODE:
+    case BGP_IPV6_NODE:
+    case RMAP_NODE:
+    case OSPF_NODE:
+    case OSPF6_NODE:
+    case ISIS_NODE:
+    case KEYCHAIN_NODE:
+    case KEYCHAIN_KEY_NODE:
+    case MASC_NODE:
+    case VTY_NODE:
+      vty_config_unlock (vty);
+      vty->node = ENABLE_NODE;
+      break;
+    default:
+      /* Unknown node, we have to ignore it. */
+      break;
+    }
+
+  vty_prompt (vty);
+  vty->cp = 0;
+}
+
+/* Delete a charcter at the current point. */
+static void
+vty_delete_char (struct vty *vty)
+{
+  int i;
+  int size;
+
+  if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
+    return;
+
+  if (vty->length == 0)
+    {
+      vty_down_level (vty);
+      return;
+    }
+
+  if (vty->cp == vty->length)
+    return;			/* completion need here? */
+
+  size = vty->length - vty->cp;
+
+  vty->length--;
+  memmove (&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1);
+  vty->buf[vty->length] = '\0';
+
+  vty_write (vty, &vty->buf[vty->cp], size - 1);
+  vty_write (vty, &telnet_space_char, 1);
+
+  for (i = 0; i < size; i++)
+    vty_write (vty, &telnet_backward_char, 1);
+}
+
+/* Delete a character before the point. */
+static void
+vty_delete_backward_char (struct vty *vty)
+{
+  if (vty->cp == 0)
+    return;
+
+  vty_backward_char (vty);
+  vty_delete_char (vty);
+}
+
+/* Kill rest of line from current point. */
+static void
+vty_kill_line (struct vty *vty)
+{
+  int i;
+  int size;
+
+  size = vty->length - vty->cp;
+  
+  if (size == 0)
+    return;
+
+  for (i = 0; i < size; i++)
+    vty_write (vty, &telnet_space_char, 1);
+  for (i = 0; i < size; i++)
+    vty_write (vty, &telnet_backward_char, 1);
+
+  memset (&vty->buf[vty->cp], 0, size);
+  vty->length = vty->cp;
+}
+
+/* Kill line from the beginning. */
+static void
+vty_kill_line_from_beginning (struct vty *vty)
+{
+  vty_beginning_of_line (vty);
+  vty_kill_line (vty);
+}
+
+/* Delete a word before the point. */
+static void
+vty_forward_kill_word (struct vty *vty)
+{
+  while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
+    vty_delete_char (vty);
+  while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
+    vty_delete_char (vty);
+}
+
+/* Delete a word before the point. */
+static void
+vty_backward_kill_word (struct vty *vty)
+{
+  while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
+    vty_delete_backward_char (vty);
+  while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
+    vty_delete_backward_char (vty);
+}
+
+/* Transpose chars before or at the point. */
+static void
+vty_transpose_chars (struct vty *vty)
+{
+  char c1, c2;
+
+  /* If length is short or point is near by the beginning of line then
+     return. */
+  if (vty->length < 2 || vty->cp < 1)
+    return;
+
+  /* In case of point is located at the end of the line. */
+  if (vty->cp == vty->length)
+    {
+      c1 = vty->buf[vty->cp - 1];
+      c2 = vty->buf[vty->cp - 2];
+
+      vty_backward_char (vty);
+      vty_backward_char (vty);
+      vty_self_insert_overwrite (vty, c1);
+      vty_self_insert_overwrite (vty, c2);
+    }
+  else
+    {
+      c1 = vty->buf[vty->cp];
+      c2 = vty->buf[vty->cp - 1];
+
+      vty_backward_char (vty);
+      vty_self_insert_overwrite (vty, c1);
+      vty_self_insert_overwrite (vty, c2);
+    }
+}
+
+/* Do completion at vty interface. */
+static void
+vty_complete_command (struct vty *vty)
+{
+  int i;
+  int ret;
+  char **matched = NULL;
+  vector vline;
+
+  if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
+    return;
+
+  vline = cmd_make_strvec (vty->buf);
+  if (vline == NULL)
+    return;
+
+  /* In case of 'help \t'. */
+  if (isspace ((int) vty->buf[vty->length - 1]))
+    vector_set (vline, '\0');
+
+  matched = cmd_complete_command (vline, vty, &ret);
+  
+  cmd_free_strvec (vline);
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+  switch (ret)
+    {
+    case CMD_ERR_AMBIGUOUS:
+      vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      break;
+    case CMD_ERR_NO_MATCH:
+      /* vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); */
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      break;
+    case CMD_COMPLETE_FULL_MATCH:
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      vty_backward_pure_word (vty);
+      vty_insert_word_overwrite (vty, matched[0]);
+      vty_self_insert (vty, ' ');
+      XFREE (MTYPE_TMP, matched[0]);
+      break;
+    case CMD_COMPLETE_MATCH:
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      vty_backward_pure_word (vty);
+      vty_insert_word_overwrite (vty, matched[0]);
+      XFREE (MTYPE_TMP, matched[0]);
+      vector_only_index_free (matched);
+      return;
+      break;
+    case CMD_COMPLETE_LIST_MATCH:
+      for (i = 0; matched[i] != NULL; i++)
+	{
+	  if (i != 0 && ((i % 6) == 0))
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  vty_out (vty, "%-10s ", matched[i]);
+	  XFREE (MTYPE_TMP, matched[i]);
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      break;
+    case CMD_ERR_NOTHING_TODO:
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      break;
+    default:
+      break;
+    }
+  if (matched)
+    vector_only_index_free (matched);
+}
+
+void
+vty_describe_fold (struct vty *vty, int cmd_width,
+                 int desc_width, struct desc *desc)
+{
+  char *buf, *cmd, *p;
+  int pos;
+
+  cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd;
+
+  if (desc_width <= 0)
+    {
+      vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, desc->str, VTY_NEWLINE);
+      return;
+    }
+
+  buf = XCALLOC (MTYPE_TMP, strlen (desc->str) + 1);
+
+  for (p = desc->str; strlen (p) > desc_width; p += pos + 1)
+    {
+      for (pos = desc_width; pos > 0; pos--)
+      if (*(p + pos) == ' ')
+        break;
+
+      if (pos == 0)
+      break;
+
+      strncpy (buf, p, pos);
+      buf[pos] = '\0';
+      vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, buf, VTY_NEWLINE);
+
+      cmd = "";
+    }
+
+  vty_out (vty, "  %-*s  %s%s", cmd_width, cmd, p, VTY_NEWLINE);
+
+  XFREE (MTYPE_TMP, buf);
+}
+
+/* Describe matched command function. */
+static void
+vty_describe_command (struct vty *vty)
+{
+  int ret;
+  vector vline;
+  vector describe;
+  int i, width, desc_width;
+  struct desc *desc, *desc_cr = NULL;
+
+  vline = cmd_make_strvec (vty->buf);
+
+  /* In case of '> ?'. */
+  if (vline == NULL)
+    {
+      vline = vector_init (1);
+      vector_set (vline, '\0');
+    }
+  else 
+    if (isspace ((int) vty->buf[vty->length - 1]))
+      vector_set (vline, '\0');
+
+  describe = cmd_describe_command (vline, vty, &ret);
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  /* Ambiguous error. */
+  switch (ret)
+    {
+    case CMD_ERR_AMBIGUOUS:
+      cmd_free_strvec (vline);
+      vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      return;
+      break;
+    case CMD_ERR_NO_MATCH:
+      cmd_free_strvec (vline);
+      vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE);
+      vty_prompt (vty);
+      vty_redraw_line (vty);
+      return;
+      break;
+    }  
+
+  /* Get width of command string. */
+  width = 0;
+  for (i = 0; i < vector_max (describe); i++)
+    if ((desc = vector_slot (describe, i)) != NULL)
+      {
+	int len;
+
+	if (desc->cmd[0] == '\0')
+	  continue;
+
+	len = strlen (desc->cmd);
+	if (desc->cmd[0] == '.')
+	  len--;
+
+	if (width < len)
+	  width = len;
+      }
+
+  /* Get width of description string. */
+  desc_width = vty->width - (width + 6);
+
+  /* Print out description. */
+  for (i = 0; i < vector_max (describe); i++)
+    if ((desc = vector_slot (describe, i)) != NULL)
+      {
+	if (desc->cmd[0] == '\0')
+	  continue;
+	
+	if (strcmp (desc->cmd, "<cr>") == 0)
+	  {
+	    desc_cr = desc;
+	    continue;
+	  }
+
+	if (!desc->str)
+	  vty_out (vty, "  %-s%s",
+		   desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
+		   VTY_NEWLINE);
+	else if (desc_width >= strlen (desc->str))
+	  vty_out (vty, "  %-*s  %s%s", width,
+		   desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
+		   desc->str, VTY_NEWLINE);
+	else
+	  vty_describe_fold (vty, width, desc_width, desc);
+
+#if 0
+	vty_out (vty, "  %-*s %s%s", width
+		 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
+		 desc->str ? desc->str : "", VTY_NEWLINE);
+#endif /* 0 */
+      }
+
+  if ((desc = desc_cr))
+    {
+      if (!desc->str)
+	vty_out (vty, "  %-s%s",
+		 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
+		 VTY_NEWLINE);
+      else if (desc_width >= strlen (desc->str))
+	vty_out (vty, "  %-*s  %s%s", width,
+		 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
+		 desc->str, VTY_NEWLINE);
+      else
+	vty_describe_fold (vty, width, desc_width, desc);
+    }
+
+  cmd_free_strvec (vline);
+  vector_free (describe);
+
+  vty_prompt (vty);
+  vty_redraw_line (vty);
+}
+
+void
+vty_clear_buf (struct vty *vty)
+{
+  memset (vty->buf, 0, vty->max);
+}
+
+/* ^C stop current input and do not add command line to the history. */
+static void
+vty_stop_input (struct vty *vty)
+{
+  vty->cp = vty->length = 0;
+  vty_clear_buf (vty);
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  switch (vty->node)
+    {
+    case VIEW_NODE:
+    case ENABLE_NODE:
+      /* Nothing to do. */
+      break;
+    case CONFIG_NODE:
+    case INTERFACE_NODE:
+    case ZEBRA_NODE:
+    case RIP_NODE:
+    case RIPNG_NODE:
+    case BGP_NODE:
+    case RMAP_NODE:
+    case OSPF_NODE:
+    case OSPF6_NODE:
+    case ISIS_NODE:
+    case KEYCHAIN_NODE:
+    case KEYCHAIN_KEY_NODE:
+    case MASC_NODE:
+    case VTY_NODE:
+      vty_config_unlock (vty);
+      vty->node = ENABLE_NODE;
+      break;
+    default:
+      /* Unknown node, we have to ignore it. */
+      break;
+    }
+  vty_prompt (vty);
+
+  /* Set history pointer to the latest one. */
+  vty->hp = vty->hindex;
+}
+
+/* Add current command line to the history buffer. */
+static void
+vty_hist_add (struct vty *vty)
+{
+  int index;
+
+  if (vty->length == 0)
+    return;
+
+  index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1;
+
+  /* Ignore the same string as previous one. */
+  if (vty->hist[index])
+    if (strcmp (vty->buf, vty->hist[index]) == 0)
+      {
+      vty->hp = vty->hindex;
+      return;
+      }
+
+  /* Insert history entry. */
+  if (vty->hist[vty->hindex])
+    XFREE (MTYPE_VTY_HIST, vty->hist[vty->hindex]);
+  vty->hist[vty->hindex] = XSTRDUP (MTYPE_VTY_HIST, vty->buf);
+
+  /* History index rotation. */
+  vty->hindex++;
+  if (vty->hindex == VTY_MAXHIST)
+    vty->hindex = 0;
+
+  vty->hp = vty->hindex;
+}
+
+/* #define TELNET_OPTION_DEBUG */
+
+/* Get telnet window size. */
+static int
+vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes)
+{
+#ifdef TELNET_OPTION_DEBUG
+  int i;
+
+  for (i = 0; i < nbytes; i++)
+    {
+      switch (buf[i])
+	{
+	case IAC:
+	  vty_out (vty, "IAC ");
+	  break;
+	case WILL:
+	  vty_out (vty, "WILL ");
+	  break;
+	case WONT:
+	  vty_out (vty, "WONT ");
+	  break;
+	case DO:
+	  vty_out (vty, "DO ");
+	  break;
+	case DONT:
+	  vty_out (vty, "DONT ");
+	  break;
+	case SB:
+	  vty_out (vty, "SB ");
+	  break;
+	case SE:
+	  vty_out (vty, "SE ");
+	  break;
+	case TELOPT_ECHO:
+	  vty_out (vty, "TELOPT_ECHO %s", VTY_NEWLINE);
+	  break;
+	case TELOPT_SGA:
+	  vty_out (vty, "TELOPT_SGA %s", VTY_NEWLINE);
+	  break;
+	case TELOPT_NAWS:
+	  vty_out (vty, "TELOPT_NAWS %s", VTY_NEWLINE);
+	  break;
+	default:
+	  vty_out (vty, "%x ", buf[i]);
+	  break;
+	}
+    }
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+#endif /* TELNET_OPTION_DEBUG */
+
+  switch (buf[0])
+    {
+    case SB:
+      buffer_reset(vty->sb_buffer);
+      vty->iac_sb_in_progress = 1;
+      return 0;
+      break;
+    case SE: 
+      {
+	char *buffer = (char *)vty->sb_buffer->head->data;
+	int length = vty->sb_buffer->length;
+
+	if (buffer == NULL)
+	  return 0;
+
+	if (!vty->iac_sb_in_progress)
+	  return 0;
+
+	if (buffer[0] == '\0')
+	  {
+	    vty->iac_sb_in_progress = 0;
+	    return 0;
+	  }
+	switch (buffer[0])
+	  {
+	  case TELOPT_NAWS:
+	    if (length < 5)
+	      break;
+	    vty->width = buffer[2];
+	    vty->height = vty->lines >= 0 ? vty->lines : buffer[4];
+	    break;
+	  }
+	vty->iac_sb_in_progress = 0;
+	return 0;
+	break;
+      }
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Execute current command line. */
+static int
+vty_execute (struct vty *vty)
+{
+  int ret;
+
+  ret = CMD_SUCCESS;
+
+  switch (vty->node)
+    {
+    case AUTH_NODE:
+    case AUTH_ENABLE_NODE:
+      vty_auth (vty, vty->buf);
+      break;
+    default:
+      ret = vty_command (vty, vty->buf);
+      if (vty->type == VTY_TERM)
+	vty_hist_add (vty);
+      break;
+    }
+
+  /* Clear command line buffer. */
+  vty->cp = vty->length = 0;
+  vty_clear_buf (vty);
+
+  if (vty->status != VTY_CLOSE 
+      && vty->status != VTY_START
+      && vty->status != VTY_CONTINUE)
+    vty_prompt (vty);
+
+  return ret;
+}
+
+#define CONTROL(X)  ((X) - '@')
+#define VTY_NORMAL     0
+#define VTY_PRE_ESCAPE 1
+#define VTY_ESCAPE     2
+
+/* Escape character command map. */
+static void
+vty_escape_map (unsigned char c, struct vty *vty)
+{
+  switch (c)
+    {
+    case ('A'):
+      vty_previous_line (vty);
+      break;
+    case ('B'):
+      vty_next_line (vty);
+      break;
+    case ('C'):
+      vty_forward_char (vty);
+      break;
+    case ('D'):
+      vty_backward_char (vty);
+      break;
+    default:
+      break;
+    }
+
+  /* Go back to normal mode. */
+  vty->escape = VTY_NORMAL;
+}
+
+/* Quit print out to the buffer. */
+static void
+vty_buffer_reset (struct vty *vty)
+{
+  buffer_reset (vty->obuf);
+  vty_prompt (vty);
+  vty_redraw_line (vty);
+}
+
+/* Read data via vty socket. */
+static int
+vty_read (struct thread *thread)
+{
+  int i;
+  int ret;
+  int nbytes;
+  unsigned char buf[VTY_READ_BUFSIZ];
+
+  int vty_sock = THREAD_FD (thread);
+  struct vty *vty = THREAD_ARG (thread);
+  vty->t_read = NULL;
+
+  /* Read raw data from socket */
+  nbytes = read (vty->fd, buf, VTY_READ_BUFSIZ);
+  if (nbytes <= 0)
+    vty->status = VTY_CLOSE;
+
+  for (i = 0; i < nbytes; i++) 
+    {
+      if (buf[i] == IAC)
+	{
+	  if (!vty->iac)
+	    {
+	      vty->iac = 1;
+	      continue;
+	    }
+	  else
+	    {
+	      vty->iac = 0;
+	    }
+	}
+      
+      if (vty->iac_sb_in_progress && !vty->iac)
+	{
+	    buffer_putc(vty->sb_buffer, buf[i]);
+	    continue;
+	}
+
+      if (vty->iac)
+	{
+	  /* In case of telnet command */
+	  ret = vty_telnet_option (vty, buf + i, nbytes - i);
+	  vty->iac = 0;
+	  i += ret;
+	  continue;
+	}
+
+      if (vty->status == VTY_MORE)
+	{
+	  switch (buf[i])
+	    {
+	    case CONTROL('C'):
+	    case 'q':
+	    case 'Q':
+	      if (vty->output_func)
+		(*vty->output_func) (vty, 1);
+	      vty_buffer_reset (vty);
+	      break;
+	    default:
+	      if (vty->output_func)
+		(*vty->output_func) (vty, 0);
+	      break;
+	    }
+	  continue;
+	}
+
+      /* Escape character. */
+      if (vty->escape == VTY_ESCAPE)
+	{
+	  vty_escape_map (buf[i], vty);
+	  continue;
+	}
+
+      /* Pre-escape status. */
+      if (vty->escape == VTY_PRE_ESCAPE)
+	{
+	  switch (buf[i])
+	    {
+	    case '[':
+	      vty->escape = VTY_ESCAPE;
+	      break;
+	    case 'b':
+	      vty_backward_word (vty);
+	      vty->escape = VTY_NORMAL;
+	      break;
+	    case 'f':
+	      vty_forward_word (vty);
+	      vty->escape = VTY_NORMAL;
+	      break;
+	    case 'd':
+	      vty_forward_kill_word (vty);
+	      vty->escape = VTY_NORMAL;
+	      break;
+	    case CONTROL('H'):
+	    case 0x7f:
+	      vty_backward_kill_word (vty);
+	      vty->escape = VTY_NORMAL;
+	      break;
+	    default:
+	      vty->escape = VTY_NORMAL;
+	      break;
+	    }
+	  continue;
+	}
+
+      switch (buf[i])
+	{
+	case CONTROL('A'):
+	  vty_beginning_of_line (vty);
+	  break;
+	case CONTROL('B'):
+	  vty_backward_char (vty);
+	  break;
+	case CONTROL('C'):
+	  vty_stop_input (vty);
+	  break;
+	case CONTROL('D'):
+	  vty_delete_char (vty);
+	  break;
+	case CONTROL('E'):
+	  vty_end_of_line (vty);
+	  break;
+	case CONTROL('F'):
+	  vty_forward_char (vty);
+	  break;
+	case CONTROL('H'):
+	case 0x7f:
+	  vty_delete_backward_char (vty);
+	  break;
+	case CONTROL('K'):
+	  vty_kill_line (vty);
+	  break;
+	case CONTROL('N'):
+	  vty_next_line (vty);
+	  break;
+	case CONTROL('P'):
+	  vty_previous_line (vty);
+	  break;
+	case CONTROL('T'):
+	  vty_transpose_chars (vty);
+	  break;
+	case CONTROL('U'):
+	  vty_kill_line_from_beginning (vty);
+	  break;
+	case CONTROL('W'):
+	  vty_backward_kill_word (vty);
+	  break;
+	case CONTROL('Z'):
+	  vty_end_config (vty);
+	  break;
+	case '\n':
+	case '\r':
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	  vty_execute (vty);
+	  break;
+	case '\t':
+	  vty_complete_command (vty);
+	  break;
+	case '?':
+	  if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
+	    vty_self_insert (vty, buf[i]);
+	  else
+	    vty_describe_command (vty);
+	  break;
+	case '\033':
+	  if (i + 1 < nbytes && buf[i + 1] == '[')
+	    {
+	      vty->escape = VTY_ESCAPE;
+	      i++;
+	    }
+	  else
+	    vty->escape = VTY_PRE_ESCAPE;
+	  break;
+	default:
+	  if (buf[i] > 31 && buf[i] < 127)
+	    vty_self_insert (vty, buf[i]);
+	  break;
+	}
+    }
+
+  /* Check status. */
+  if (vty->status == VTY_CLOSE)
+    vty_close (vty);
+  else
+    {
+      vty_event (VTY_WRITE, vty_sock, vty);
+      vty_event (VTY_READ, vty_sock, vty);
+    }
+  return 0;
+}
+
+/* Flush buffer to the vty. */
+static int
+vty_flush (struct thread *thread)
+{
+  int erase;
+  int dont_more;
+  int vty_sock = THREAD_FD (thread);
+  struct vty *vty = THREAD_ARG (thread);
+  vty->t_write = NULL;
+
+  /* Tempolary disable read thread. */
+  if (vty->lines == 0)
+    if (vty->t_read)
+      {
+	thread_cancel (vty->t_read);
+	vty->t_read = NULL;
+      }
+
+  /* Function execution continue. */
+  if (vty->status == VTY_START || vty->status == VTY_CONTINUE)
+    {
+      if (vty->status == VTY_CONTINUE)
+	erase = 1;
+      else
+	erase = 0;
+
+      if (vty->output_func == NULL)
+	dont_more = 1;
+      else
+	dont_more = 0;
+
+      if (vty->lines == 0)
+	{
+	  erase = 0;
+	  dont_more = 1;
+	}
+
+      buffer_flush_vty_all (vty->obuf, vty->fd, erase, dont_more);
+
+      if (vty->status == VTY_CLOSE)
+	{
+	  vty_close (vty);
+	  return 0;
+	}
+
+      if (vty->output_func == NULL)
+	{
+	  vty->status = VTY_NORMAL;
+	  vty_prompt (vty);
+	  vty_event (VTY_WRITE, vty_sock, vty);
+	}
+      else
+	vty->status = VTY_MORE;
+
+      if (vty->lines == 0)
+	{
+	  if (vty->output_func == NULL)
+	    vty_event (VTY_READ, vty_sock, vty);
+	  else
+	    {
+	      if (vty->output_func)
+		(*vty->output_func) (vty, 0);
+	      vty_event (VTY_WRITE, vty_sock, vty);
+	    }
+	}
+    }
+  else
+    {
+      if (vty->status == VTY_MORE)
+	erase = 1;
+      else
+	erase = 0;
+
+      if (vty->lines == 0)
+	buffer_flush_window (vty->obuf, vty->fd, vty->width, 25, 0, 1);
+      else
+	buffer_flush_window (vty->obuf, vty->fd, vty->width,
+			     vty->lines >= 0 ? vty->lines : vty->height,
+			     erase, 0);
+  
+      if (buffer_empty (vty->obuf))
+	{
+	  if (vty->status == VTY_CLOSE)
+	    vty_close (vty);
+	  else
+	    {
+	      vty->status = VTY_NORMAL;
+	  
+	      if (vty->lines == 0)
+		vty_event (VTY_READ, vty_sock, vty);
+	    }
+	}
+      else
+	{
+	  vty->status = VTY_MORE;
+
+	  if (vty->lines == 0)
+	    vty_event (VTY_WRITE, vty_sock, vty);
+	}
+    }
+
+  return 0;
+}
+
+/* Create new vty structure. */
+struct vty *
+vty_create (int vty_sock, union sockunion *su)
+{
+  struct vty *vty;
+
+  /* Allocate new vty structure and set up default values. */
+  vty = vty_new ();
+  vty->fd = vty_sock;
+  vty->type = VTY_TERM;
+  vty->address = sockunion_su2str (su);
+  if (no_password_check)
+    {
+      if (host.advanced)
+	vty->node = ENABLE_NODE;
+      else
+	vty->node = VIEW_NODE;
+    }
+  else
+    vty->node = AUTH_NODE;
+  vty->fail = 0;
+  vty->cp = 0;
+  vty_clear_buf (vty);
+  vty->length = 0;
+  memset (vty->hist, 0, sizeof (vty->hist));
+  vty->hp = 0;
+  vty->hindex = 0;
+  vector_set_index (vtyvec, vty_sock, vty);
+  vty->status = VTY_NORMAL;
+  vty->v_timeout = vty_timeout_val;
+  if (host.lines >= 0)
+    vty->lines = host.lines;
+  else
+    vty->lines = -1;
+  vty->iac = 0;
+  vty->iac_sb_in_progress = 0;
+  vty->sb_buffer = buffer_new (1024);
+
+  if (! no_password_check)
+    {
+      /* Vty is not available if password isn't set. */
+      if (host.password == NULL && host.password_encrypt == NULL)
+	{
+	  vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE);
+	  vty->status = VTY_CLOSE;
+	  vty_close (vty);
+	  return NULL;
+	}
+    }
+
+  /* Say hello to the world. */
+  vty_hello (vty);
+  if (! no_password_check)
+    vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+
+  /* Setting up terminal. */
+  vty_will_echo (vty);
+  vty_will_suppress_go_ahead (vty);
+
+  vty_dont_linemode (vty);
+  vty_do_window_size (vty);
+  /* vty_dont_lflow_ahead (vty); */
+
+  vty_prompt (vty);
+
+  /* Add read/write thread. */
+  vty_event (VTY_WRITE, vty_sock, vty);
+  vty_event (VTY_READ, vty_sock, vty);
+
+  return vty;
+}
+
+/* Accept connection from the network. */
+static int
+vty_accept (struct thread *thread)
+{
+  int vty_sock;
+  struct vty *vty;
+  union sockunion su;
+  int ret;
+  unsigned int on;
+  int accept_sock;
+  struct prefix *p = NULL;
+  struct access_list *acl = NULL;
+
+  accept_sock = THREAD_FD (thread);
+
+  /* We continue hearing vty socket. */
+  vty_event (VTY_SERV, accept_sock, NULL);
+
+  memset (&su, 0, sizeof (union sockunion));
+
+  /* We can handle IPv4 or IPv6 socket. */
+  vty_sock = sockunion_accept (accept_sock, &su);
+  if (vty_sock < 0)
+    {
+      zlog_warn ("can't accept vty socket : %s", strerror (errno));
+      return -1;
+    }
+
+  p = sockunion2hostprefix (&su);
+
+  /* VTY's accesslist apply. */
+  if (p->family == AF_INET && vty_accesslist_name)
+    {
+      if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) &&
+	  (access_list_apply (acl, p) == FILTER_DENY))
+	{
+	  char *buf;
+	  zlog (NULL, LOG_INFO, "Vty connection refused from %s",
+		(buf = sockunion_su2str (&su)));
+	  free (buf);
+	  close (vty_sock);
+	  
+	  /* continue accepting connections */
+	  vty_event (VTY_SERV, accept_sock, NULL);
+	  
+	  prefix_free (p);
+
+	  return 0;
+	}
+    }
+
+#ifdef HAVE_IPV6
+  /* VTY's ipv6 accesslist apply. */
+  if (p->family == AF_INET6 && vty_ipv6_accesslist_name)
+    {
+      if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) &&
+	  (access_list_apply (acl, p) == FILTER_DENY))
+	{
+	  char *buf;
+	  zlog (NULL, LOG_INFO, "Vty connection refused from %s",
+		(buf = sockunion_su2str (&su)));
+	  free (buf);
+	  close (vty_sock);
+	  
+	  /* continue accepting connections */
+	  vty_event (VTY_SERV, accept_sock, NULL);
+	  
+	  prefix_free (p);
+
+	  return 0;
+	}
+    }
+#endif /* HAVE_IPV6 */
+  
+  prefix_free (p);
+
+  on = 1;
+  ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY, 
+		    (char *) &on, sizeof (on));
+  if (ret < 0)
+    zlog (NULL, LOG_INFO, "can't set sockopt to vty_sock : %s", 
+	  strerror (errno));
+
+  vty = vty_create (vty_sock, &su);
+
+  return 0;
+}
+
+#if defined(HAVE_IPV6) && !defined(NRL)
+void
+vty_serv_sock_addrinfo (const char *hostname, unsigned short port)
+{
+  int ret;
+  struct addrinfo req;
+  struct addrinfo *ainfo;
+  struct addrinfo *ainfo_save;
+  int sock;
+  char port_str[BUFSIZ];
+
+  memset (&req, 0, sizeof (struct addrinfo));
+  req.ai_flags = AI_PASSIVE;
+  req.ai_family = AF_UNSPEC;
+  req.ai_socktype = SOCK_STREAM;
+  sprintf (port_str, "%d", port);
+  port_str[sizeof (port_str) - 1] = '\0';
+
+  ret = getaddrinfo (hostname, port_str, &req, &ainfo);
+
+  if (ret != 0)
+    {
+      fprintf (stderr, "getaddrinfo failed: %s\n", gai_strerror (ret));
+      exit (1);
+    }
+
+  ainfo_save = ainfo;
+
+  do
+    {
+      if (ainfo->ai_family != AF_INET
+#ifdef HAVE_IPV6
+	  && ainfo->ai_family != AF_INET6
+#endif /* HAVE_IPV6 */
+	  )
+	continue;
+
+      sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
+      if (sock < 0)
+	continue;
+
+      sockopt_reuseaddr (sock);
+      sockopt_reuseport (sock);
+
+      ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
+      if (ret < 0)
+	{
+	  close (sock);	/* Avoid sd leak. */
+	continue;
+	}
+
+      ret = listen (sock, 3);
+      if (ret < 0) 
+	{
+	  close (sock);	/* Avoid sd leak. */
+	continue;
+	}
+
+      vty_event (VTY_SERV, sock, NULL);
+    }
+  while ((ainfo = ainfo->ai_next) != NULL);
+
+  freeaddrinfo (ainfo_save);
+}
+#endif /* HAVE_IPV6 && ! NRL */
+
+/* Make vty server socket. */
+void
+vty_serv_sock_family (unsigned short port, int family)
+{
+  int ret;
+  union sockunion su;
+  int accept_sock;
+
+  memset (&su, 0, sizeof (union sockunion));
+  su.sa.sa_family = family;
+
+  /* Make new socket. */
+  accept_sock = sockunion_stream_socket (&su);
+  if (accept_sock < 0)
+    return;
+
+  /* This is server, so reuse address. */
+  sockopt_reuseaddr (accept_sock);
+  sockopt_reuseport (accept_sock);
+
+  /* Bind socket to universal address and given port. */
+  ret = sockunion_bind (accept_sock, &su, port, NULL);
+  if (ret < 0)
+    {
+      close (accept_sock);	/* Avoid sd leak. */
+      return;
+    }
+
+  /* Listen socket under queue 3. */
+  ret = listen (accept_sock, 3);
+  if (ret < 0) 
+    {
+      zlog (NULL, LOG_WARNING, "can't listen socket");
+      close (accept_sock);	/* Avoid sd leak. */
+      return;
+    }
+
+  /* Add vty server event. */
+  vty_event (VTY_SERV, accept_sock, NULL);
+}
+
+#ifdef VTYSH
+/* For sockaddr_un. */
+#include <sys/un.h>
+
+/* VTY shell UNIX domain socket. */
+void
+vty_serv_un (char *path)
+{
+  int ret;
+  int sock, len;
+  struct sockaddr_un serv;
+  mode_t old_mask;
+
+  /* First of all, unlink existing socket */
+  unlink (path);
+
+  /* Set umask */
+  old_mask = umask (0077);
+
+  /* Make UNIX domain socket. */
+  sock = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (sock < 0)
+    {
+      perror ("sock");
+      return;
+    }
+
+  /* Make server socket. */
+  memset (&serv, 0, sizeof (struct sockaddr_un));
+  serv.sun_family = AF_UNIX;
+  strncpy (serv.sun_path, path, strlen (path));
+#ifdef HAVE_SUN_LEN
+  len = serv.sun_len = SUN_LEN(&serv);
+#else
+  len = sizeof (serv.sun_family) + strlen (serv.sun_path);
+#endif /* HAVE_SUN_LEN */
+
+  ret = bind (sock, (struct sockaddr *) &serv, len);
+  if (ret < 0)
+    {
+      perror ("bind");
+      close (sock);	/* Avoid sd leak. */
+      return;
+    }
+
+  ret = listen (sock, 5);
+  if (ret < 0)
+    {
+      perror ("listen");
+      close (sock);	/* Avoid sd leak. */
+      return;
+    }
+
+  umask (old_mask);
+
+  vty_event (VTYSH_SERV, sock, NULL);
+}
+
+/* #define VTYSH_DEBUG 1 */
+
+static int
+vtysh_accept (struct thread *thread)
+{
+  int accept_sock;
+  int sock;
+  int client_len;
+  struct sockaddr_un client;
+  struct vty *vty;
+  
+  accept_sock = THREAD_FD (thread);
+
+  vty_event (VTYSH_SERV, accept_sock, NULL);
+
+  memset (&client, 0, sizeof (struct sockaddr_un));
+  client_len = sizeof (struct sockaddr_un);
+
+  sock = accept (accept_sock, (struct sockaddr *) &client, &client_len);
+
+  if (sock < 0)
+    {
+      zlog_warn ("can't accept vty socket : %s", strerror (errno));
+      return -1;
+    }
+
+#ifdef VTYSH_DEBUG
+  printf ("VTY shell accept\n");
+#endif /* VTYSH_DEBUG */
+
+  vty = vty_new ();
+  vty->fd = sock;
+  vty->type = VTY_SHELL_SERV;
+  vty->node = VIEW_NODE;
+
+  vty_event (VTYSH_READ, sock, vty);
+
+  return 0;
+}
+
+static int
+vtysh_read (struct thread *thread)
+{
+  int ret;
+  int sock;
+  int nbytes;
+  struct vty *vty;
+  unsigned char buf[VTY_READ_BUFSIZ];
+  u_char header[4] = {0, 0, 0, 0};
+
+  sock = THREAD_FD (thread);
+  vty = THREAD_ARG (thread);
+  vty->t_read = NULL;
+
+  nbytes = read (sock, buf, VTY_READ_BUFSIZ);
+  if (nbytes <= 0)
+    {
+      vty_close (vty);
+#ifdef VTYSH_DEBUG
+      printf ("close vtysh\n");
+#endif /* VTYSH_DEBUG */
+      return 0;
+    }
+
+#ifdef VTYSH_DEBUG
+  printf ("line: %s\n", buf);
+#endif /* VTYSH_DEBUG */
+
+  vty_ensure (vty, nbytes);
+  memcpy (vty->buf, buf, nbytes);
+  
+  /* Pass this line to parser. */
+  ret = vty_execute (vty);
+
+  vty_clear_buf (vty);
+
+  /* Return result. */
+#ifdef VTYSH_DEBUG
+  printf ("result: %d\n", ret);
+  printf ("vtysh node: %d\n", vty->node);
+#endif /* VTYSH_DEBUG */
+
+  header[3] = ret;
+  write (vty->fd, header, 4);
+
+  vty_event (VTYSH_READ, sock, vty);
+
+  return 0;
+}
+#endif /* VTYSH */
+
+/* Determine address family to bind. */
+void
+vty_serv_sock (const char *hostname, unsigned short port, char *path)
+{
+  /* If port is set to 0, do not listen on TCP/IP at all! */
+  if (port)
+    {
+
+#ifdef HAVE_IPV6
+#ifdef NRL
+      vty_serv_sock_family (port, AF_INET);
+      vty_serv_sock_family (port, AF_INET6);
+#else /* ! NRL */
+      vty_serv_sock_addrinfo (hostname, port);
+#endif /* NRL*/
+#else /* ! HAVE_IPV6 */
+      vty_serv_sock_family (port, AF_INET);
+#endif /* HAVE_IPV6 */
+    }
+
+#ifdef VTYSH
+  vty_serv_un (path);
+#endif /* VTYSH */
+}
+
+/* Close vty interface. */
+void
+vty_close (struct vty *vty)
+{
+  int i;
+
+  /* Cancel threads.*/
+  if (vty->t_read)
+    thread_cancel (vty->t_read);
+  if (vty->t_write)
+    thread_cancel (vty->t_write);
+  if (vty->t_timeout)
+    thread_cancel (vty->t_timeout);
+  if (vty->t_output)
+    thread_cancel (vty->t_output);
+
+  /* Flush buffer. */
+  if (! buffer_empty (vty->obuf))
+    buffer_flush_all (vty->obuf, vty->fd);
+
+  /* Free input buffer. */
+  buffer_free (vty->obuf);
+
+  /* Free SB buffer. */
+  if (vty->sb_buffer)
+    buffer_free (vty->sb_buffer);
+
+  /* Free command history. */
+  for (i = 0; i < VTY_MAXHIST; i++)
+    if (vty->hist[i])
+      XFREE (MTYPE_VTY_HIST, vty->hist[i]);
+
+  /* Unset vector. */
+  vector_unset (vtyvec, vty->fd);
+
+  /* Close socket. */
+  if (vty->fd > 0)
+    close (vty->fd);
+
+  if (vty->address)
+    XFREE (0, vty->address);
+  if (vty->buf)
+    XFREE (MTYPE_VTY, vty->buf);
+
+  /* Check configure. */
+  vty_config_unlock (vty);
+
+  /* OK free vty. */
+  XFREE (MTYPE_VTY, vty);
+}
+
+/* When time out occur output message then close connection. */
+static int
+vty_timeout (struct thread *thread)
+{
+  struct vty *vty;
+
+  vty = THREAD_ARG (thread);
+  vty->t_timeout = NULL;
+  vty->v_timeout = 0;
+
+  /* Clear buffer*/
+  buffer_reset (vty->obuf);
+  vty_out (vty, "%sVty connection is timed out.%s", VTY_NEWLINE, VTY_NEWLINE);
+
+  /* Close connection. */
+  vty->status = VTY_CLOSE;
+  vty_close (vty);
+
+  return 0;
+}
+
+/* Read up configuration file from file_name. */
+static void
+vty_read_file (FILE *confp)
+{
+  int ret;
+  struct vty *vty;
+
+  vty = vty_new ();
+  vty->fd = 0;			/* stdout */
+  vty->type = VTY_TERM;
+  vty->node = CONFIG_NODE;
+  
+  /* Execute configuration file */
+  ret = config_from_file (vty, confp);
+
+  if (ret != CMD_SUCCESS) 
+    {
+      switch (ret)
+	{
+	case CMD_ERR_AMBIGUOUS:
+	  fprintf (stderr, "Ambiguous command.\n");
+	  break;
+	case CMD_ERR_NO_MATCH:
+	  fprintf (stderr, "There is no such command.\n");
+	  break;
+	}
+      fprintf (stderr, "Error occured during reading below line.\n%s\n", 
+	       vty->buf);
+      vty_close (vty);
+      exit (1);
+    }
+
+  vty_close (vty);
+}
+
+FILE *
+vty_use_backup_config (char *fullpath)
+{
+  char *fullpath_sav, *fullpath_tmp;
+  FILE *ret = NULL;
+  struct stat buf;
+  int tmp, sav;
+  int c;
+  char buffer[512];
+  
+  fullpath_sav = malloc (strlen (fullpath) + strlen (CONF_BACKUP_EXT) + 1);
+  strcpy (fullpath_sav, fullpath);
+  strcat (fullpath_sav, CONF_BACKUP_EXT);
+  if (stat (fullpath_sav, &buf) == -1)
+    {
+      free (fullpath_sav);
+      return NULL;
+    }
+
+  fullpath_tmp = malloc (strlen (fullpath) + 8);
+  sprintf (fullpath_tmp, "%s.XXXXXX", fullpath);
+  
+  /* Open file to configuration write. */
+  tmp = mkstemp (fullpath_tmp);
+  if (tmp < 0)
+    {
+      free (fullpath_sav);
+      free (fullpath_tmp);
+      return NULL;
+    }
+
+  sav = open (fullpath_sav, O_RDONLY);
+  if (sav < 0)
+    {
+      free (fullpath_sav);
+      free (fullpath_tmp);
+      unlink (fullpath_tmp);
+      return NULL;
+    }
+  
+  while((c = read (sav, buffer, 512)) > 0)
+    write (tmp, buffer, c);
+  
+  close (sav);
+  close (tmp);
+  
+  if (link (fullpath_tmp, fullpath) == 0)
+    ret = fopen (fullpath, "r");
+
+  unlink (fullpath_tmp);
+  
+  free (fullpath_sav);
+  free (fullpath_tmp);
+  return fopen (fullpath, "r");
+}
+
+/* Read up configuration file from file_name. */
+void
+vty_read_config (char *config_file,
+		 char *config_current_dir,
+		 char *config_default_dir)
+{
+  char *cwd;
+  FILE *confp = NULL;
+  char *fullpath;
+
+  /* If -f flag specified. */
+  if (config_file != NULL)
+    {
+      if (! IS_DIRECTORY_SEP (config_file[0]))
+	{
+	  cwd = getcwd (NULL, MAXPATHLEN);
+	  fullpath = XMALLOC (MTYPE_TMP, 
+			      strlen (cwd) + strlen (config_file) + 2);
+	  sprintf (fullpath, "%s/%s", cwd, config_file);
+	}
+      else
+	fullpath = config_file;
+
+      confp = fopen (fullpath, "r");
+
+      if (confp == NULL)
+	{
+	  confp = vty_use_backup_config (fullpath);
+	  if (confp)
+	    fprintf (stderr, "WARNING: using backup configuration file!\n");
+	  else
+	    {
+	      fprintf (stderr, "can't open configuration file [%s]\n", 
+		       config_file);
+	      exit(1);
+	    }
+	}
+    }
+  else
+    {
+      /* Relative path configuration file open. */
+      if (config_current_dir)
+	{
+	  confp = fopen (config_current_dir, "r");
+	  if (confp == NULL)
+	    {
+	      confp = vty_use_backup_config (config_current_dir);
+	      if (confp)
+		fprintf (stderr, "WARNING: using backup configuration file!\n");
+	    }
+	}
+
+      /* If there is no relative path exists, open system default file. */
+      if (confp == NULL)
+	{
+#ifdef VTYSH
+	  int ret;
+	  struct stat conf_stat;
+
+	  /* !!!!PLEASE LEAVE!!!!
+	     This is NEEDED for use with vtysh -b, or else you can get
+	     a real configuration food fight with a lot garbage in the
+	     merged configuration file it creates coming from the per
+	     daemon configuration files.  This also allows the daemons
+	     to start if there default configuration file is not
+	     present or ignore them, as needed when using vtysh -b to
+	     configure the daemons at boot - MAG */
+
+	  /* Stat for vtysh Zebra.conf, if found startup and wait for
+	     boot configuration */
+
+	  if ( strstr(config_default_dir, "vtysh") == NULL)
+	    {
+	      ret = stat (integrate_default, &conf_stat);
+	      if (ret >= 0)
+		{
+		  return;
+		}
+	    }
+#endif /* VTYSH */
+
+	  confp = fopen (config_default_dir, "r");
+	  if (confp == NULL)
+	    {
+	      confp = vty_use_backup_config (config_default_dir);
+	      if (confp)
+		{
+		  fprintf (stderr, "WARNING: using backup configuration file!\n");
+		  fullpath = config_default_dir;
+		}
+	      else
+		{
+		  fprintf (stderr, "can't open configuration file [%s]\n",
+			   config_default_dir);
+		  exit (1);
+		}
+	    }      
+	  else
+	    fullpath = config_default_dir;
+	}
+      else
+	{
+	  /* Rleative path configuration file. */
+	  cwd = getcwd (NULL, MAXPATHLEN);
+	  fullpath = XMALLOC (MTYPE_TMP, 
+			      strlen (cwd) + strlen (config_current_dir) + 2);
+	  sprintf (fullpath, "%s/%s", cwd, config_current_dir);
+	}  
+    }  
+  vty_read_file (confp);
+
+  fclose (confp);
+
+  host_config_set (fullpath);
+}
+
+/* Small utility function which output log to the VTY. */
+void
+vty_log (const char *proto_str, const char *format, va_list va)
+{
+  int i;
+  struct vty *vty;
+
+  for (i = 0; i < vector_max (vtyvec); i++)
+    if ((vty = vector_slot (vtyvec, i)) != NULL)
+      if (vty->monitor)
+	vty_log_out (vty, proto_str, format, va);
+}
+
+int
+vty_config_lock (struct vty *vty)
+{
+  if (vty_config == 0)
+    {
+      vty->config = 1;
+      vty_config = 1;
+    }
+  return vty->config;
+}
+
+int
+vty_config_unlock (struct vty *vty)
+{
+  if (vty_config == 1 && vty->config == 1)
+    {
+      vty->config = 0;
+      vty_config = 0;
+    }
+  return vty->config;
+}
+
+/* Master of the threads. */
+extern struct thread_master *master;
+/* struct thread_master *master; */
+
+static void
+vty_event (enum event event, int sock, struct vty *vty)
+{
+  struct thread *vty_serv_thread;
+
+  switch (event)
+    {
+    case VTY_SERV:
+      vty_serv_thread = thread_add_read (master, vty_accept, vty, sock);
+      vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
+      break;
+#ifdef VTYSH
+    case VTYSH_SERV:
+      thread_add_read (master, vtysh_accept, vty, sock);
+      break;
+    case VTYSH_READ:
+      thread_add_read (master, vtysh_read, vty, sock);
+      break;
+#endif /* VTYSH */
+    case VTY_READ:
+      vty->t_read = thread_add_read (master, vty_read, vty, sock);
+
+      /* Time out treatment. */
+      if (vty->v_timeout)
+	{
+	  if (vty->t_timeout)
+	    thread_cancel (vty->t_timeout);
+	  vty->t_timeout = 
+	    thread_add_timer (master, vty_timeout, vty, vty->v_timeout);
+	}
+      break;
+    case VTY_WRITE:
+      if (! vty->t_write)
+	vty->t_write = thread_add_write (master, vty_flush, vty, sock);
+      break;
+    case VTY_TIMEOUT_RESET:
+      if (vty->t_timeout)
+	{
+	  thread_cancel (vty->t_timeout);
+	  vty->t_timeout = NULL;
+	}
+      if (vty->v_timeout)
+	{
+	  vty->t_timeout = 
+	    thread_add_timer (master, vty_timeout, vty, vty->v_timeout);
+	}
+      break;
+    }
+}
+
+DEFUN (config_who,
+       config_who_cmd,
+       "who",
+       "Display who is on vty\n")
+{
+  int i;
+  struct vty *v;
+
+  for (i = 0; i < vector_max (vtyvec); i++)
+    if ((v = vector_slot (vtyvec, i)) != NULL)
+      vty_out (vty, "%svty[%d] connected from %s.%s",
+	       v->config ? "*" : " ",
+	       i, v->address, VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
+
+/* Move to vty configuration mode. */
+DEFUN (line_vty,
+       line_vty_cmd,
+       "line vty",
+       "Configure a terminal line\n"
+       "Virtual terminal\n")
+{
+  vty->node = VTY_NODE;
+  return CMD_SUCCESS;
+}
+
+/* Set time out value. */
+int
+exec_timeout (struct vty *vty, char *min_str, char *sec_str)
+{
+  unsigned long timeout = 0;
+
+  /* min_str and sec_str are already checked by parser.  So it must be
+     all digit string. */
+  if (min_str)
+    {
+      timeout = strtol (min_str, NULL, 10);
+      timeout *= 60;
+    }
+  if (sec_str)
+    timeout += strtol (sec_str, NULL, 10);
+
+  vty_timeout_val = timeout;
+  vty->v_timeout = timeout;
+  vty_event (VTY_TIMEOUT_RESET, 0, vty);
+
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (exec_timeout_min,
+       exec_timeout_min_cmd,
+       "exec-timeout <0-35791>",
+       "Set timeout value\n"
+       "Timeout value in minutes\n")
+{
+  return exec_timeout (vty, argv[0], NULL);
+}
+
+DEFUN (exec_timeout_sec,
+       exec_timeout_sec_cmd,
+       "exec-timeout <0-35791> <0-2147483>",
+       "Set the EXEC timeout\n"
+       "Timeout in minutes\n"
+       "Timeout in seconds\n")
+{
+  return exec_timeout (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_exec_timeout,
+       no_exec_timeout_cmd,
+       "no exec-timeout",
+       NO_STR
+       "Set the EXEC timeout\n")
+{
+  return exec_timeout (vty, NULL, NULL);
+}
+
+/* Set vty access class. */
+DEFUN (vty_access_class,
+       vty_access_class_cmd,
+       "access-class WORD",
+       "Filter connections based on an IP access list\n"
+       "IP access list\n")
+{
+  if (vty_accesslist_name)
+    XFREE(MTYPE_VTY, vty_accesslist_name);
+
+  vty_accesslist_name = XSTRDUP(MTYPE_VTY, argv[0]);
+
+  return CMD_SUCCESS;
+}
+
+/* Clear vty access class. */
+DEFUN (no_vty_access_class,
+       no_vty_access_class_cmd,
+       "no access-class [WORD]",
+       NO_STR
+       "Filter connections based on an IP access list\n"
+       "IP access list\n")
+{
+  if (! vty_accesslist_name || (argc && strcmp(vty_accesslist_name, argv[0])))
+    {
+      vty_out (vty, "Access-class is not currently applied to vty%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  XFREE(MTYPE_VTY, vty_accesslist_name);
+
+  vty_accesslist_name = NULL;
+
+  return CMD_SUCCESS;
+}
+
+#ifdef HAVE_IPV6
+/* Set vty access class. */
+DEFUN (vty_ipv6_access_class,
+       vty_ipv6_access_class_cmd,
+       "ipv6 access-class WORD",
+       IPV6_STR
+       "Filter connections based on an IP access list\n"
+       "IPv6 access list\n")
+{
+  if (vty_ipv6_accesslist_name)
+    XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
+
+  vty_ipv6_accesslist_name = XSTRDUP(MTYPE_VTY, argv[0]);
+
+  return CMD_SUCCESS;
+}
+
+/* Clear vty access class. */
+DEFUN (no_vty_ipv6_access_class,
+       no_vty_ipv6_access_class_cmd,
+       "no ipv6 access-class [WORD]",
+       NO_STR
+       IPV6_STR
+       "Filter connections based on an IP access list\n"
+       "IPv6 access list\n")
+{
+  if (! vty_ipv6_accesslist_name ||
+      (argc && strcmp(vty_ipv6_accesslist_name, argv[0])))
+    {
+      vty_out (vty, "IPv6 access-class is not currently applied to vty%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
+
+  vty_ipv6_accesslist_name = NULL;
+
+  return CMD_SUCCESS;
+}
+#endif /* HAVE_IPV6 */
+
+/* vty login. */
+DEFUN (vty_login,
+       vty_login_cmd,
+       "login",
+       "Enable password checking\n")
+{
+  no_password_check = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_vty_login,
+       no_vty_login_cmd,
+       "no login",
+       NO_STR
+       "Enable password checking\n")
+{
+  no_password_check = 1;
+  return CMD_SUCCESS;
+}
+
+DEFUN (service_advanced_vty,
+       service_advanced_vty_cmd,
+       "service advanced-vty",
+       "Set up miscellaneous service\n"
+       "Enable advanced mode vty interface\n")
+{
+  host.advanced = 1;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_service_advanced_vty,
+       no_service_advanced_vty_cmd,
+       "no service advanced-vty",
+       NO_STR
+       "Set up miscellaneous service\n"
+       "Enable advanced mode vty interface\n")
+{
+  host.advanced = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (terminal_monitor,
+       terminal_monitor_cmd,
+       "terminal monitor",
+       "Set terminal line parameters\n"
+       "Copy debug output to the current terminal line\n")
+{
+  vty->monitor = 1;
+  return CMD_SUCCESS;
+}
+
+DEFUN (terminal_no_monitor,
+       terminal_no_monitor_cmd,
+       "terminal no monitor",
+       "Set terminal line parameters\n"
+       NO_STR
+       "Copy debug output to the current terminal line\n")
+{
+  vty->monitor = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_history,
+       show_history_cmd,
+       "show history",
+       SHOW_STR
+       "Display the session command history\n")
+{
+  int index;
+
+  for (index = vty->hindex + 1; index != vty->hindex;)
+    {
+      if (index == VTY_MAXHIST)
+	{
+	  index = 0;
+	  continue;
+	}
+
+      if (vty->hist[index] != NULL)
+	vty_out (vty, "  %s%s", vty->hist[index], VTY_NEWLINE);
+
+      index++;
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* Display current configuration. */
+int
+vty_config_write (struct vty *vty)
+{
+  vty_out (vty, "line vty%s", VTY_NEWLINE);
+
+  if (vty_accesslist_name)
+    vty_out (vty, " access-class %s%s",
+	     vty_accesslist_name, VTY_NEWLINE);
+
+  if (vty_ipv6_accesslist_name)
+    vty_out (vty, " ipv6 access-class %s%s",
+	     vty_ipv6_accesslist_name, VTY_NEWLINE);
+
+  /* exec-timeout */
+  if (vty_timeout_val != VTY_TIMEOUT_DEFAULT)
+    vty_out (vty, " exec-timeout %ld %ld%s", 
+	     vty_timeout_val / 60,
+	     vty_timeout_val % 60, VTY_NEWLINE);
+
+  /* login */
+  if (no_password_check)
+    vty_out (vty, " no login%s", VTY_NEWLINE);
+
+  vty_out (vty, "!%s", VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+struct cmd_node vty_node =
+{
+  VTY_NODE,
+  "%s(config-line)# ",
+};
+
+/* Reset all VTY status. */
+void
+vty_reset ()
+{
+  int i;
+  struct vty *vty;
+  struct thread *vty_serv_thread;
+
+  for (i = 0; i < vector_max (vtyvec); i++)
+    if ((vty = vector_slot (vtyvec, i)) != NULL)
+      {
+	buffer_reset (vty->obuf);
+	vty->status = VTY_CLOSE;
+	vty_close (vty);
+      }
+
+  for (i = 0; i < vector_max (Vvty_serv_thread); i++)
+    if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL)
+      {
+	thread_cancel (vty_serv_thread);
+	vector_slot (Vvty_serv_thread, i) = NULL;
+        close (i);
+      }
+
+  vty_timeout_val = VTY_TIMEOUT_DEFAULT;
+
+  if (vty_accesslist_name)
+    {
+      XFREE(MTYPE_VTY, vty_accesslist_name);
+      vty_accesslist_name = NULL;
+    }
+
+  if (vty_ipv6_accesslist_name)
+    {
+      XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
+      vty_ipv6_accesslist_name = NULL;
+    }
+}
+
+/* for ospf6d easy temprary reload function */
+/* vty_reset + close accept socket */
+void
+vty_finish ()
+{
+  int i;
+  struct vty *vty;
+  struct thread *vty_serv_thread;
+
+  for (i = 0; i < vector_max (vtyvec); i++)
+    if ((vty = vector_slot (vtyvec, i)) != NULL)
+      {
+	buffer_reset (vty->obuf);
+	vty->status = VTY_CLOSE;
+	vty_close (vty);
+      }
+
+  for (i = 0; i < vector_max (Vvty_serv_thread); i++)
+    if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL)
+      {
+	thread_cancel (vty_serv_thread);
+	vector_slot (Vvty_serv_thread, i) = NULL;
+        close (i);
+      }
+
+  vty_timeout_val = VTY_TIMEOUT_DEFAULT;
+
+  if (vty_accesslist_name)
+    {
+      XFREE(MTYPE_VTY, vty_accesslist_name);
+      vty_accesslist_name = NULL;
+    }
+
+  if (vty_ipv6_accesslist_name)
+    {
+      XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
+      vty_ipv6_accesslist_name = NULL;
+    }
+}
+
+void
+vty_save_cwd ()
+{
+  char *cwd;
+
+  cwd = getcwd (NULL, MAXPATHLEN);
+
+  vty_cwd = XMALLOC (MTYPE_TMP, strlen (cwd) + 1);
+  strcpy (vty_cwd, cwd);
+}
+
+char *
+vty_get_cwd ()
+{
+  return vty_cwd;
+}
+
+int
+vty_shell (struct vty *vty)
+{
+  return vty->type == VTY_SHELL ? 1 : 0;
+}
+
+int
+vty_shell_serv (struct vty *vty)
+{
+  return vty->type == VTY_SHELL_SERV ? 1 : 0;
+}
+
+void
+vty_init_vtysh ()
+{
+  vtyvec = vector_init (VECTOR_MIN_SIZE);
+}
+
+/* Install vty's own commands like `who' command. */
+void
+vty_init ()
+{
+  /* For further configuration read, preserve current directory. */
+  vty_save_cwd ();
+
+  vtyvec = vector_init (VECTOR_MIN_SIZE);
+
+  /* Initilize server thread vector. */
+  Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE);
+
+  /* Install bgp top node. */
+  install_node (&vty_node, vty_config_write);
+
+  install_element (VIEW_NODE, &config_who_cmd);
+  install_element (VIEW_NODE, &show_history_cmd);
+  install_element (ENABLE_NODE, &config_who_cmd);
+  install_element (CONFIG_NODE, &line_vty_cmd);
+  install_element (CONFIG_NODE, &service_advanced_vty_cmd);
+  install_element (CONFIG_NODE, &no_service_advanced_vty_cmd);
+  install_element (CONFIG_NODE, &show_history_cmd);
+  install_element (ENABLE_NODE, &terminal_monitor_cmd);
+  install_element (ENABLE_NODE, &terminal_no_monitor_cmd);
+  install_element (ENABLE_NODE, &show_history_cmd);
+
+  install_default (VTY_NODE);
+  install_element (VTY_NODE, &exec_timeout_min_cmd);
+  install_element (VTY_NODE, &exec_timeout_sec_cmd);
+  install_element (VTY_NODE, &no_exec_timeout_cmd);
+  install_element (VTY_NODE, &vty_access_class_cmd);
+  install_element (VTY_NODE, &no_vty_access_class_cmd);
+  install_element (VTY_NODE, &vty_login_cmd);
+  install_element (VTY_NODE, &no_vty_login_cmd);
+#ifdef HAVE_IPV6
+  install_element (VTY_NODE, &vty_ipv6_access_class_cmd);
+  install_element (VTY_NODE, &no_vty_ipv6_access_class_cmd);
+#endif /* HAVE_IPV6 */
+}
diff --git a/isisd/modified/zebra.h b/isisd/modified/zebra.h
new file mode 100644
index 0000000..989e882
--- /dev/null
+++ b/isisd/modified/zebra.h
@@ -0,0 +1,313 @@
+/* Zebra common header.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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.  */
+
+#ifndef _ZEBRA_H
+#define _ZEBRA_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef SUNOS_5
+#define _XPG4_2
+#define __EXTENSIONS__
+#endif /* SUNOS_5 */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif /* HAVE_STROPTS_H */
+#include <sys/fcntl.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif /* HAVE_SYS_SYSCTL_H */
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_CONF_H
+#include <sys/conf.h>
+#endif /* HAVE_SYS_CONF_H */
+#ifdef HAVE_SYS_KSYM_H
+#include <sys/ksym.h>
+#endif /* HAVE_SYS_KSYM_H */
+#include <syslog.h>
+#include <time.h>
+#include <sys/uio.h>
+#include <sys/utsname.h>
+#ifdef HAVE_RUSAGE
+#include <sys/resource.h>
+#endif /* HAVE_RUSAGE */
+
+/* machine dependent includes */
+#ifdef SUNOS_5
+#include <limits.h>
+#include <strings.h>
+#endif /* SUNOS_5 */
+
+/* machine dependent includes */
+#ifdef HAVE_LINUX_VERSION_H
+#include <linux/version.h>
+#endif /* HAVE_LINUX_VERSION_H */
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif /* HAVE_ASM_TYPES_H */
+
+/* misc include group */
+#include <stdarg.h>
+#include <assert.h>
+
+/* network include group */
+
+#include <sys/socket.h>
+
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif /* HAVE_SYS_SOCKIO_H */
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#ifdef HAVE_NET_NETOPT_H
+#include <net/netopt.h>
+#endif /* HAVE_NET_NETOPT_H */
+
+#include <net/if.h>
+
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif /* HAVE_NET_IF_DL_H */
+
+#ifdef HAVE_NET_IF_VAR_H
+#include <net/if_var.h>
+#endif /* HAVE_NET_IF_VAR_H */
+
+#include <net/route.h>
+
+#ifdef HAVE_NETLINK
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#else
+#define RT_TABLE_MAIN		0
+#endif /* HAVE_NETLINK */
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif /* HAVE_NETDB_H */
+
+#include <arpa/inet.h>
+#include <arpa/telnet.h>
+
+#ifdef HAVE_INET_ND_H
+#include <inet/nd.h>
+#endif /* HAVE_INET_ND_H */
+
+#ifdef HAVE_NETINET_IN_VAR_H
+#include <netinet/in_var.h>
+#endif /* HAVE_NETINET_IN_VAR_H */
+
+#ifdef HAVE_NETINET_IN6_VAR_H
+#include <netinet/in6_var.h>
+#endif /* HAVE_NETINET_IN6_VAR_H */
+
+#ifdef HAVE_NETINET6_IN_H
+#include <netinet6/in.h>
+#endif /* HAVE_NETINET6_IN_H */
+
+
+#ifdef HAVE_NETINET6_IP6_H
+#include <netinet6/ip6.h>
+#endif /* HAVE_NETINET6_IP6_H */
+
+#ifdef HAVE_NETINET_ICMP6_H
+#include <netinet/icmp6.h>
+#endif /* HAVE_NETINET_ICMP6_H */
+
+#ifdef HAVE_NETINET6_ND6_H
+#include <netinet6/nd6.h>
+#endif /* HAVE_NETINET6_ND6_H */
+
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif /* HAVE_LIBUTIL_H */
+
+#ifdef BSDI_NRL
+
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif /* HAVE_NETINET6_IN6_H */
+
+#ifdef NRL
+#include <netinet6/in6.h>
+#endif /* NRL */
+
+#define IN6_ARE_ADDR_EQUAL IN6_IS_ADDR_EQUAL
+
+/* BSD/OS 4.0 has lost belows defines, it should appear at
+   /usr/include/sys/socket.h.  */
+#define CMSG_ALIGN(n)           (((n) + 3) & ~3)
+#define CMSG_SPACE(l)   (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(l))
+#define CMSG_LEN(l)     (CMSG_ALIGN(sizeof(struct cmsghdr)) + (l))
+
+#endif /* BSDI_NRL */
+
+/*  The definition of struct in_pktinfo is missing in old version of
+    GLIBC 2.1 (Redhat 6.1).  */
+#if defined (GNU_LINUX) && ! defined (HAVE_INPKTINFO)
+struct in_pktinfo
+{
+  int ipi_ifindex;
+  struct in_addr ipi_spec_dst;
+  struct in_addr ipi_addr;
+};
+#endif
+
+/* For old definition. */
+#ifndef IN6_ARE_ADDR_EQUAL
+#define IN6_ARE_ADDR_EQUAL IN6_IS_ADDR_EQUAL
+#endif /* IN6_ARE_ADDR_EQUAL */
+
+/* Zebra message types. */
+#define ZEBRA_INTERFACE_ADD                1
+#define ZEBRA_INTERFACE_DELETE             2
+#define ZEBRA_INTERFACE_ADDRESS_ADD        3
+#define ZEBRA_INTERFACE_ADDRESS_DELETE     4
+#define ZEBRA_INTERFACE_UP                 5
+#define ZEBRA_INTERFACE_DOWN               6
+#define ZEBRA_IPV4_ROUTE_ADD               7
+#define ZEBRA_IPV4_ROUTE_DELETE            8
+#define ZEBRA_IPV6_ROUTE_ADD               9
+#define ZEBRA_IPV6_ROUTE_DELETE           10
+#define ZEBRA_REDISTRIBUTE_ADD            11
+#define ZEBRA_REDISTRIBUTE_DELETE         12
+#define ZEBRA_REDISTRIBUTE_DEFAULT_ADD    13
+#define ZEBRA_REDISTRIBUTE_DEFAULT_DELETE 14
+#define ZEBRA_IPV4_NEXTHOP_LOOKUP         15
+#define ZEBRA_IPV6_NEXTHOP_LOOKUP         16
+#define ZEBRA_IPV4_IMPORT_LOOKUP          17
+#define ZEBRA_IPV6_IMPORT_LOOKUP          18
+#define ZEBRA_MESSAGE_MAX                 19
+
+/* Zebra route's types. */
+#define ZEBRA_ROUTE_SYSTEM               0
+#define ZEBRA_ROUTE_KERNEL               1
+#define ZEBRA_ROUTE_CONNECT              2
+#define ZEBRA_ROUTE_STATIC               3
+#define ZEBRA_ROUTE_RIP                  4
+#define ZEBRA_ROUTE_RIPNG                5
+#define ZEBRA_ROUTE_OSPF                 6
+#define ZEBRA_ROUTE_OSPF6                7
+#define ZEBRA_ROUTE_ISIS                 8
+#define ZEBRA_ROUTE_BGP                  9
+#define ZEBRA_ROUTE_MAX                  10
+
+/* Zebra's family types. */
+#define ZEBRA_FAMILY_IPV4                1
+#define ZEBRA_FAMILY_IPV6                2
+#define ZEBRA_FAMILY_MAX                 3
+
+/* Error codes of zebra. */
+#define ZEBRA_ERR_RTEXIST               -1
+#define ZEBRA_ERR_RTUNREACH             -2
+#define ZEBRA_ERR_EPERM                 -3
+#define ZEBRA_ERR_RTNOEXIST             -4
+
+/* Zebra message flags */
+#define ZEBRA_FLAG_INTERNAL           0x01
+#define ZEBRA_FLAG_SELFROUTE          0x02
+#define ZEBRA_FLAG_BLACKHOLE          0x04
+#define ZEBRA_FLAG_IBGP               0x08
+#define ZEBRA_FLAG_SELECTED           0x10
+#define ZEBRA_FLAG_CHANGED            0x20
+#define ZEBRA_FLAG_STATIC             0x40
+
+/* Zebra nexthop flags. */
+#define ZEBRA_NEXTHOP_IFINDEX            1
+#define ZEBRA_NEXTHOP_IFNAME             2
+#define ZEBRA_NEXTHOP_IPV4               3
+#define ZEBRA_NEXTHOP_IPV4_IFINDEX       4
+#define ZEBRA_NEXTHOP_IPV4_IFNAME        5
+#define ZEBRA_NEXTHOP_IPV6               6
+#define ZEBRA_NEXTHOP_IPV6_IFINDEX       7
+#define ZEBRA_NEXTHOP_IPV6_IFNAME        8
+
+#ifndef INADDR_LOOPBACK
+#define	INADDR_LOOPBACK	0x7f000001	/* Internet address 127.0.0.1.  */
+#endif
+
+/* Address family numbers from RFC1700. */
+#define AFI_IP                    1
+#define AFI_IP6                   2
+#define AFI_MAX                   3
+
+/* Subsequent Address Family Identifier. */
+#define SAFI_UNICAST              1
+#define SAFI_MULTICAST            2
+#define SAFI_UNICAST_MULTICAST    3
+#define SAFI_MPLS_VPN             4
+#define SAFI_MAX                  5
+
+/* Filter direction.  */
+#define FILTER_IN                 0
+#define FILTER_OUT                1
+#define FILTER_MAX                2
+
+/* Default Administrative Distance of each protocol. */
+#define ZEBRA_KERNEL_DISTANCE_DEFAULT      0
+#define ZEBRA_CONNECT_DISTANCE_DEFAULT     0
+#define ZEBRA_STATIC_DISTANCE_DEFAULT      1
+#define ZEBRA_RIP_DISTANCE_DEFAULT       120
+#define ZEBRA_RIPNG_DISTANCE_DEFAULT     120
+#define ZEBRA_OSPF_DISTANCE_DEFAULT      110
+#define ZEBRA_OSPF6_DISTANCE_DEFAULT     110
+#define ZEBRA_ISIS_DISTANCE_DEFAULT      115
+#define ZEBRA_IBGP_DISTANCE_DEFAULT      200
+#define ZEBRA_EBGP_DISTANCE_DEFAULT       20
+
+/* Flag manipulation macros. */
+#define CHECK_FLAG(V,F)      ((V) & (F))
+#define SET_FLAG(V,F)        (V) = (V) | (F)
+#define UNSET_FLAG(V,F)      (V) = (V) & ~(F)
+
+/* AFI and SAFI type. */
+typedef u_int16_t afi_t;
+typedef u_char safi_t;
+
+/* Zebra types. */
+typedef u_int16_t zebra_size_t;
+typedef u_int8_t zebra_command_t;
+
+#endif /* _ZEBRA_H */
diff --git a/isisd/topology/Makefile.am b/isisd/topology/Makefile.am
new file mode 100644
index 0000000..045c15c
--- /dev/null
+++ b/isisd/topology/Makefile.am
@@ -0,0 +1,23 @@
+## Process this file with automake to produce Makefile.in.
+
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+
+noinst_LIBRARIES = libtopology.a
+
+libtopology_a_SOURCES = \
+	spgrid.c
+
+libtopology_a_DEPENDENCIES = @LIB_REGEX@
+
+libtopology_a_LIBADD = @LIB_REGEX@ ../../lib/libzebra.a
+
+noinst_HEADERS = \
+	spgrid.h
+
+EXTRA_DIST = regex.c regex-gnu.h
+
+depend:
+	@$(CPP) -MM $(INCLUDES) $(LDFLAGS) *.c
+
+## File dependency.
diff --git a/isisd/topology/random.c b/isisd/topology/random.c
new file mode 100644
index 0000000..d4ef995
--- /dev/null
+++ b/isisd/topology/random.c
@@ -0,0 +1,154 @@
+/*********************************************************************/
+/*                                                                   */
+/* current processor time in seconds                                 */
+/* difference between two calls is processor time spent by your code */
+/* needs: <sys/types.h>, <sys/times.h>                               */
+/* depends on compiler and OS                                        */
+/*                                                                   */
+/*********************************************************************/
+
+#include <sys/types.h>
+#include <sys/times.h>
+
+float timer()
+   { struct tms hold;
+
+        times(&hold);
+        return  (float)(hold.tms_utime) / 60.0;
+   }
+
+
+/*********************************************************************/
+/*                                                                   */
+/*            Family of random number generators                     */
+/*                                                                   */
+/*  Initialisation:                                                  */
+/*            void init_rand ( seed );                               */
+/*                 long seed     - any positive number               */
+/*                                 if seed<=0 init_rand takes time   */
+/*                                 from timer instead of seed        */
+/*                                                                   */
+/*  Whole number uniformly distributed on [0,n):                     */
+/*            long nrand (n);                                        */
+/*                 long n                                            */
+/*                                                                   */
+/*  Real number uniformly distributed on [0,1]                       */
+/*            double rand01();                                       */
+/*                                                                   */
+/*  Real number with Gauss(0,1) disitribution:                       */
+/*            double randg01();                                      */
+/*                                                                   */
+/*  Algorithm:                                                       */
+/*            x(n+1) = (x(n) * 5^13) mod 2^31                        */
+/*                                                                   */
+/*********************************************************************/
+
+unsigned long internal_seed;
+
+void init_rand ( init_seed )
+
+long init_seed;
+
+{ internal_seed = ( init_seed > 0 )
+                 ? (unsigned long) init_seed
+                 : (unsigned long) timer(); 
+                
+
+  /* only odd numbers are acceptable */
+  if ( internal_seed % 2 == 0 ) internal_seed --;
+}
+
+/*********************************************************************/
+/*                                                                   */
+/* Internal function  irand  may depend on OS and compiler           */
+/*                                                                   */
+/* irand assumption:                                                 */
+/* unsigned long i,j;                                                */
+/*   if i*j > max(unsigned long)                                     */
+/*           1. No overflow interruption                             */
+/*           2. i*j = i*j mod max(unsigned long)                     */
+/*                                                                   */
+/* This assumption is true for a lot of computers.                   */
+/* If your computer fails:                                           */
+/*   rename: irand <---> xrand                                       */
+/*                                                                   */
+/*********************************************************************/
+ 
+#define  A   1220703125
+#define  B   2147483647
+#define  BF  2147483647.
+
+static long irand ()
+
+{ internal_seed = ( internal_seed * A ) & B;
+  return (long) internal_seed ;
+}
+
+/*********************************************************************/
+/*                                                                   */
+/*              computer independent variant of  irand               */
+/*                                                                   */
+/*********************************************************************/
+
+
+#define T15  32768 
+#define T16  65536
+#define A1   37252
+#define A2   29589
+
+static long xrand()
+
+{ unsigned long is1, is2;
+
+  is1 = internal_seed / T15;
+  is2 = internal_seed % T15;
+
+  internal_seed = ( (((is2 * A1) + (is1 * A2))% T16 )* T15 + (is2 * A2) ) & B;
+  return (long) ( internal_seed ) ;
+}
+
+
+/*********************************************************************/
+
+
+double rand01()
+
+{ return  (double) irand() / BF ;
+}
+  
+/*********************************************************************/
+
+#define NK  12
+
+double randg01()
+
+{ int i;
+  double sum = 0;
+
+  for ( i = 0; i < NK; i++ ) sum += rand01();
+  return sum - 6.;
+
+  /* if   NK != 12  then you must return (12/NK)*sum - (NK/2) */
+}
+
+#undef NK
+     
+  
+/*********************************************************************/
+
+long nrand ( n )
+
+long n;
+
+{ return (long) ( rand01() * (double) n );
+}
+
+/*********************************************************************/
+
+#undef A
+#undef A1
+#undef A2
+#undef B
+#undef BF
+#undef T15
+#undef T16
diff --git a/isisd/topology/spacyc.c b/isisd/topology/spacyc.c
new file mode 100644
index 0000000..8531447
--- /dev/null
+++ b/isisd/topology/spacyc.c
@@ -0,0 +1,483 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <values.h>
+
+#include "random.c"
+
+#define DASH '-'
+#define VERY_FAR 100000000
+
+
+/* generator of acyclic random networks for the shortest paths problem;
+   extended DIMACS format for output */
+
+main ( argc, argv )
+
+int argc;
+char* argv[];
+
+{
+
+char   args[30];
+
+long   n,
+       n0,
+       source,
+       i,
+       i0,
+       j,
+       dij;
+
+long   m,
+       m0,
+       mc,
+       k;
+
+long   *p,
+       p_t,
+       l,
+       lx;
+
+long   seed,
+       seed1,
+       seed2;
+
+int    ext=0;
+
+FILE   *fout;
+
+/* variables for lengths generating */
+/* initialized by default values */
+int    l_f = 0, ll_f = 0, lm_f = 0, ln_f = 0, ls_f = 0;
+long   ll = 10000,    /* upper bound of the interval */
+       lm = 0;        /* lower bound of the interval */
+double ln = 0,        /* l += ln * |i-j| */ 
+       ls = 0;        /* l += ls * |i-j|^2 */
+
+/* variables for connecting path(s) */
+int    c_f = 0, cl_f = 0, ch_f = 0, c_rand = 1;
+long   cl = 1;        /* length of path arc */
+long   ch;            /* number of arcs in the path
+                         n - by default */
+
+/* variables for artifical source */
+int    s_f = 0, sl_f = 0, sm_f = 0;
+long   sl   = VERY_FAR, /* upper bound of artifical arc */
+       sm,              /* lower bound of artifical arc */
+       s;  
+
+/* variables for potentials */
+int    p_f = 0, pl_f = 0, pm_f = 0, pn_f = 0, ps_f = 0,
+       pa_f = 0, pap_f = 0, pac_f = 0;
+long   pl,            /* upper bound of the interval */
+       pm;            /* lower bound of the interval */
+double pn = 0,        /* l += ln * |i-j| */ 
+       ps = 0,        /* l += ls * |i-j|^2 */
+       pap = 0,       /* part of nodes with alternative dustribution */
+       pac = -1;      /* multiplier for alternative distribution */
+
+int np;               /* number of parameter parsing now */
+
+#define PRINT_ARC( i, j, length )\
+{\
+l = length;\
+if ( p_f ) l += ( p[i] - p[j] );\
+printf ("a %8ld %8ld %12ld\n", i, j, l );\
+}
+
+  /* parsing  parameters */
+
+if ( argc < 2 ) goto usage;
+
+np = 0;
+
+strcpy ( args, argv[1] );
+
+  if ( ( args[0] == DASH ) && ( args[1] == 'h')
+     )
+      goto help;
+
+if ( argc < 4 ) goto usage;
+
+/* first parameter - number of nodes */
+np = 1;
+if ( ( n = atoi ( argv[1] ) )  <  2  )  goto usage;
+
+/* second parameter - number of arcs */
+np = 2;
+if ( ( m = atoi ( argv[2] ) )  <  n  )  goto usage;
+
+/* third parameter - seed */
+np=3;
+if ( ( seed = atoi ( argv[3] ) )  <=  0  )  goto usage;
+
+/* other parameters */
+
+for ( np = 4; np < argc; np ++ )
+  {
+    strcpy ( args, argv[np] );
+    if ( args[0] != DASH ) goto usage;
+
+    switch ( args[1] )
+      {
+
+      case 'l' : /* an interval for arc length */
+	l_f = 1;
+	switch ( args[2] )
+	  { 
+	  case 'l': /* length of the interval */
+	    ll_f = 1;
+	    ll  =  (long) atof ( &args[3] );
+	    break;
+	  case 'm': /* minimal bound */
+	    lm_f = 1;
+	    lm  = (long ) atof ( &args[3] );
+	    break;
+	  case 'n': /* additional length: l*|i-j| */
+	    ln_f = 1;
+	    ln  = atof ( &args[3] );
+	    break;
+	  case 's': /* additional length: l*|i-j|^2 */
+	    ls_f = 1;
+	    ls  = atof ( &args[3] );
+	    break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+	  }
+	break;
+
+      case 'c' : /* connecting path(s) */
+        c_f = 1;
+	switch ( args[2] )
+	  { 
+	  case 'l': /* length of path arc */
+            c_rand = 0; /* fixed arc length */
+	    cl_f = 1;
+	    cl  =  (long) atof ( &args[3] );
+            break;
+	  case 'h': /* number of arcs in connecting path */
+	    ch_f = 1;
+	    ch  =  (long) atof ( &args[3] );
+            if ( ch < 1 || ch > n ) goto usage;
+	    break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+          }
+	break;
+
+      case 's' : /* additional source */
+        s_f = 1;
+	if ( strlen ( args ) > 2 )
+	{  
+	switch ( args[2] )
+	  { 
+	  case 'l': /* upper bound of art. arc */
+	    sl_f = 1;
+	    sl  =  (long) atof ( &args[3] );
+            break;
+	  case 'm': /* lower bound of art. arc */
+	    sm_f = 1;
+	    sm  =  (long) atof ( &args[3] );
+            break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+          }
+         }
+	break;
+
+      case 'p' : /* potentials */
+	p_f = 1;
+	if ( strlen ( args ) > 2 )
+	{  
+	switch ( args[2] )
+	  { 
+	  case 'l': /* length of the interval */
+	    pl_f = 1;
+	    pl  =  (long) atof ( &args[3] );
+	    break;
+	  case 'm': /* minimal bound */
+	    pm_f = 1;
+	    pm  = (long ) atof ( &args[3] );
+	    break;
+	  case 'n': /* additional length: l*|i-j| */
+	    pn_f = 1;
+	    pn  = atof ( &args[3] );
+	    break;
+	  case 's': /* additional length: l*|i-j|^2 */
+	    ps_f = 1;
+	    ps  = atof ( &args[3] );
+	    break;
+	  case 'a': /* bipolar distribution */
+	    pa_f = 1;
+	    switch ( args[3] )
+	      {
+	      case 'p': /* % of alternative potentials */
+                pap_f = 1;
+                pap  = atof ( &args[4] );
+		if ( pap < 0   ) pap = 0;
+		if ( pap > 100 ) pap = 100;
+                pap /= 100;
+		break;
+	      case 'c': /* multiplier */
+		pac_f = 1;
+		pac = atof ( &args[4] );
+		break;
+	      default: /* unknown switch value */
+		goto usage;
+	      }
+	    break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+	  }
+      }
+	break;
+
+      default  : /* unknoun case */
+	goto usage;
+      }
+  }
+   
+/* ----- ajusting parameters ----- */
+
+n0 = n; m0 = m;
+
+/* length parameters */
+if ( ll < lm ) { lx = ll; ll = lm; lm = lx; }
+
+/* potential parameters */
+if ( p_f )
+  {
+   if ( ! pl_f ) pl = ll;
+   if ( ! pm_f ) pm = lm;
+   if ( pl < pm ) { lx = pl; pl = pm; pm = lx; }
+  }
+
+/* path(s) parameters */
+if ( ! ch_f ) ch = n - 1;
+mc = n - 1;
+
+ /* artifical source parameters */
+if ( s_f )          
+   { m0 += n; n0 ++ ; 
+     if ( ! sm_f ) sm = sl;
+     if ( sl < sm ) { lx = sl; sl = sm; sm = lx; }
+   }
+
+/*----- printing title -----*/
+
+printf ("c acyclic network for shortest paths problem\n");
+printf ("c extended DIMACS format\nc\n" );
+
+
+/* name of the problem */
+printf ("t ac_%ld_%ld_%ld_", n, m, seed );
+if ( l_f )
+  printf ("%c", 'l');
+if ( c_f )
+  printf ("%c", 'c');
+if ( s_f )
+  printf ("%c", 's');
+if ( p_f )
+  printf ("%c", 'p');
+printf ("\nc\n");
+
+/* printing additional information  */
+if ( l_f )
+  printf ("c length -> min: %ld max: %ld k1: %.2f k2: %.2f\n",
+           lm, ll, ln, ls );
+if ( c_f )
+  printf ("c path(s) -> number of arcs: %ld arc length: %ld\n",
+           ch, cl );
+if ( s_f )
+  printf ("c length of arcs from artifical source -> min: %ld max: %ld\n",
+           sm, sl );
+if ( p_f )
+  {
+  printf ("c potentials -> min: %ld max: %ld k1: %.2f k2: %.2f\n",
+	  pm, pl, pn, ps );
+  if ( pa_f )
+  printf ("c potentials -> part of alternative distribution: %.2f k: %.2f\n",
+          pap, pac );
+  }
+printf ("c\n" );
+
+printf ("p sp %8ld %8ld\nc\n", n0, m0 );
+
+source = ( s_f ) ? n0 : 1;
+printf ("n %8ld\nc\n", source );
+
+
+if ( p_f ) /* generating potentials */
+  {
+    seed1 = 2*seed + 1;
+    p = (long*) calloc ( n+2, sizeof (long) );
+    init_rand ( seed1);
+    pl = pl - pm + 1;
+
+    for ( i = 0; i <= n; i ++ )
+      {
+	p_t = pm + nrand ( pl );
+	if ( pn_f ) p_t += (long) ( i * pn );
+	if ( ps_f ) p_t += (long) ( i * ( i * ps ));
+	if ( pap_f )
+	    if ( rand01() < pap )
+		p_t = (long) ( p_t * pac );
+        p[i] = p_t;
+      }
+    p[n+1] = 0;
+  }
+
+
+if ( s_f ) /* additional arcs from artifical source */
+  {
+    seed2 = 3*seed + 1;
+    init_rand ( seed2 );
+    sl = sl - sm + 1;
+
+    for ( i = n; i > 1; i -- )
+      {
+	s = sm + nrand ( sl );
+	PRINT_ARC ( n0, i, s ) 
+      }
+
+    PRINT_ARC ( n0, 1, 0 )
+  }
+
+/* initialize random number generator */
+init_rand ( seed );
+ll = ll - lm + 1;
+
+/* generating connecting path(s) */
+for ( i = 1; i < n; i ++ )
+  {
+    if ( ( (i-1) % ch ) != 0 )
+      i0 = i;
+    else
+      i0 = 1;
+
+      if (c_rand)
+        cl = lm + nrand(ll);
+      PRINT_ARC ( i0, i+1, cl )
+  }
+
+/* generating random arcs */
+
+
+for ( k = 1; k <= m - mc; k ++ )
+  {
+    i = 1 + nrand ( n );
+
+    do
+    j = 1 + nrand ( n );
+    while ( j == i );
+
+    if ( i > j )
+      { i0 = i; i = j; j = i0; }
+
+    dij = j - i;
+    l = lm + nrand ( ll );
+    if ( ln_f ) l += (long) ( dij * ln );
+    if ( ls_f ) l += (long) ( dij * ( dij * ls ) );
+    PRINT_ARC ( i, j, l );
+  }
+
+/* all is done */
+exit (ext);
+
+/* ----- wrong usage ----- */
+
+ usage:
+fprintf ( stderr,
+"\nusage: %s  n  m  seed  [ -ll#i -lm#i -cl#i -p -pl#i -pm#i ... ]\n\
+help:  %s -h\n\n", argv[0], argv[0] );
+
+if ( np > 0 )
+  fprintf ( stderr, "error in parameter # %d\n\n", np );   
+exit (4);
+
+/* ---- help ---- */
+
+ help:
+
+if ( args[2] == 'h') goto hhelp;
+
+fprintf ( stderr, 
+"\n'%s' - acyclic network generator for shortest paths problem.\n\
+Generates problems in extended DIMACS format.\n\
+\n\
+   %s  n m seed [ -ll#i -lm#i -cl#i -p -pl#i -pm#i ... ]\n\
+   %s -hh\n\
+\n\
+                        #i - integer number   #f - real number\n\
+\n\
+-ll#i  - #i is the upper bound on arc lengths          (default 10000)\n\
+-lm#i  - #i is the lower bound on arc lengths          (default 0)\n\
+-cl#i  - #i is length of arcs in connecting path(s)    (default random)\n\
+-p     - generate potentials \n\
+-pl#i  - #i is the upper bound on potentials           (default ll)\n\
+-pm#i  - #i is the lower bound on potentials           (default lm)\n\
+\n\
+-hh    - extended help \n\n",
+argv[0], argv[0], argv[0] );
+
+exit (0);
+
+/* --------- sophisticated help ------------ */
+ hhelp:
+
+if ( argc < 3 )
+     fout = stderr;
+else
+     fout = fopen ( argv[2], "w" );
+
+if ( fout == NULL )
+{ fprintf ( stderr, "\nCan't open file  '%s' for writing help\n\n", argv[2] );
+  exit ( 2 );
+}
+
+fprintf (fout, 
+"\n'%s' - acyclic network generator for shortest paths problem.\n\
+Generates problems in extended DIMACS format.\n\
+\n\
+   %s  n m seed [ -ll#i -lm#i -ln#f -ls#f\n\
+                      -p  -pl#i -pm#i -pn#f -ps#f -pap#i -pac#f\n\
+                      -cl#i -ch#i\n\
+                      -s  -sl#i -sm#i\n\
+                    ]\n\
+   %s -hh file_name\n\
+\n\
+                        #i - integer number   #f - real number\n\
+\n\
+      Arc length parameters:\n\
+-ll#i  - #i is the upper bound on arc lengths          (default 10000)\n\
+-lm#i  - #i is the lower bound on arc lengths          (default 0)\n\
+-ln#f  - multipliy l(i, j) by #f * |i-j|               (default 0)\n\
+-ls#f  - multipliy l(i, j) by #f * |i-j|^2             (default 0)\n\
+\n\
+      Potential parameters:\n\
+-p     - generate potentials \n\
+-pl#i  - #i is the upper bound on potentials           (default ll)\n\
+-pm#i  - #i is the lower bound on potentials           (default lm)\n\
+-pn#f  - multiply p(i) by #f * i                       (default 0)\n\
+-ps#f  - multiply p(i) by #f * i^2                     (default 0)\n\
+-pap#i - percentage of alternative potential nodes     (default 0)\n\
+-pac#f - if i is alternative, multiply  p(i) by #f     (default -1)\n\
+\n\
+      Connecting path(s) parameters:\n\
+-cl#i  - #i is length of arcs in connecting path(s)   (default random)\n\
+-ch#i  - #i is length of connecting path(s)           (default n-1)\n\
+\n\
+      Artificial source parameters:\n\
+-s     - generate artificial source with default connecting arc lengths\n\
+-sl#i  - #i is the upper bound on art. arc lengths    (default 100000000)\n\
+-sm#i  - #i is the lower bound on art. arc lengths    (default sl)\n\
+\n\
+-hh file_name  - save this help in the file 'file_name'\n\n",
+argv[0], argv[0], argv[0] );
+
+exit (0);
+}
+
+
+
diff --git a/isisd/topology/spgrid.c b/isisd/topology/spgrid.c
new file mode 100644
index 0000000..22d3a80
--- /dev/null
+++ b/isisd/topology/spgrid.c
@@ -0,0 +1,729 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <values.h>
+
+#include "random.c"
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "vty.h"
+#include "log.h"
+#include "linklist.h"
+
+#include "spgrid.h"
+
+
+#define DASH '-'
+#define VERY_FAR 100000000
+
+#define DOUBLE_CYCLE   0
+#define CYCLE          1
+#define PATH           2
+
+#define NO             0
+#define YES            1
+
+#define NODE( x, y ) (x*Y + y + 1)
+
+char   *graph_type[] =  {
+  "double cycle",
+  "cycle",
+  "path"
+};
+
+struct arc *arc;
+
+char   args[30];
+
+long   X,   /* horizontal size of grid */
+       Y;   /* vertical size of grid */
+
+long   x,
+       y,
+       y1, y2, yp,
+       dl, dx, xn, yn, count,
+       *mess;
+
+double n;
+long   n0,
+       source,
+       i,
+       i0,
+       j,
+       dij;
+
+double m;
+long   m0,
+       mc,
+       k;
+
+long   *p,
+       p_t,
+       l,
+       lx;
+
+long   seed,
+       seed1,
+       seed2;
+
+int    ext=0;
+
+/* initialized by default values */
+
+/* variables for generating one layer */
+
+/* variables for generating spanning graph */
+int    c_f = 0, cw_f = 0, cm_f = 0, cl_f = 0;
+
+int    cw = DOUBLE_CYCLE;  /* type of spanning graph */
+long   cm = 0,             /* lower bound of the interval */
+       cl = 100;           /* upper bound of the interval */
+
+/* variables for generating additional arcs */
+int    a_f = 0, ax_f = 0, am_f = 0, al_f = 0;
+
+long   ax = 0,             /* number of additional arcs */
+       am = 0,             /* lower bound of the interval */
+       al = 100;           /* upper bound of the interval */
+
+/* variables for inter-layer arcs */
+int    i_f = 0, ip_f = 0, ix_f = 0, ih_f = 0,
+       im_f = 0, il_f = 0, in_f = 0, is_f = 0;
+
+int    ip = NO;       /* to mess or not to mess */
+long   ix = 1,        /* number of interlayered arcs in a NODE */
+       ih = 1,        /* step between two layeres */
+       il = 10000,    /* upper bound of the interval */
+       im = 1000;     /* lower bound of the interval */
+double in = 1,        /* l *=  in * |x1-x2| */
+       is = 0;        /* l *=  is * |x1-x2|^2 */
+
+/* variables for artifical source */
+int    s_f = 0, sl_f = 0, sm_f = 0;
+long   sl   = VERY_FAR, /* upper bound of artifical arc */
+       sm,              /* lower bound of artifical arc */
+       s;
+
+/* variables for potentials */
+int    p_f = 0, pl_f = 0, pm_f = 0, pn_f = 0, ps_f = 0;
+
+long   pl,            /* upper bound of the interval */
+       pm;            /* lower bound of the interval */
+double pn = 0,        /* p +=  ln * (x+1) */
+       ps = 0;        /* p +=  ls * (x+1)^2 */
+
+int np;               /* number of parameter parsing now */
+
+
+void
+free_arc   (void *val) {
+  free(val);
+}
+
+void
+print_arc (struct vty *vty, struct list *topology, long i, long j, long length)
+{
+  struct arc *myarc;
+
+  l = length;
+  if ( p_f ) l += ( p[i] - p[j] );
+//  vty_out (vty,"a %8ld %8ld %12ld%s", i, j, l ,VTY_NEWLINE);
+  myarc = malloc (sizeof(struct arc));
+  myarc->from_node = i;
+  myarc->to_node = j;
+  myarc->distance = l;
+  topology->del = free_arc;
+  listnode_add (topology, myarc);
+}
+
+/* ---- help ---- */
+void
+help (struct vty *vty) {
+//  if ( args[2] == 'h') hhelp (vty);
+  vty_out (vty,"grid network generator for shortest paths problem.%s",VTY_NEWLINE);
+  vty_out (vty,"Generates problems in extended DIMACS format.%s",VTY_NEWLINE);
+  vty_out (vty,"X Y seed [ -cl#i -cm#i -c{c|d|p} -ip -il#i -im#i -p -pl#i -pm#i... ]%s",VTY_NEWLINE);
+  vty_out (vty,"#i - integer number%s",VTY_NEWLINE);
+  vty_out (vty,"-cl#i - #i is the upper bound on layer arc lengths    (default 100)%s",VTY_NEWLINE);
+  vty_out (vty,"-cm#i - #i is the lower bound on layer arc lengths    (default 0)%s",VTY_NEWLINE);
+  vty_out (vty,"-c#t  - #t is the type of connecting graph: { c | d | p }%s",VTY_NEWLINE);
+  vty_out (vty,"           c - cycle, d - double cycle, p - path      (default d)%s",VTY_NEWLINE);
+  vty_out (vty,"-ip   - shuffle inter-layer arcs                     (default NO)%s",VTY_NEWLINE);
+  vty_out (vty,"-il#i - #i is the upper bound on inter-layer arc lengths (default 10000)%s",VTY_NEWLINE);
+  vty_out (vty,"-im#i - #i is the lower bound on inter-layer arc lengths (default 1000)%s",VTY_NEWLINE);
+  vty_out (vty,"-p    - generate potentials%s",VTY_NEWLINE);
+  vty_out (vty,"-pl#i - #i is the upper bound on potentials           (default il)%s",VTY_NEWLINE);
+  vty_out (vty,"-pm#i - #i is the lower bound on potentials           (default im)%s",VTY_NEWLINE);
+  vty_out (vty,"%s",VTY_NEWLINE);
+  vty_out (vty,"-hh    - extended help%s",VTY_NEWLINE);
+}
+
+/* --------- sophisticated help ------------ */
+void
+hhelp (struct vty *vty) {
+/*
+zlog_info (
+"\n'%s' - grid network generator for shortest paths problem.\n\
+Generates problems in extended DIMACS format.\n\
+\n\
+   %s  X Y seed [ -cl#i -cm#i -c{c|d|p}\n\
+                      -ax#i -al#i -am#i\n\
+                      -ip   -il#i -im#i -in#i -is#i -ix#i -ih#i\n\
+                      -p    -pl#i -pm#i -pn#f -ps#f\n\
+                      -s    -sl#i -sm#i\n\
+                    ]\n\
+   %s -hh file_name\n\
+\n\
+                        #i - integer number   #f - real number\n\
+\n\
+      Parameters of connecting arcs within one layer:\n\
+-cl#i - #i is the upper bound on arc lengths          (default 100)\n\
+-cm#i - #i is the lower bound on arc lengths          (default 0)\n\
+-c#t  - #t is the type of connecting graph: { c | d | p }\n\
+           c - cycle, d - double cycle, p - path      (default d)\n\
+\n\
+      Parameters of additional arcs within one layer:\n\
+-ax#i - #i is the number of additional arcs           (default 0)\n\
+-al#i - #i is the upper bound on arc lengths          (default 100)\n\
+-am#i - #i is the lower bound on arc lengths          (default 0)\n\
+\n\
+      Interlayerd arc parameters:\n\
+-ip    - shuffle inter-layer arcs                         (default NO)\n\
+-il#i  - #i is the upper bound on arc lengths          (default 10000)\n\
+-im#i  - #i is the lower bound on arc lengths          (default 1000)\n\
+-in#f  - multiply l(i, j) by #f * x(j)-x(i)           (default 1)\n\
+         if #f=0 - don't multiply\n\
+-is#f  - multiply l(i, j) by #f * (x(j)-x(i))^2       (default NO)\n\
+-ix#i  - #i - is the number of arcs from a node        (default 1)\n\
+-ih#i  - #i - is the step between connected layers     (default 1)\n\
+\n\
+      Potential parameters:\n\
+-p     - generate potentials \n\
+-pl#i  - #i is the upper bound on potentials           (default ll)\n\
+-pm#i  - #i is the lower bound on potentials           (default lm)\n\
+-pn#f  - multiply p(i) by #f * x(i)                    (default NO)\n\
+-ps#f  - multiply p(i) by #f * x(i)^2                  (default NO)\n\
+\n");
+zlog_info (
+"     Artificial source parameters:\n\
+-s     - generate artificial source with default connecting arc lengths\n\
+-sl#i  - #i is the upper bound on art. arc lengths    (default 100000000)\n\
+-sm#i  - #i is the lower bound on art. arc lengths    (default sl)\n\"
+);*/
+}
+
+/* ----- wrong usage ----- */
+void
+usage (struct vty *vty) {
+  vty_out (vty,"usage: X Y seed [-ll#i -lm#i -cl#i -p -pl#i -pm#i ...]%s",VTY_NEWLINE);
+  vty_out (vty,"help: -h or -hh%s",VTY_NEWLINE);
+
+  if ( np > 0 )
+    zlog_err ("error in parameter # %d\n\n", np );
+}
+
+
+/* parsing  parameters */
+/* checks the validity of incoming parameters */
+int
+spgrid_check_params ( struct vty *vty, int argc, char **argv)
+{
+/* initialized by default values */
+  ext=0;
+
+/* variables for generating one layer */
+
+/* variables for generating spanning graph */
+  c_f = 0;
+  cw_f = 0;
+  cm_f = 0;
+  cl_f = 0;
+
+  cw = PATH;  /* type of spanning graph */
+  cm = 0;             /* lower bound of the interval */
+  cl = 63;           /* upper bound of the interval */
+
+/* variables for generating additional arcs */
+  a_f = 0;
+  ax_f = 0;
+  am_f = 0;
+  al_f = 0;
+
+  ax = 0;             /* number of additional arcs */
+  am = 0;             /* lower bound of the interval */
+  al = 63;           /* upper bound of the interval */
+
+/* variables for inter-layer arcs */
+  i_f = 0;
+  ip_f = 0;
+  ix_f = 0;
+  ih_f = 0;
+  im_f = 0;
+  il_f = 0;
+  in_f = 0;
+  is_f = 0;
+
+  ip = NO;       /* to mess or not to mess */
+  ix = 1;        /* number of interlayered arcs in a NODE */
+  ih = 1;        /* step between two layeres */
+  il = 63; //was 10000;    /* upper bound of the interval */
+  im = 0;  //was 1000;     /* lower bound of the interval */
+  in = 1;        /* l *=  in * |x1-x2| */
+  is = 0;        /* l *=  is * |x1-x2|^2 */
+
+/* variables for artifical source */
+  s_f = 0;
+  sl_f = 0;
+  sm_f = 0;
+  sl   = VERY_FAR; /* upper bound of artifical arc */
+
+/* variables for potentials */
+  p_f = 0;
+  pl_f = 0;
+  pm_f = 0;
+  pn_f = 0;
+  ps_f = 0;
+
+  pn = 0;        /* p +=  ln * (x+1) */
+  ps = 0;        /* p +=  ls * (x+1)^2 */
+
+
+  if ( argc < 1 ) {
+    usage (vty);
+    return 1;
+  }
+
+  np = 0;
+
+  strcpy ( args, argv[0] );
+
+  if ((args[0] == DASH) && (args[1] == 'h'))
+    help (vty);
+
+  if ( argc < 3 ) {
+    usage (vty);
+    return 1;
+  }
+
+  /* first parameter - horizontal size */
+  np = 1;
+  if ( ( X = atoi ( argv[0] ) )  <  1  ) {
+    usage (vty);
+    return 1;
+  }
+
+  /* second parameter - vertical size */
+  np = 2;
+  if ( ( Y = atoi ( argv[1] ) )  <  1  ) {
+    usage (vty);
+    return 1;
+  }
+
+  /* third parameter - seed */
+  np=3;
+  if ( ( seed = atoi ( argv[2] ) )  <=  0  ) {
+    usage (vty);
+    return 1;
+  }
+
+  /* other parameters */
+  for ( np = 3; np < argc; np ++ ) {
+    strcpy ( args, argv[np] );
+    if ( args[0] != DASH )  {
+      usage (vty);
+      return 1;
+    }
+
+    switch ( args[1] ) {
+      case 'c' : /* spanning graph in one layer */
+        c_f = 1;
+        switch ( args[2] ) {
+          case 'l': /* upper bound of the interval */
+            cl_f = 1;
+            cl  =  (long) atof ( &args[3] );
+            break;
+          case 'm': /* lower bound */
+            cm_f = 1;
+            cm  = (long ) atof ( &args[3] );
+            break;
+          case 'c': /* type - cycle */
+            cw_f = 1;
+            cw   = CYCLE;
+            break;
+          case 'd': /* type - double cycle */
+            cw_f = 1;
+            cw   = DOUBLE_CYCLE;
+            break;
+          case 'p': /* type - path */
+            cw_f = 1;
+            cw   = PATH;
+            break;
+
+          default:  /* unknown switch  value */
+            usage (vty);
+            return 1;
+          }
+        break;
+
+      case 'a' : /* additional arcs in one layer */
+         a_f = 1;
+        switch ( args[2] )
+          {
+          case 'l': /* upper bound of the interval */
+            al_f = 1;
+            al  =  (long) atof ( &args[3] );
+            break;
+          case 'm': /* lower bound */
+            am_f = 1;
+            am  = (long ) atof ( &args[3] );
+            break;
+          case 'x': /* number of additional arcs */
+            ax_f = 1;
+            ax   = (long ) atof ( &args[3] );
+            if ( ax < 0 )
+             {
+               usage (vty);
+               return 1;
+             }
+            break;
+
+          default:  /* unknown switch  value */
+            {
+              usage (vty);
+              return 1;
+            }
+          }
+        break;
+
+
+      case 'i' : /* interlayered arcs */
+        i_f = 1;
+
+        switch ( args[2] )
+          {
+          case 'l': /* upper bound */
+            il_f = 1;
+            il  =  (long) atof ( &args[3] );
+            break;
+          case 'm': /* lower bound */
+            im_f = 1;
+            im  = (long ) atof ( &args[3] );
+            break;
+          case 'n': /* additional length: l *= in*|i1-i2| */
+            in_f = 1;
+            in  = atof ( &args[3] );
+            break;
+          case 's': /* additional length: l *= is*|i1-i2|^2 */
+            is_f = 1;
+            is  = atof ( &args[3] );
+            break;
+          case 'p': /* mess interlayered arcs */
+            ip_f = 1;
+            ip = YES;
+            break;
+          case 'x': /* number of interlayered arcs */
+            ix_f = 1;
+            ix  = atof ( &args[3] );
+            if ( ix < 1 ) {
+              usage (vty);
+              return 1;
+            }
+            break;
+          case 'h': /* step between two layeres */
+            ih_f = 1;
+            ih  = atof ( &args[3] );
+            if ( ih < 1 ) {
+               usage (vty);
+               return 1;
+             }
+            break;
+          default:  /* unknown switch  value */
+            usage (vty);
+            return 1;
+          }
+        break;
+
+      case 's' : /* additional source */
+        s_f = 1;
+        if ( strlen ( args ) > 2 )
+        {
+        switch ( args[2] )
+          {
+          case 'l': /* upper bound of art. arc */
+            sl_f = 1;
+            sl  =  (long) atof ( &args[3] );
+            break;
+          case 'm': /* lower bound of art. arc */
+            sm_f = 1;
+            sm  =  (long) atof ( &args[3] );
+            break;
+          default:  /* unknown switch  value */
+            usage (vty);
+            return 1;
+          }
+         }
+        break;
+
+      case 'p' : /* potentials */
+        p_f = 1;
+        if ( strlen ( args ) > 2 )
+        {
+        switch ( args[2] )
+          {
+          case 'l': /* upper bound */
+            pl_f = 1;
+            pl  =  (long) atof ( &args[3] );
+            break;
+          case 'm': /* lower bound */
+            pm_f = 1;
+            pm  = (long ) atof ( &args[3] );
+            break;
+          case 'n': /* additional: p *= pn*(x+1) */
+            pn_f = 1;
+            pn  = atof ( &args[3] );
+            break;
+          case 's': /* additional: p = ps* (x+1)^2 */
+            ps_f = 1;
+            ps  = atof ( &args[3] );
+            break;
+          default:  /* unknown switch  value */
+            usage (vty);
+            return 1;
+          }
+        }
+        break;
+
+      default: /* unknoun case */
+        usage (vty);
+        return 1;
+      }
+  }
+
+
+  return 0;
+}
+
+
+/* generator of layered networks for the shortest paths problem;
+   extended DIMACS format for output */
+int
+gen_spgrid_topology (struct vty *vty, struct list *topology)
+{
+  /* ----- ajusting parameters ----- */
+
+  /* spanning */
+  if ( cl < cm ) { lx = cl; cl = cm; cm = lx; }
+
+  /* additional arcs */
+  if ( al < am ) { lx = al; al = am; am = lx; }
+
+  /* interlayered arcs */
+  if ( il < im ) { lx = il; il = im; im = lx; }
+
+  /* potential parameters */
+  if ( p_f )
+    {
+     if ( ! pl_f ) pl = il;
+     if ( ! pm_f ) pm = im;
+     if ( pl < pm ) { lx = pl; pl = pm; pm = lx; }
+    }
+
+  /* number of nodes and arcs */
+
+  n = (double)X *(double)Y + 1;
+
+  m  = (double)Y; /* arcs from source */
+
+  switch ( cw )
+  {
+   case PATH:
+    mc = (double)Y - 1;
+    break;
+   case CYCLE:
+    mc = (double)Y;
+    break;
+   case DOUBLE_CYCLE:
+    mc = 2*(double)Y;
+  }
+
+  m += (double)X * (double)mc;  /* spanning arcs */
+  m += (double)X * (double)ax;  /* additional arcs */
+
+  /* interlayered arcs */
+  for ( x = 0; x < X; x ++ )
+  {
+    dl = ( ( X - x - 1 ) + ( ih - 1 ) ) / ih;
+    if ( dl > ix ) dl = ix;
+    m += (double)Y * (double)dl;
+  }
+
+   /* artifical source parameters */
+  if ( s_f ) {
+    m += n; n ++ ;
+    if ( ! sm_f ) sm = sl;
+    if ( sl < sm ) { lx = sl; sl = sm; sm = lx; }
+  }
+
+  if ( n >= (double)MAXLONG || m >= (double)MAXLONG )
+  {
+    zlog_err ("Too large problem. It can't be generated\n");
+    exit (4);
+  }
+   else
+  {
+    n0 = (long)n; m0 = (long)m;
+  }
+
+  if ( ip_f )
+     mess = (long*) calloc ( Y, sizeof ( long ) );
+
+  /* printing title */
+  zlog_info ("Generating topology for ISIS");
+
+  source = ( s_f ) ? n0-1 : n0;
+
+  if ( p_f ) /* generating potentials */ {
+    p = (long*) calloc ( n0+1, sizeof (long) );
+    seed1 = 2*seed + 1;
+    init_rand ( seed1);
+    pl = pl - pm + 1;
+
+    for ( x = 0; x < X; x ++ )
+      for ( y = 0; y < Y; y ++ ) {
+        p_t = pm + nrand ( pl );
+        if ( pn_f ) p_t *= (long) ( (1 + x) * pn );
+        if ( ps_f ) p_t *= (long) ( (1 + x) * ( (1 + x) * ps ));
+
+        p[ NODE ( x, y ) ] = p_t;
+      }
+      p[n0] = 0;
+      if ( s_f ) p[n0-1] = 0;
+    }
+
+  if ( s_f ) /* additional arcs from artifical source */
+    {
+      seed2 = 3*seed + 1;
+      init_rand ( seed2 );
+      sl = sl - sm + 1;
+
+      for ( x = X - 1; x >= 0; x -- )
+        for ( y = Y - 1; y >= 0; y -- )
+        {
+          i = NODE ( x, y );
+          s = sm + nrand ( sl );
+          print_arc (vty, topology,  n0, i, s );
+        }
+
+      print_arc (vty, topology,  n0, n0-1, 0 );
+    }
+
+
+  /* ----- generating arcs within layers ----- */
+
+  init_rand ( seed );
+  cl = cl - cm + 1;
+  al = al - am + 1;
+
+  for ( x = 0; x < X; x ++ )
+   {
+  /* generating arcs within one layer */
+    for ( y = 0; y < Y-1; y ++ )
+    {
+       /* generating spanning graph */
+       i = NODE ( x, y );
+       j = NODE ( x, y+1 );
+       l = cm + nrand ( cl );
+       print_arc (vty, topology,  i, j, l );
+
+       if ( cw == DOUBLE_CYCLE )
+         {
+           l = cm + nrand ( cl );
+           print_arc (vty, topology,  j, i, l );
+         }
+     }
+
+    if ( cw <= CYCLE )
+      {
+        i = NODE ( x, Y-1 );
+        j = NODE ( x, 0 );
+        l = cm + nrand ( cl );
+        print_arc (vty, topology,  i, j, l );
+
+        if ( cw == DOUBLE_CYCLE )
+          {
+  	  l = cm + nrand ( cl );
+            print_arc (vty, topology,  j, i, l );
+          }
+       }
+
+  /* generating additional arcs */
+
+    for ( k = ax; k > 0; k -- )
+       {
+         y1 = nrand ( Y );
+         do
+            y2 = nrand ( Y );
+         while ( y2 == y1 );
+         i  = NODE ( x, y1 );
+         j  = NODE ( x, y2 );
+         l = am + nrand ( al );
+         print_arc (vty, topology,  i, j, l );
+       }
+   }
+
+  /* ----- generating interlayered arcs ------ */
+
+  il = il - im + 1;
+
+  /* arcs from the source */
+
+    for ( y = 0; y < Y; y ++ )
+      {
+        l = im + nrand ( il );
+        i = NODE ( 0, y );
+        print_arc (vty, topology,  source, i, l );
+      }
+
+  for ( x = 0; x < X-1; x ++ )
+   {
+  /* generating arcs from one layer */
+     for ( count = 0, xn = x + 1;
+           count < ix && xn < X;
+           count ++, xn += ih )
+      {
+        if ( ip_f )
+        for ( y = 0; y < Y; y ++ )
+  	mess[y] = y;
+
+        for ( y = 0; y < Y; y ++ )
+         {
+            i = NODE ( x, y );
+  	  dx = xn - x;
+  	  if ( ip_f )
+  	    {
+  	      yp = nrand(Y-y);
+  	      yn = mess[ yp ];
+                mess[ yp ] = mess[ Y - y - 1 ];
+  	    }
+  	  else
+               yn =  y;
+  	  j = NODE ( xn, yn );
+  	  l = im + nrand ( il );
+  	  if ( in != 0 )
+              l *= (long) ( in * dx );
+            if ( is_f )
+              l *= (long) ( ( is * dx ) * dx );
+            print_arc (vty, topology,  i, j, l );
+  	}
+      }
+   }
+  /* all is done */
+  return ext;
+
+return 0;
+}
+
+
+
diff --git a/isisd/topology/spgrid.h b/isisd/topology/spgrid.h
new file mode 100644
index 0000000..f96c00f
--- /dev/null
+++ b/isisd/topology/spgrid.h
@@ -0,0 +1,45 @@
+/*
+ * IS-IS Rout(e)ing protocol - topology/spgrid.h
+                               Routines for manipulation of SSN and SRM flags
+ * Copyright (C) 2001 Sampo Saaristo, Ofer Wald
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the GNU General Public Licenseas published by the Free 
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc., 
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * Based on:
+ * SPLIB Copyright C 1994 by Cherkassky, Goldberg, and Radzik
+ *
+ */
+#ifndef _ZEBRA_ISIS_TOPOLOGY_SPGRID_H
+#define _ZEBRA_ISIS_TOPOLOGY_SPGRID_H
+
+struct arc {
+  long from_node;
+  long to_node;
+  long distance;
+};
+
+int           gen_spgrid_topology (struct vty *vty, struct list *topology);
+int           spgrid_check_params (struct vty *vty, int argc, char **argv);
+
+
+#endif /* _ZEBRA_ISIS_TOPOLOGY_SPGRID_H */
+
+
+
+
+
+
diff --git a/isisd/topology/sprand.c b/isisd/topology/sprand.c
new file mode 100644
index 0000000..28b58b3
--- /dev/null
+++ b/isisd/topology/sprand.c
@@ -0,0 +1,499 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <values.h>
+
+#include "random.c"
+
+#define DASH '-'
+#define VERY_FAR 100000000
+
+/* generator of random networks for the shortest paths problem;
+   extended DIMACS format for output */
+
+main ( argc, argv )
+
+int argc;
+char* argv[];
+
+{
+
+char   args[30];
+
+long   n,
+       n0,
+       source,
+       i,
+       i0,
+       j,
+       dij;
+
+long   m,
+       m0,
+       mc,
+       k;
+
+long   *p,
+       p_t,
+       l,
+       lx;
+
+long   seed,
+       seed1,
+       seed2;
+
+int    ext=0;
+
+FILE   *fout;
+
+/* variables for lengths generating */
+/* initialized by default values */
+int    l_f = 0, ll_f = 0, lm_f = 0, ln_f = 0, ls_f = 0;
+long   ll = 10000,    /* length of the interval */
+       lm = 0;        /* minimal bound of the interval */
+double ln = 0,        /* l += ln * |i-j| */ 
+       ls = 0;        /* l += ls * |i-j|^2 */
+
+/* variables for connecting cycle(s) */
+int    c_f = 0, cl_f = 0, ch_f = 0, c_random = 1;
+long   cl = 1;        /* length of cycle arc */
+long   ch;            /* number of arcs in the cycle 
+                         n - by default */
+
+/* variables for artifical source */
+int    s_f = 0, sl_f = 0, sm_f = 0;
+long   sl   = VERY_FAR, /* upper bound of artifical arc */
+       sm,              /* lower bound of artifical arc */
+       s;  
+
+/* variables for potentials */
+int    p_f = 0, pl_f = 0, pm_f = 0, pn_f = 0, ps_f = 0,
+       pa_f = 0, pap_f = 0, pac_f = 0;
+long   pl,            /* length of the interval */
+       pm;            /* minimal bound of the interval */
+double pn = 0,        /* l += ln * |i-j| */ 
+       ps = 0,        /* l += ls * |i-j|^2 */
+       pap = 0,       /* part of nodes with alternative dustribution */
+       pac = -1;      /* multiplier for alternative distribution */
+
+int np;               /* number of parameter parsing now */
+
+#define PRINT_ARC( i, j, length )\
+{\
+l = length;\
+if ( p_f ) l += ( p[i] - p[j] );\
+printf ("a %8ld %8ld %12ld\n", i, j, l );\
+}
+
+  /* parsing  parameters */
+
+if ( argc < 2 ) goto usage;
+
+np = 0;
+
+strcpy ( args, argv[1] );
+
+  if ( ( args[0] == DASH ) && ( args[1] == 'h')
+     )
+      goto help;
+
+if ( argc < 4 ) goto usage;
+
+/* first parameter - number of nodes */
+np = 1;
+if ( ( n = atoi ( argv[1] ) )  <  2  )  goto usage;
+
+/* second parameter - number of arcs */
+np = 2;
+if ( ( m = atoi ( argv[2] ) )  <  n  )  goto usage;
+
+/* third parameter - seed */
+np=3;
+if ( ( seed = atoi ( argv[3] ) )  <=  0  )  goto usage;
+
+/* other parameters */
+
+for ( np = 4; np < argc; np ++ )
+  {
+    strcpy ( args, argv[np] );
+    if ( args[0] != DASH ) goto usage;
+
+    switch ( args[1] )
+      {
+
+      case 'l' : /* an interval for arc length */
+	l_f = 1;
+	switch ( args[2] )
+	  { 
+	  case 'l': /* length of the interval */
+	    ll_f = 1;
+	    ll  =  (long) atof ( &args[3] );
+	    break;
+	  case 'm': /* minimal bound */
+	    lm_f = 1;
+	    lm  = (long ) atof ( &args[3] );
+	    break;
+	  case 'n': /* additional length: l*|i-j| */
+	    ln_f = 1;
+	    ln  = atof ( &args[3] );
+	    break;
+	  case 's': /* additional length: l*|i-j|^2 */
+	    ls_f = 1;
+	    ls  = atof ( &args[3] );
+	    break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+	  }
+	break;
+
+      case 'c' : /* connecting cycle(s) */
+        c_f = 1;
+	switch ( args[2] )
+	  { 
+	  case 'l':
+            c_random = 0;
+	    cl_f = 1;
+	    cl  =  (long) atof ( &args[3] );
+            if ( cl < 0 ) goto usage;
+	    break;
+	  case 'h':
+	    ch_f = 1;
+	    ch  =  (long) atof ( &args[3] );
+            if ( ch < 2 || ch > n ) goto usage;
+	    break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+          }
+	break;
+
+      case 's' : /* additional source */
+        s_f = 1;
+	if ( strlen ( args ) > 2 )
+	{  
+	switch ( args[2] )
+	  { 
+	  case 'l': /* upper bound of art. arc */
+	    sl_f = 1;
+	    sl  =  (long) atof ( &args[3] );
+            break;
+	  case 'm': /* lower bound of art. arc */
+	    sm_f = 1;
+	    sm  =  (long) atof ( &args[3] );
+            break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+          }
+         }
+	break;
+
+      case 'p' : /* potentials */
+	p_f = 1;
+	if ( strlen ( args ) > 2 )
+	{  
+	switch ( args[2] )
+	  { 
+	  case 'l': /* length of the interval */
+	    pl_f = 1;
+	    pl  =  (long) atof ( &args[3] );
+	    break;
+	  case 'm': /* minimal bound */
+	    pm_f = 1;
+	    pm  = (long ) atof ( &args[3] );
+	    break;
+	  case 'n': /* additional length: l*|i-j| */
+	    pn_f = 1;
+	    pn  = atof ( &args[3] );
+	    break;
+	  case 's': /* additional length: l*|i-j|^2 */
+	    ps_f = 1;
+	    ps  = atof ( &args[3] );
+	    break;
+	  case 'a': /* bipolar distribution */
+	    pa_f = 1;
+	    switch ( args[3] )
+	      {
+	      case 'p': /* % of alternative potentials */
+                pap_f = 1;
+                pap  = atof ( &args[4] );
+		if ( pap < 0   ) pap = 0;
+		if ( pap > 100 ) pap = 100;
+                pap /= 100;
+		break;
+	      case 'c': /* multiplier */
+		pac_f = 1;
+		pac = atof ( &args[4] );
+		break;
+	      default: /* unknown switch value */
+		goto usage;
+	      }
+	    break;
+	  default:  /* unknown switch  value */
+	    goto usage;
+	  }
+      }
+	break;
+
+      default  : /* unknoun case */
+	goto usage;
+      }
+  }
+   
+
+/* ----- ajusting parameters ----- */
+
+n0 = n; m0 = m;
+
+/* length parameters */
+if ( ll < lm ) { lx = ll; ll = lm; lm = lx; }
+
+/* potential parameters */
+if ( p_f )
+  {
+   if ( ! pl_f ) pl = ll;
+   if ( ! pm_f ) pm = lm;
+   if ( pl < pm ) { lx = pl; pl = pm; pm = lx; }
+  }
+
+/* path(s) parameters */
+if ( ! ch_f ) ch = n;
+
+mc = n + (n-2) / (ch-1);
+if ( mc > m ) 
+  { fprintf ( stderr,
+              "Error: not enough arcs for generating connecting cycle(s)\n" );
+    exit (4);
+  }
+
+ /* artifical source parameters */
+if ( s_f )          
+   { m0 += n; n0 ++ ; 
+     if ( ! sm_f ) sm = sl;
+     if ( sl < sm ) { lx = sl; sl = sm; sm = lx; }
+   }
+
+/* printing title */
+printf ("c random network for shortest paths problem\n");
+printf ("c extended DIMACS format\nc\n" );
+
+/* name of the problem */
+printf ("t rd_%ld_%ld_%ld_", n, m, seed );
+if ( l_f )
+  printf ("%c", 'l');
+if ( c_f )
+  printf ("%c", 'c');
+if ( s_f )
+  printf ("%c", 's');
+if ( p_f )
+  printf ("%c", 'p');
+printf ("\nc\n");
+
+/* printing additional information  */
+if ( l_f )
+  printf ("c length -> min: %ld max: %ld k1: %.2f k2: %.2f\n",
+           lm, ll, ln, ls );
+if ( c_f )
+  {
+    if ( c_random )
+      printf ("c cycle -> number of arcs: %ld  arc length: random\n", ch);
+    else
+      printf ("c cycle -> number of arcs: %ld  arc length: %ld\n",
+	       ch, cl );
+  }
+if ( s_f )
+  printf ("c length of arcs from artifical source -> min: %ld max: %ld\n",
+           sm, sl );
+if ( p_f )
+  {
+  printf ("c potentials -> min: %ld max: %ld k1: %.2f k2: %.2f\n",
+	  pm, pl, pn, ps );
+  if ( pa_f )
+  printf ("c potentials -> part of alternative distribution: %.2f k: %.2f\n",
+          pap, pac );
+  }
+printf ("c\n" );
+
+
+printf ("p sp %8ld %8ld\nc\n", n0, m0 );
+
+source = ( s_f ) ? n0 : 1;
+printf ("n %8ld\nc\n", source );
+
+if ( p_f ) /* generating potentials */
+  {
+    p = (long*) calloc ( n+2, sizeof (long) );
+    seed1 = 2*seed + 1;
+    init_rand ( seed1);
+    pl = pl - pm + 1;
+
+    for ( i = 0; i <= n; i ++ )
+      {
+	p_t = pm + nrand ( pl );
+	if ( pn_f ) p_t += (long) ( i * pn );
+	if ( ps_f ) p_t += (long) ( i * ( i * ps ));
+	if ( pap_f )
+	    if ( rand01() < pap )
+		p_t = (long) ( p_t * pac );
+        p[i] = p_t;
+      }
+    p[n+1] = 0;
+  }
+
+
+if ( s_f ) /* additional arcs from artifical source */
+  {
+    seed2 = 3*seed + 1;
+    init_rand ( seed2 );
+    sl = sl - sm + 1;
+
+    for ( i = n; i > 1; i -- )
+      {
+	s = sm + nrand ( sl );
+	PRINT_ARC ( n0, i, s ) 
+      }
+
+    PRINT_ARC ( n0, 1, 0 )
+  }
+
+/* initialize random number generator */
+init_rand ( seed );
+ll = ll - lm + 1;
+
+/* generating connecting cycle(s) */
+if (c_random)
+  cl = lm + nrand ( ll );
+PRINT_ARC ( 1, 2, cl )
+if (c_random)
+  cl = lm + nrand ( ll );
+PRINT_ARC ( n, 1, cl )
+
+for ( i = 2; i < n; i ++ )
+  {
+    if (c_random)
+      cl = lm + nrand ( ll );
+
+    if ( ( (i-1) % (ch-1) ) != 0 )
+        PRINT_ARC ( i, i+1, cl )
+    else
+      { PRINT_ARC ( i,   1, cl )
+        if (c_random)
+          cl = lm + nrand ( ll );
+	PRINT_ARC ( 1, i+1, cl )
+      }
+  }
+
+/* generating random arcs */
+
+for ( k = 1; k <= m - mc; k ++ )
+  {
+    i = 1 + nrand ( n );
+
+    do
+    j = 1 + nrand ( n );
+    while ( j == i );
+
+    dij = ( i > j ) ? ( i - j ) : ( j - i );
+    l = lm + nrand ( ll );
+    if ( ln_f ) l += (long) ( dij * ln );
+    if ( ls_f ) l += (long) ( dij * ( dij * ls ) );
+    PRINT_ARC ( i, j, l );
+  }
+
+/* all is done */
+exit (ext);
+
+/* ----- wrong usage ----- */
+
+ usage:
+fprintf ( stderr,
+"\nusage: %s  n  m  seed  [ -ll#i -lm#i -cl#i -p -pl#i -pm#i ... ]\n\
+help:  %s -h\n\n", argv[0], argv[0] );
+
+if ( np > 0 )
+  fprintf ( stderr, "error in parameter # %d\n\n", np );   
+exit (4);
+
+/* ---- help ---- */
+
+ help:
+
+if ( args[2] == 'h') goto hhelp;
+
+fprintf ( stderr, 
+"\n'%s' - random network generator for shortest paths problem.\n\
+Generates problems in extended DIMACS format.\n\
+\n\
+   %s  n m seed [ -ll#i -lm#i -cl#i -p -pl#i -pm#i ... ]\n\
+   %s -hh\n\
+\n\
+                        #i - integer number   #f - real number\n\
+\n\
+-ll#i  - #i is the upper bound on arc lengths          (default 10000)\n\
+-lm#i  - #i is the lower bound on arc lengths          (default 0)\n\
+-cl#i  - #i is length of arcs in connecting cycle(s)   (default random)\n\
+-p     - generate potentials \n\
+-pl#i  - #i is the upper bound on potentials           (default ll)\n\
+-pm#i  - #i is the lower bound on potentials           (default lm)\n\
+\n\
+-hh    - extended help \n\n",
+argv[0], argv[0], argv[0] );
+
+exit (0);
+
+/* --------- sophisticated help ------------ */
+ hhelp:
+
+if ( argc < 3 )
+     fout = stderr;
+else
+     fout = fopen ( argv[2], "w" );
+
+if ( fout == NULL )
+{ fprintf ( stderr, "\nCan't open file  '%s' for writing help\n\n", argv[2] );
+  exit ( 2 );
+}
+
+fprintf (fout, 
+"\n'%s' - random network generator for shortest paths problem.\n\
+Generates problems in extended DIMACS format.\n\
+\n\
+   %s  n m seed [ -ll#i -lm#i -ln#f -ls#f\n\
+                      -p  -pl#i -pm#i -pn#f -ps#f -pap#i -pac#f\n\
+                      -cl#i -ch#i\n\
+                      -s -sl#i -sm#i\n\
+                    ]\n\
+   %s -hh file_name\n\
+\n\
+                        #i - integer number   #f - real number\n\
+\n\
+      Arc length parameters:\n\
+-ll#i  - #i is the upper bound on arc lengths          (default 10000)\n\
+-lm#i  - #i is the lower bound on arc lengths          (default 0)\n\
+-ln#f  - multipliy l(i, j) by #f * |i-j|               (default 0)\n\
+-ls#f  - multipliy l(i, j) by #f * |i-j|^2             (default 0)\n\
+\n\
+      Potential parameters:\n\
+-p     - generate potentials \n\
+-pl#i  - #i is the upper bound on potentials           (default ll)\n\
+-pm#i  - #i is the lower bound on potentials           (default lm)\n\
+-pn#f  - multiply p(i) by #f * i                       (default 0)\n\
+-ps#f  - multiply p(i) by #f * i^2                     (default 0)\n\
+-pap#i - percentage of alternative potential nodes     (default 0)\n\
+-pac#f - if i is alternative, multiply  p(i) by #f     (default -1)\n\
+\n\
+      Connecting cycle(s) parameters:\n\
+-cl#i  - #i is length of arcs in connecting cycle(s)   (default random)\n\
+-ch#i  - #i is length of connecting cycles             (default n)\n\
+\n\
+      Artificial source parameters:\n\
+-s     - generate artificial source with default connecting arc lengths\n\
+-sl#i  - #i is the upper bound on art. arc lengths    (default 100000000)\n\
+-sm#i  - #i is the lower bound on art. arc lengths    (default sl)\n\
+\n\
+-hh file_name  - save this help in the file 'file_name'\n\n",
+argv[0], argv[0], argv[0] );
+
+exit (0);
+}
+
+
+