Merge 'patch-tracking/4/proposed/netdef-solaris' into accepted
diff --git a/.gitignore b/.gitignore
index 48e6b38..e8de252 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,4 +37,4 @@
 *.loT
 m4/*.m4
 !m4/ax_sys_weak_alias.m4
-
+cscope.*
diff --git a/HACKING.md b/HACKING.md
new file mode 100644
index 0000000..3a449da
--- /dev/null
+++ b/HACKING.md
@@ -0,0 +1,500 @@
+---
+title: Conventions for working on Quagga 
+papersize: a4paper
+geometry: scale=0.82
+fontsize: 11pt
+toc: true
+date: \today
+include-before: 
+  \large This is a living document. Suggestions for updates, via the
+  [quagga-dev list](http://lists.quagga.net/mailman/listinfo/quagga-dev),
+  are welcome. \newpage
+...
+
+\newpage
+
+GUIDELINES FOR HACKING ON QUAGGA {#sec:guidelines}
+================================
+
+GNU coding standards apply.  Indentation follows the result of
+invoking GNU indent (as of 2.2.8a) with the -–nut argument.
+
+Originally, tabs were used instead of spaces, with tabs are every 8 columns. 
+However, tab’s interoperability issues mean space characters are now preferred for
+new changes. We generally only clean up whitespace when code is unmaintainable
+due to whitespace issues, to minimise merging conflicts.
+
+Be particularly careful not to break platforms/protocols that you
+cannot test.
+
+New code should have good comments, which explain why the code is correct.
+Changes to existing code should in many cases upgrade the comments when
+necessary for a reviewer to conclude that the change has no unintended
+consequences.
+
+Each file in the Git repository should have a git format-placeholder (like
+an RCS Id keyword), somewhere very near the top, commented out appropriately
+for the file type. The placeholder used for Quagga (replacing \<dollar\>
+with \$) is:
+
+`$QuaggaId: <dollar>Format:%an, %ai, %h<dollar> $`
+
+See line 2 of HACKING.tex, the source for this document, for an example.
+
+This placeholder string will be expanded out by the ‘git archive’ commands,
+which is used to generate the tar archives for snapshots and releases.
+
+Please document fully the proper use of a new function in the header file
+in which it is declared.  And please consult existing headers for
+documentation on how to use existing functions.  In particular, please consult
+these header files:
+
+<span>lib/log.h</span> logging levels and usage guidance
+
+<span>[more to be added]</span>
+
+If changing an exported interface, please try to deprecate the interface in
+an orderly manner. If at all possible, try to retain the old deprecated
+interface as is, or functionally equivalent. Make a note of when the
+interface was deprecated and guard the deprecated interface definitions in
+the header file, i.e.:
+
+    /* Deprecated: 20050406 */
+    #if !defined(QUAGGA_NO_DEPRECATED_INTERFACES)
+    #warning "Using deprecated <libname> (interface(s)|function(s))"
+    ...
+    #endif /* QUAGGA_NO_DEPRECATED_INTERFACES */
+
+This is to ensure that the core Quagga sources do not use the deprecated
+interfaces (you should update Quagga sources to use new interfaces, if
+applicable), while allowing external sources to continue to build. 
+Deprecated interfaces should be excised in the next unstable cycle.
+
+Note: If you wish, you can test for GCC and use a function
+marked with the ’deprecated’ attribute.  However, you must provide the
+warning for other compilers.
+
+If changing or removing a command definition, *ensure* that you
+properly deprecate it - use the \_DEPRECATED form of the appropriate DEFUN
+macro. This is *critical*.  Even if the command can no longer
+function, you *MUST* still implement it as a do-nothing stub.
+
+Failure to follow this causes grief for systems administrators, as an
+upgrade may cause daemons to fail to start because of unrecognised commands. 
+Deprecated commands should be excised in the next unstable cycle.  A list of
+deprecated commands should be collated for each release.
+
+See also section [sec:dll-versioning] below regarding SHARED LIBRARY
+VERSIONING.
+
+YOUR FIRST CONTRIBUTIONS
+========================
+
+Routing protocols can be very complex sometimes. Then, working with an
+Opensource community can be complex too, but usually friendly with
+anyone who is ready to be willing to do it properly.
+
+-   First, start doing simple tasks. Quagga’s patchwork is a good place
+    to start with. Pickup some patches, apply them on your git trie,
+    review them and send your ack’t or review comments. Then, a
+    maintainer will apply the patch if ack’t or the author will have to
+    provide a new update. It help a lot to drain the patchwork queues.
+    See <http://patchwork.quagga.net/project/quagga/list/>
+
+-   The more you’ll review patches from patchwork, the more the Quagga’s
+    maintainers will be willing to consider some patches you will be
+    sending.
+
+-   start using git clone, pwclient
+    <http://patchwork.quagga.net/help/pwclient/>
+
+        $ pwclient list -s new
+        ID    State        Name
+        --    -----        ----
+        179   New          [quagga-dev,6648] Re: quagga on FreeBSD 4.11 (gcc-2.95)
+        181   New          [quagga-dev,6660] proxy-arp patch
+        [...]
+
+        $ pwclient git-am 1046
+
+HANDY GUIDELINES FOR MAINTAINERS
+================================
+
+Get your cloned trie:
+
+      git clone vjardin@git.sv.gnu.org:/srv/git/quagga.git
+
+Apply some ack’t patches:
+
+      pwclient git-am 1046
+        Applying patch #1046 using 'git am'
+        Description: [quagga-dev,11595] zebra: route_unlock_node is missing in "show ip[v6] route <prefix>" commands
+        Applying: zebra: route_unlock_node is missing in "show ip[v6] route <prefix>" commands
+
+Run a quick review. If the ack’t was not done properly, you know who you have
+to blame.
+
+Push the patches:
+
+      git push
+
+Set the patch to accepted on patchwork
+
+      pwclient update -s Accepted 1046
+
+COMPILE-TIME CONDITIONAL CODE
+=============================
+
+Please think very carefully before making code conditional at compile time,
+as it increases maintenance burdens and user confusion. In particular,
+please avoid gratuitous -–enable-… switches to the configure script -
+typically code should be good enough to be in Quagga, or it shouldn’t be
+there at all.
+
+When code must be compile-time conditional, try have the compiler make it
+conditional rather than the C pre-processor - so that it will still be
+checked by the compiler, even if disabled. I.e.  this:
+
+        if (SOME_SYMBOL)
+          frobnicate();
+
+rather than:
+
+      #ifdef SOME_SYMBOL
+      frobnicate ();
+      #endif /* SOME_SYMBOL */
+
+Note that the former approach requires ensuring that SOME\_SYMBOL will
+be defined (watch your AC\_DEFINEs).
+
+COMMIT MESSAGES
+===============
+
+The commit message requirements are:
+
+-   The message *MUST* provide a suitable one-line summary followed by a
+    blank line as the very first line of the message, in the form:
+
+    `topic: high-level, one line summary`
+
+    Where topic would tend to be name of a subdirectory, and/or daemon, unless
+    there’s a more suitable topic (e.g. ’build’). This topic is used to
+    organise change summaries in release announcements.
+
+-   It should have a suitable “body”, which tries to address the
+    following areas, so as to help reviewers and future browsers of the
+    code-base understand why the change is correct (note also the code
+    comment requirements):
+
+    -   The motivation for the change (does it fix a bug, if so which?
+        add a feature?)
+
+    -   The general approach taken, and trade-offs versus any other
+        approaches.
+
+    -   Any testing undertaken or other information affecting the confidence
+        that can be had in the change.
+
+    -   Information to allow reviewers to be able to tell which specific
+        changes to the code are intended (and hence be able to spot any accidental
+        unintended changes).
+
+The one-line summary must be limited to 54 characters, and all other
+lines to 72 characters.
+
+Commit message bodies in the Quagga project have typically taken the
+following form:
+
+-   An optional introduction, describing the change generally.
+
+-   A short description of each specific change made, preferably:
+
+    -   file by file
+
+        -   function by function (use of “ditto”, or globs is allowed)
+
+Contributors are strongly encouraged to follow this form.
+
+This itemised commit messages allows reviewers to have confidence that the
+author has self-reviewed every line of the patch, as well as providing
+reviewers a clear index of which changes are intended, and descriptions for
+them (C-to-english descriptions are not desirable - some discretion is
+useful).  For short patches, a per-function/file break-down may be
+redundant.  For longer patches, such a break-down may be essential.  A
+contrived example (where the general discussion is obviously somewhat
+redundant, given the one-line summary):
+
+>     zebra: Enhance frob FSM to detect loss of frob
+>
+>     Add a new DOWN state to the frob state machine to allow the barinator to
+>     detect loss of frob.
+>
+>     * frob.h: (struct frob) Add DOWN state flag.
+>     * frob.c: (frob_change) set/clear DOWN appropriately on state change.
+>     * bar.c: (barinate) Check frob for DOWN state.
+
+Please have a look at the git commit logs to get a feel for what the norms
+are.
+
+Note that the commit message format follows git norms, so that “git log
+–oneline” will have useful output.
+
+HACKING THE BUILD SYSTEM
+========================
+
+If you change or add to the build system (configure.ac, any Makefile.am,
+etc.), try to check that the following things still work:
+
+-   make dist
+
+-   resulting dist tarball builds
+
+-   out-of-tree builds
+
+The quagga.net site relies on make dist to work to generate snapshots. It
+must work. Common problems are to forget to have some additional file
+included in the dist, or to have a make rule refer to a source file without
+using the srcdir variable.
+
+RELEASE PROCEDURE
+=================
+
+-   Tag the appropriate commit with a release tag (follow existing
+    conventions).
+
+    [This enables recreating the release, and is just good CM practice.]
+
+-   Create a fresh tar archive of the quagga.net repository, and do a
+    test build:
+
+            vim configure.ac
+            git commit -m "release: 0.99.99.99"
+            git tag -u 54CD2E60 quagga-0.99.99.99
+            git push savannah tag quagga-0.99.99.99
+
+            git archive --prefix=quagga-release/ quagga-0.99.99.99 | tar xC /tmp
+            git log quagga-0.99.99.98..quagga-0.99.99.99 > \
+               /tmp/quagga-release/quagga-0.99.99.99.changelog.txt
+            cd /tmp/quagga-release
+
+            autoreconf -i
+            ./configure
+            make
+            make dist-gzip
+
+            gunzip < quagga-0.99.99.99.tar.gz > quagga-0.99.99.99.tar
+            xz -6e < quagga-0.99.99.99.tar > quagga-0.99.99.99.tar.xz
+            gpg -u 54CD2E60 -a --detach-sign quagga-0.99.99.99.tar
+
+            scp quagga-0.99.99.99.* username@dl.sv.nongnu.org:/releases/quagga
+          
+
+    Do NOT do this in a subdirectory of the Quagga sources, autoconf
+    will think it’s a sub-package and fail to include neccessary files.
+
+-   Add the version number on https://bugzilla.quagga.net/, under
+    Administration, Products, “Quagga”, Edit versions, Add a version.
+
+-   Edit the wiki on
+    https://wiki.quagga.net/wiki/index.php/Release\_status
+
+-   Post a news entry on Savannah
+
+-   Send a mail to quagga-dev and quagga-users
+
+The tarball which ‘make dist’ creates is the tarball to be released! The
+git-archive step ensures you’re working with code corresponding to that in
+the official repository, and also carries out keyword expansion. If any
+errors occur, move tags as needed and start over from the fresh checkouts.
+Do not append to tarballs, as this has produced non-standards-conforming
+tarballs in the past.
+
+See also: <http://wiki.quagga.net/index.php/Main/Processes>
+
+[TODO: collation of a list of deprecated commands. Possibly can be
+scripted to extract from vtysh/vtysh\_cmd.c]
+
+TOOL VERSIONS
+=============
+
+Require versions of support tools are listed in INSTALL.quagga.txt.
+Required versions should only be done with due deliberation, as it can
+cause environments to no longer be able to compile quagga.
+
+SHARED LIBRARY VERSIONING {#sec:dll-versioning}
+=========================
+
+[this section is at the moment just gdt’s opinion]
+
+Quagga builds several shared libaries (lib/libzebra, ospfd/libospf,
+ospfclient/libsopfapiclient).  These may be used by external programs,
+e.g. a new routing protocol that works with the zebra daemon, or
+ospfapi clients.  The libtool info pages (node Versioning) explain
+when major and minor version numbers should be changed.  These values
+are set in Makefile.am near the definition of the library.  If you
+make a change that requires changing the shared library version,
+please update Makefile.am.
+
+libospf exports far more than it should, and is needed by ospfapi
+clients.  Only bump libospf for changes to functions for which it is
+reasonable for a user of ospfapi to call, and please err on the side
+of not bumping.
+
+There is no support intended for installing part of zebra.  The core
+library libzebra and the included daemons should always be built and
+installed together.
+
+GIT COMMIT SUBMISSION {#sec:git-submission}
+=====================
+
+The preferred method for submitting changes is to provide git commits via a
+publicly-accessible git repository, which the maintainers can easily pull.
+
+The commits should be in a branch based off the Quagga.net master - a
+“feature branch”.  Ideally there should be no commits to this branch other
+than those in master, and those intended to be submitted.  However, merge
+commits to this branch from the Quagga master are permitted, though strongly
+discouraged - use another (potentially local and throw-away) branch to test
+merge with the latest Quagga master.
+
+Recommended practice is to keep different logical sets of changes on
+separate branches - “topic” or “feature” branches.  This allows you to still
+merge them together to one branch (potentially local and/or “throw-away”)
+for testing or use, while retaining smaller, independent branches that are
+easier to merge.
+
+All content guidelines in section [sec:patch-submission], PATCH
+SUBMISSION apply.
+
+PATCH SUBMISSION {#sec:patch-submission}
+================
+
+-   For complex changes, contributors are strongly encouraged to first
+    start a design discussion on the quagga-dev list *before* starting
+    any coding.
+
+-   Send a clean diff against the ’master’ branch of the quagga.git
+    repository, in unified diff format, preferably with the ’-p’
+    argument to show C function affected by any chunk, and with the -w
+    and -b arguments to minimise changes. E.g:
+
+    git diff -up mybranch..remotes/quagga.net/master
+
+    It is preferable to use git format-patch, and even more preferred to
+    publish a git repository (see GIT COMMIT SUBMISSION, section
+    [sec:git-submission]).
+
+    If not using git format-patch, Include the commit message in the
+    email.
+
+-   After a commit, code should have comments explaining to the reviewer
+    why it is correct, without reference to history. The commit message
+    should explain why the change is correct.
+
+-   Include NEWS entries as appropriate.
+
+-   Include only one semantic change or group of changes per patch.
+
+-   Do not make gratuitous changes to whitespace. See the w and b
+    arguments to diff.
+
+-   Changes should be arranged so that the least controversial and most
+    trivial are first, and the most complex or more controversial are
+    last. This will maximise how many the Quagga maintainers can merge,
+    even if some other commits need further work.
+
+-   Providing a unit-test is strongly encouraged. Doing so will make it
+    much easier for maintainers to have confidence that they will be
+    able to support your change.
+
+-   New code should be arranged so that it easy to verify and test. E.g.
+    stateful logic should be separated out from functional logic as much
+    as possible: wherever possible, move complex logic out to smaller
+    helper functions which access no state other than their arguments.
+
+-   State on which platforms and with what daemons the patch has been
+    tested. Understand that if the set of testing locations is small,
+    and the patch might have unforeseen or hard to fix consequences that
+    there may be a call for testers on quagga-dev, and that the patch
+    may be blocked until test results appear.
+
+    If there are no users for a platform on quagga-dev who are able and
+    willing to verify -current occasionally, that platform may be
+    dropped from the “should be checked” list.
+
+PATCH APPLICATION
+=================
+
+-   Only apply patches that meet the submission guidelines.
+
+-   If the patch might break something, issue a call for testing on the
+    mailing-list.
+
+-   Give an appropriate commit message (see above), and use the –author
+    argument to git-commit, if required, to ensure proper attribution
+    (you should still be listed as committer)
+
+-   Immediately after commiting, double-check (with git-log and/or
+    gitk). If there’s a small mistake you can easily fix it with ‘git
+    commit –amend ..’
+
+-   When merging a branch, always use an explicit merge commit. Giving
+    –no-ff ensures a merge commit is created which documents “this human
+    decided to merge this branch at this time”.
+
+STABLE PLATFORMS AND DAEMONS
+============================
+
+The list of platforms that should be tested follow.  This is a list
+derived from what quagga is thought to run on and for which
+maintainers can test or there are people on quagga-dev who are able
+and willing to verify that -current does or does not work correctly.
+
+-   BSD (Free, Net or Open, any platform)
+
+-   GNU/Linux (any distribution, i386)
+
+-   Solaris (strict alignment, any platform)
+
+-   future: NetBSD/sparc64
+
+The list of daemons that are thought to be stable and that should be
+tested are:
+
+-   zebra
+
+-   bgpd
+
+-   ripd
+
+-   ospfd
+
+-   ripngd
+
+Daemons which are in a testing phase are
+
+-   ospf6d
+
+-   isisd
+
+-   watchquagga
+
+IMPORT OR UPDATE VENDOR SPECIFIC ROUTING PROTOCOLS
+==================================================
+
+The source code of Quagga is based on two vendors:
+
+`zebra_org` (<http://www.zebra.org/>) `isisd_sf`
+(<http://isisd.sf.net/>)
+
+To import code from further sources, e.g. for archival purposes without
+necessarily having to review and/or fix some changeset, create a branch
+from ‘master’:
+
+        git checkout -b archive/foo master
+        <apply changes>
+        git commit -a "Joe Bar <joe@example.com>"
+        git push quagga archive/foo
+
+presuming ‘quagga’ corresponds to a file in your .git/remotes with
+configuration for the appropriate Quagga.net repository.
diff --git a/HACKING.tex b/HACKING.tex
deleted file mode 100644
index be86ae1..0000000
--- a/HACKING.tex
+++ /dev/null
@@ -1,533 +0,0 @@
-%% -*- mode: text; -*-
-%% $QuaggaId: Format:%an, %ai, %h$ $
-
-\documentclass[oneside]{article}
-\usepackage{parskip}
-\usepackage[bookmarks,colorlinks=true]{hyperref}
-
-\title{Conventions for working on Quagga}
-
-\begin{document}
-\maketitle
-
-This is a living document. Suggestions for updates, via the
-\href{http://lists.quagga.net/mailman/listinfo/quagga-dev}{quagga-dev list},
-are welcome.
-
-\tableofcontents
-
-\section{GUIDELINES FOR HACKING ON QUAGGA}
-\label{sec:guidelines}
-
-
-GNU coding standards apply.  Indentation follows the result of
-invoking GNU indent (as of 2.2.8a) with the --nut argument.
-
-Originally, tabs were used instead of spaces, with tabs are every 8 columns. 
-However, tab's interoperability issues mean space characters are now preferred for
-new changes. We generally only clean up whitespace when code is unmaintainable
-due to whitespace issues, to minimise merging conflicts.
-
-Be particularly careful not to break platforms/protocols that you
-cannot test.
-
-New code should have good comments, which explain why the code is correct.
-Changes to existing code should in many cases upgrade the comments when
-necessary for a reviewer to conclude that the change has no unintended
-consequences.
-
-Each file in the Git repository should have a git format-placeholder (like
-an RCS Id keyword), somewhere very near the top, commented out appropriately
-for the file type. The placeholder used for Quagga (replacing <dollar> with
-\$) is:
-
-	\verb|$QuaggaId: <dollar>Format:%an, %ai, %h<dollar> $|
-
-See line 2 of HACKING.tex, the source for this document, for an example.
-
-This placeholder string will be expanded out by the `git archive' commands,
-which is used to generate the tar archives for snapshots and releases.
-
-Please document fully the proper use of a new function in the header file
-in which it is declared.  And please consult existing headers for
-documentation on how to use existing functions.  In particular, please consult
-these header files:
-
-\begin{description}
-  \item{lib/log.h}	logging levels and usage guidance
-  \item{[more to be added]}
-\end{description}
-
-If changing an exported interface, please try to deprecate the interface in
-an orderly manner. If at all possible, try to retain the old deprecated
-interface as is, or functionally equivalent. Make a note of when the
-interface was deprecated and guard the deprecated interface definitions in
-the header file, i.e.:
-
-\begin{verbatim}
-/* Deprecated: 20050406 */
-#if !defined(QUAGGA_NO_DEPRECATED_INTERFACES)
-#warning "Using deprecated <libname> (interface(s)|function(s))"
-...
-#endif /* QUAGGA_NO_DEPRECATED_INTERFACES */
-\end{verbatim}
-
-This is to ensure that the core Quagga sources do not use the deprecated
-interfaces (you should update Quagga sources to use new interfaces, if
-applicable), while allowing external sources to continue to build. 
-Deprecated interfaces should be excised in the next unstable cycle.
-
-Note: If you wish, you can test for GCC and use a function
-marked with the 'deprecated' attribute. However, you must provide the
-warning for other compilers.
-
-If changing or removing a command definition, \emph{ensure} that you
-properly deprecate it - use the \_DEPRECATED form of the appropriate DEFUN
-macro.  This is \emph{critical}.  Even if the command can no longer
-function, you \emph{MUST} still implement it as a do-nothing stub. 
-
-Failure to follow this causes grief for systems administrators, as an
-upgrade may cause daemons to fail to start because of unrecognised commands. 
-Deprecated commands should be excised in the next unstable cycle.  A list of
-deprecated commands should be collated for each release.
-
-See also section~\ref{sec:dll-versioning} below regarding SHARED LIBRARY
-VERSIONING.
-
-\section{YOUR FIRST CONTRIBUTIONS}
-
-Routing protocols can be very complex sometimes. Then, working with an
-Opensource community can be complex too, but usually friendly with
-anyone who is ready to be willing to do it properly.
-
-\begin{itemize}
-
-  \item First, start doing simple tasks. Quagga's patchwork is a good place
-        to start with. Pickup some patches, apply them on your git trie,
-        review them and send your ack't or review comments. Then, a
-        maintainer will apply the patch if ack't or the author will
-        have to provide a new update. It help a lot to drain the
-        patchwork queues.
-        See \url{http://patchwork.quagga.net/project/quagga/list/}
-
-  \item The more you'll review patches from patchwork, the more the
-        Quagga's maintainers will be willing to consider some patches you will
-        be sending.
-
-  \item start using git clone, pwclient \url{http://patchwork.quagga.net/help/pwclient/}
-
-\begin{verbatim}
-$ pwclient list -s new
-ID    State        Name
---    -----        ----
-179   New          [quagga-dev,6648] Re: quagga on FreeBSD 4.11 (gcc-2.95)
-181   New          [quagga-dev,6660] proxy-arp patch
-[...]
-
-$ pwclient git-am 1046
-\end{verbatim}
-
-\end{itemize}
-
-\section{HANDY GUIDELINES FOR MAINTAINERS}
-
-Get your cloned trie:
-\begin{verbatim}
-  git clone vjardin@git.sv.gnu.org:/srv/git/quagga.git
-\end{verbatim}
-
-Apply some ack't patches:
-\begin{verbatim}
-  pwclient git-am 1046
-    Applying patch #1046 using 'git am'
-    Description: [quagga-dev,11595] zebra: route_unlock_node is missing in "show ip[v6] route <prefix>" commands
-    Applying: zebra: route_unlock_node is missing in "show ip[v6] route <prefix>" commands
-\end{verbatim}
-
-Run a quick review. If the ack't was not done properly, you know who you have
-to blame.
-
-Push the patches:
-\begin{verbatim}
-  git push
-\end{verbatim}
-
-Set the patch to accepted on patchwork
-\begin{verbatim}
-  pwclient update -s Accepted 1046
-\end{verbatim}
-
-\section{COMPILE-TIME CONDITIONAL CODE}
-
-Please think very carefully before making code conditional at compile time,
-as it increases maintenance burdens and user confusion. In particular,
-please avoid gratuitous --enable-\ldots switches to the configure script -
-typically code should be good enough to be in Quagga, or it shouldn't be
-there at all. 
-
-When code must be compile-time conditional, try have the compiler make it
-conditional rather than the C pre-processor - so that it will still be
-checked by the compiler, even if disabled. I.e.  this:
-
-\begin{verbatim}
-    if (SOME_SYMBOL)
-      frobnicate();
-\end{verbatim}
-
-rather than:
-
-\begin{verbatim}
-  #ifdef SOME_SYMBOL
-  frobnicate ();
-  #endif /* SOME_SYMBOL */
-\end{verbatim}
-
-Note that the former approach requires ensuring that SOME\_SYMBOL will be
-defined (watch your AC\_DEFINEs).
-
-
-\section{COMMIT MESSAGES}
-
-The commit message requirements are:
-
-\begin{itemize}
-
-\item The message \emph{MUST} provide a suitable one-line summary followed
-      by a blank line as the very first line of the message, in the form:
-
-  \verb|topic: high-level, one line summary|
-
-  Where topic would tend to be name of a subdirectory, and/or daemon, unless
-  there's a more suitable topic (e.g.  'build').  This topic is used to
-  organise change summaries in release announcements.
-
-\item It should have a suitable "body", which tries  to address the
-      following areas, so as to help reviewers and future browsers of the
-      code-base understand why the change is correct (note also the code
-      comment requirements):
-
-  \begin{itemize}
-  
-  \item The motivation for the change (does it fix a bug, if so which? 
-        add a feature?)
-  
-  \item The general approach taken, and trade-offs versus any other
-        approaches.
-  
-  \item Any testing undertaken or other information affecting the confidence
-        that can be had in the change.
-  
-  \item Information to allow reviewers to be able to tell which specific
-        changes to the code are intended (and hence be able to spot any accidental
-        unintended changes).
-
-  \end{itemize}
-\end{itemize}
-
-The one-line summary must be limited to 54 characters, and all other
-lines to 72 characters.
-
-Commit message bodies in the Quagga project have typically taken the
-following form:
-
-\begin{itemize}
-\item An optional introduction, describing the change generally.
-\item A short description of each specific change made, preferably:
-  \begin{itemize} \item file by file
-    \begin{itemize} \item function by function (use of "ditto", or globs is
-                          allowed)
-    \end{itemize}
-  \end{itemize}
-\end{itemize}
-
-Contributors are strongly encouraged to follow this form.
-
-This itemised commit messages allows reviewers to have confidence that the
-author has self-reviewed every line of the patch, as well as providing
-reviewers a clear index of which changes are intended, and descriptions for
-them (C-to-english descriptions are not desirable - some discretion is
-useful).  For short patches, a per-function/file break-down may be
-redundant.  For longer patches, such a break-down may be essential.  A
-contrived example (where the general discussion is obviously somewhat
-redundant, given the one-line summary):
-
-\begin{quote}\begin{verbatim}
-zebra: Enhance frob FSM to detect loss of frob
-
-Add a new DOWN state to the frob state machine to allow the barinator to
-detect loss of frob.
-
-* frob.h: (struct frob) Add DOWN state flag.
-* frob.c: (frob_change) set/clear DOWN appropriately on state change.
-* bar.c: (barinate) Check frob for DOWN state.
-\end{verbatim}\end{quote}
-
-Please have a look at the git commit logs to get a feel for what the norms
-are.
-
-Note that the commit message format follows git norms, so that ``git
-log --oneline'' will have useful output.
-
-\section{HACKING THE BUILD SYSTEM}
-
-If you change or add to the build system (configure.ac, any Makefile.am,
-etc.), try to check that the following things still work:
-
-\begin{itemize}
-\item make dist
-\item resulting dist tarball builds
-\item out-of-tree builds
-\end{itemize}
-
-The quagga.net site relies on make dist to work to generate snapshots. It
-must work. Common problems are to forget to have some additional file
-included in the dist, or to have a make rule refer to a source file without
-using the srcdir variable.
-
-
-\section{RELEASE PROCEDURE}
-
-\begin{itemize}
-\item Tag the appropriate commit with a release tag (follow existing
-  conventions).
-  
-  [This enables recreating the release, and is just good CM practice.]
-
-\item Create a fresh tar archive of the quagga.net repository, and do a test
-  build:
-
-  \begin{verbatim}
-    vim configure.ac
-    git commit -m "release: 0.99.99.99"
-    git tag -u 54CD2E60 quagga-0.99.99.99
-    git push savannah tag quagga-0.99.99.99
-
-    git archive --prefix=quagga-release/ quagga-0.99.99.99 | tar xC /tmp
-    git log quagga-0.99.99.98..quagga-0.99.99.99 > \
-       /tmp/quagga-release/quagga-0.99.99.99.changelog.txt
-    cd /tmp/quagga-release
-
-    autoreconf -i
-    ./configure
-    make
-    make dist-gzip
-
-    gunzip < quagga-0.99.99.99.tar.gz > quagga-0.99.99.99.tar
-    xz -6e < quagga-0.99.99.99.tar > quagga-0.99.99.99.tar.xz
-    gpg -u 54CD2E60 -a --detach-sign quagga-0.99.99.99.tar
-
-    scp quagga-0.99.99.99.* username@dl.sv.nongnu.org:/releases/quagga
-  \end{verbatim}
-
-  Do NOT do this in a subdirectory of the Quagga sources, autoconf will think
-  it's a sub-package and fail to include neccessary files.
-
-\item Add the version number on https://bugzilla.quagga.net/, under
-  Administration, Products, "Quagga", Edit versions, Add a version.
-\item Edit the wiki on https://wiki.quagga.net/wiki/index.php/Release\_status
-\item Post a news entry on Savannah
-\item Send a mail to quagga-dev and quagga-users
-\end{itemize}
-
-The tarball which `make dist' creates is the tarball to be released! The
-git-archive step ensures you're working with code corresponding to that in
-the official repository, and also carries out keyword expansion. If any
-errors occur, move tags as needed and start over from the fresh checkouts.
-Do not append to tarballs, as this has produced non-standards-conforming
-tarballs in the past.
-
-See also: \url{http://wiki.quagga.net/index.php/Main/Processes}
-
-[TODO: collation of a list of deprecated commands. Possibly can be scripted
-to extract from vtysh/vtysh\_cmd.c]
-
-
-\section{TOOL VERSIONS}
-
-Require versions of support tools are listed in INSTALL.quagga.txt.
-Required versions should only be done with due deliberation, as it can
-cause environments to no longer be able to compile quagga.
-
-
-\section{SHARED LIBRARY VERSIONING}
-\label{sec:dll-versioning}
-
-[this section is at the moment just gdt's opinion]
-
-Quagga builds several shared libaries (lib/libzebra, ospfd/libospf, 
-ospfclient/libsopfapiclient).  These may be used by external programs,
-e.g. a new routing protocol that works with the zebra daemon, or
-ospfapi clients.  The libtool info pages (node Versioning) explain
-when major and minor version numbers should be changed.  These values
-are set in Makefile.am near the definition of the library.  If you
-make a change that requires changing the shared library version,
-please update Makefile.am.
-
-libospf exports far more than it should, and is needed by ospfapi
-clients.  Only bump libospf for changes to functions for which it is
-reasonable for a user of ospfapi to call, and please err on the side
-of not bumping.
-
-There is no support intended for installing part of zebra.  The core
-library libzebra and the included daemons should always be built and
-installed together.
-
-
-\section{GIT COMMIT SUBMISSION}
-\label{sec:git-submission}
-
-The preferred method for submitting changes is to provide git commits via a
-publicly-accessible git repository, which the maintainers can easily pull.
-
-The commits should be in a branch based off the Quagga.net master - a
-"feature branch".  Ideally there should be no commits to this branch other
-than those in master, and those intended to be submitted.  However, merge
-commits to this branch from the Quagga master are permitted, though strongly
-discouraged - use another (potentially local and throw-away) branch to test
-merge with the latest Quagga master.
-
-Recommended practice is to keep different logical sets of changes on
-separate branches - "topic" or "feature" branches.  This allows you to still
-merge them together to one branch (potentially local and/or "throw-away")
-for testing or use, while retaining smaller, independent branches that are
-easier to merge.
-
-All content guidelines in section \ref{sec:patch-submission}, PATCH
-SUBMISSION apply.
-
-
-\section{PATCH SUBMISSION}
-\label{sec:patch-submission}
-
-\begin{itemize}
-
-\item For complex changes, contributors are strongly encouraged to first
-      start a design discussion on the quagga-dev list \emph{before}
-      starting any coding.
-
-\item Send a clean diff against the 'master' branch of the quagga.git
-      repository, in unified diff format, preferably with the '-p' argument to
-      show C function affected by any chunk, and with the -w and -b arguments to
-      minimise changes. E.g:
-
-     git diff -up mybranch..remotes/quagga.net/master
-
-     It is preferable to use git format-patch, and even more preferred to
-     publish a git repository (see GIT COMMIT SUBMISSION, section
-     \ref{sec:git-submission}).
-
-     If not using git format-patch, Include the commit message in the email.
-
-\item After a commit, code should have comments explaining to the reviewer
-      why it is correct, without reference to history.  The commit message
-      should explain why the change is correct.
-
-\item Include NEWS entries as appropriate.
-
-\item Include only one semantic change or group of changes per patch.
-
-\item Do not make gratuitous changes to whitespace. See the w and b arguments
-      to diff.
-
-\item Changes should be arranged so that the least controversial and most
-      trivial are first, and the most complex or more controversial are
-      last.  This will maximise how many the Quagga maintainers can merge,
-      even if some other commits need further work.
-
-\item Providing a unit-test is strongly encouraged. Doing so will make it
-      much easier for maintainers to have confidence that they will be able
-      to support your change.
-
-\item New code should be arranged so that it easy to verify and test. E.g. 
-      stateful logic should be separated out from functional logic as much as
-      possible: wherever possible, move complex logic out to smaller helper
-      functions which access no state other than their arguments.
-
-\item State on which platforms and with what daemons the patch has been
-      tested.  Understand that if the set of testing locations is small,
-      and the patch might have unforeseen or hard to fix consequences that
-      there may be a call for testers on quagga-dev, and that the patch
-      may be blocked until test results appear.
-
-      If there are no users for a platform on quagga-dev who are able and
-      willing to verify -current occasionally, that platform may be
-      dropped from the "should be checked" list.
-
-\end{itemize}
-
-\section{PATCH APPLICATION}
-
-\begin{itemize}
-
-\item Only apply patches that meet the submission guidelines.
-
-\item If the patch might break something, issue a call for testing on the
-      mailing-list.
-
-\item Give an appropriate commit message (see above), and use the --author
-      argument to git-commit, if required, to ensure proper attribution (you
-      should still be listed as committer)
-
-\item Immediately after commiting, double-check (with git-log and/or gitk).
-      If there's a small mistake you can easily fix it with `git commit
-      --amend ..'
-
-\item When merging a branch, always use an explicit merge commit. Giving
-      --no-ff ensures a merge commit is created which documents ``this human
-      decided to merge this branch at this time''.
-\end{itemize}
-
-\section{STABLE PLATFORMS AND DAEMONS}
-
-The list of platforms that should be tested follow.  This is a list
-derived from what quagga is thought to run on and for which
-maintainers can test or there are people on quagga-dev who are able
-and willing to verify that -current does or does not work correctly.
-
-\begin{itemize}
-  \item BSD (Free, Net or Open, any platform)
-  \item GNU/Linux (any distribution, i386)
-  \item Solaris (strict alignment, any platform)
-  \item future: NetBSD/sparc64
-\end{itemize}
-
-The list of daemons that are thought to be stable and that should be
-tested are:
-
-\begin{itemize}
-  \item zebra
-  \item bgpd
-  \item ripd
-  \item ospfd
-  \item ripngd
-\end{itemize}
-Daemons which are in a testing phase are
-
-\begin{itemize}
-  \item ospf6d
-  \item isisd
-  \item watchquagga
-\end{itemize}
-
-\section{IMPORT OR UPDATE VENDOR SPECIFIC ROUTING PROTOCOLS}
-
-The source code of Quagga is based on two vendors:
-
-   \verb|zebra_org| (\url{http://www.zebra.org/})
-   \verb|isisd_sf| (\url{http://isisd.sf.net/})
-
-To import code from further sources, e.g. for archival purposes without
-necessarily having to review and/or fix some changeset, create a branch from
-`master':
-
-\begin{verbatim}
-	git checkout -b archive/foo master
-	<apply changes>
-	git commit -a "Joe Bar <joe@example.com>"
-	git push quagga archive/foo
-\end{verbatim}
-
-presuming `quagga' corresponds to a file in your .git/remotes with
-configuration for the appropriate Quagga.net repository.
-
-\end{document}
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 0aec3ef..9d49f34 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -98,6 +98,12 @@
   return (XMALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
 }
 
+static void
+assegment_data_free (as_t *asdata)
+{
+  XFREE (MTYPE_AS_SEG_DATA, asdata);
+}
+
 /* Get a new segment. Note that 0 is an allowed length,
  * and will result in a segment with no allocated data segment.
  * the caller should immediately assign data to the segment, as the segment
@@ -126,7 +132,7 @@
     return;
   
   if (seg->as)
-    XFREE (MTYPE_AS_SEG_DATA, seg->as);
+    assegment_data_free (seg->as);
   memset (seg, 0xfe, sizeof(struct assegment));
   XFREE (MTYPE_AS_SEG, seg);
   
@@ -194,13 +200,14 @@
   if (num >= AS_SEGMENT_MAX)
     return seg; /* we don't do huge prepends */
   
-  newas = assegment_data_new (seg->length + num);
-
+  if ((newas = assegment_data_new (seg->length + num)) == NULL)
+    return seg;
+  
   for (i = 0; i < num; i++)
     newas[i] = asnum;
 
   memcpy (newas + num, seg->as, ASSEGMENT_DATA_SIZE (seg->length, 1));
-  XFREE (MTYPE_AS_SEG_DATA, seg->as);
+  assegment_data_free (seg->as);
   seg->as = newas;
   seg->length += num;
 
@@ -1879,6 +1886,7 @@
 void
 aspath_finish (void)
 {
+  hash_clean (ashash, (void (*)(void *))aspath_free);
   hash_free (ashash);
   ashash = NULL;
   
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 3f09103..ef19bc4 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -203,6 +203,7 @@
 static void
 cluster_finish (void)
 {
+  hash_clean (cluster_hash, (void (*)(void *))cluster_free);
   hash_free (cluster_hash);
   cluster_hash = NULL;
 }
@@ -279,6 +280,7 @@
 static void
 transit_finish (void)
 {
+  hash_clean (transit_hash, (void (*)(void *))transit_free);
   hash_free (transit_hash);
   transit_hash = NULL;
 }
@@ -452,9 +454,20 @@
   attrhash = hash_create (attrhash_key_make, attrhash_cmp);
 }
 
+/*
+ * special for hash_clean below
+ */
+static void
+attr_vfree (void *attr)
+{
+  bgp_attr_extra_free ((struct attr *)attr);
+  XFREE (MTYPE_ATTR, attr);
+}
+
 static void
 attrhash_finish (void)
 {
+  hash_clean(attrhash, attr_vfree);
   hash_free (attrhash);
   attrhash = NULL;
 }
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 05c30ff..359fce3 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -115,7 +115,7 @@
     
   damp->t_reuse = NULL;
   damp->t_reuse =
-    thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
+    thread_add_timer (bm->master, bgp_reuse_timer, NULL, DELTA_REUSE);
 
   t_now = bgp_clock ();
 
@@ -447,7 +447,7 @@
   /* Register reuse timer.  */
   if (! damp->t_reuse)
     damp->t_reuse = 
-      thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
+      thread_add_timer (bm->master, bgp_reuse_timer, NULL, DELTA_REUSE);
 
   return 0;
 }
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index a3c9526..3d88dee 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -156,13 +156,13 @@
 	  secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour;
 	  interval = interval - secs_into_day % interval; /* always > 0 */
 	}
-      bgp_dump->t_interval = thread_add_timer (master, bgp_dump_interval_func, 
+      bgp_dump->t_interval = thread_add_timer (bm->master, bgp_dump_interval_func,
 					       bgp_dump, interval);
     }
   else
     {
       /* One-off dump: execute immediately, don't affect any scheduled dumps */
-      bgp_dump->t_interval = thread_add_event (master, bgp_dump_interval_func,
+      bgp_dump->t_interval = thread_add_event (bm->master, bgp_dump_interval_func,
 					       bgp_dump, 0);
     }
 
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index a749f8e..752d6e2 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -26,7 +26,7 @@
 #define BGP_READ_ON(T,F,V)			\
   do {						\
     if (!(T) && (peer->status != Deleted))	\
-      THREAD_READ_ON(master,T,F,peer,V);	\
+      THREAD_READ_ON(bm->master,T,F,peer,V);	\
   } while (0)
 
 #define BGP_READ_OFF(T)				\
@@ -38,7 +38,7 @@
 #define BGP_WRITE_ON(T,F,V)			\
   do {						\
     if (!(T) && (peer->status != Deleted))	\
-      THREAD_WRITE_ON(master,(T),(F),peer,(V)); \
+      THREAD_WRITE_ON(bm->master,(T),(F),peer,(V)); \
   } while (0)
     
 #define BGP_WRITE_OFF(T)			\
@@ -50,7 +50,7 @@
 #define BGP_TIMER_ON(T,F,V)			\
   do {						\
     if (!(T) && (peer->status != Deleted))	\
-      THREAD_TIMER_ON(master,(T),(F),peer,(V)); \
+      THREAD_TIMER_ON(bm->master,(T),(F),peer,(V)); \
   } while (0)
 
 #define BGP_TIMER_OFF(T)			\
@@ -62,13 +62,13 @@
 #define BGP_EVENT_ADD(P,E)			\
   do {						\
     if ((P)->status != Deleted)			\
-      thread_add_event (master, bgp_event, (P), (E)); \
+      thread_add_event (bm->master, bgp_event, (P), (E)); \
   } while (0)
 
 #define BGP_EVENT_FLUSH(P)			\
   do { 						\
     assert (peer); 				\
-    thread_cancel_event (master, (P)); 		\
+    thread_cancel_event (bm->master, (P)); 	\
   } while (0)
 
 /* Prototypes. */
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 7c2988c..591a6f9 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -37,6 +37,7 @@
 #include "plist.h"
 #include "stream.h"
 #include "vrf.h"
+#include "workqueue.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_attr.h"
@@ -105,9 +106,6 @@
 /* Route retain mode flag. */
 static int retain_mode = 0;
 
-/* Master of threads. */
-struct thread_master *master;
-
 /* Manually specified configuration file name.  */
 char *config_file = NULL;
 
@@ -199,10 +197,12 @@
 {
   zlog_notice ("Terminating on signal");
 
-  if (! retain_mode)
-    bgp_terminate ();
+  if (! retain_mode) 
+    {
+      bgp_terminate ();
+      zprivs_terminate (&bgpd_privs);
+    }
 
-  zprivs_terminate (&bgpd_privs);
   bgp_exit (0);
 }
 
@@ -237,7 +237,27 @@
   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
     bgp_delete (bgp);
   list_free (bm->bgp);
-
+  bm->bgp = NULL;
+  
+  /*
+   * bgp_delete can re-allocate the process queues after they were
+   * deleted in bgp_terminate. delete them again.
+   *
+   * It might be better to ensure the RIBs (including static routes)
+   * are cleared by bgp_terminate() during its call to bgp_cleanup_routes(),
+   * which currently only deletes the kernel routes.
+   */
+  if (bm->process_main_queue)
+    {
+     work_queue_free (bm->process_main_queue);
+     bm->process_main_queue = NULL;
+    }
+  if (bm->process_rsclient_queue)
+    {
+      work_queue_free (bm->process_rsclient_queue);
+      bm->process_rsclient_queue = NULL;
+    }
+  
   /* reverse bgp_master_init */
   for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
     {
@@ -302,8 +322,8 @@
     stream_free (bgp_nexthop_buf);
 
   /* reverse bgp_master_init */
-  if (master)
-    thread_master_free (master);
+  if (bm->master)
+    thread_master_free (bm->master);
 
   if (zlog_default)
     closezlog (zlog_default);
@@ -416,15 +436,12 @@
 	}
     }
 
-  /* Make thread master. */
-  master = bm->master;
-
   /* Initializations. */
   srandom (time (NULL));
-  signal_init (master, array_size(bgp_signals), bgp_signals);
+  signal_init (bm->master, array_size(bgp_signals), bgp_signals);
   zprivs_init (&bgpd_privs);
   cmd_init (1);
-  vty_init (master);
+  vty_init (bm->master);
   memory_init ();
   vrf_init ();
 
@@ -453,13 +470,14 @@
   vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
 
   /* Print banner. */
-  zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d", QUAGGA_VERSION,
+  zlog_notice ("BGPd %s starting: vty@%d, bgp@%s:%d pid %d", QUAGGA_VERSION,
 	       vty_port, 
 	       (bm->address ? bm->address : "<all>"),
-	       bm->port);
+	       bm->port,
+	       getpid ());
 
   /* Start finite state machine, here we go! */
-  while (thread_fetch (master, &thread))
+  while (thread_fetch (bm->master, &thread))
     thread_call (&thread);
 
   /* Not reached. */
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 8a1ed70..a72d5ed 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -170,11 +170,12 @@
 int
 str2prefix_rd (const char *str, struct prefix_rd *prd)
 {
-  int ret;
+  int ret; /* ret of called functions */
+  int lret; /* local ret, of this func */
   char *p;
   char *p2;
-  struct stream *s;
-  char *half;
+  struct stream *s = NULL;
+  char *half = NULL;
   struct in_addr addr;
 
   s = stream_new (8);
@@ -182,12 +183,13 @@
   prd->family = AF_UNSPEC;
   prd->prefixlen = 64;
 
+  lret = 0;
   p = strchr (str, ':');
   if (! p)
-    return 0;
+    goto out;
 
   if (! all_digit (p + 1))
-    return 0;
+    goto out;
 
   half = XMALLOC (MTYPE_TMP, (p - str) + 1);
   memcpy (half, str, (p - str));
@@ -198,10 +200,8 @@
   if (! p2)
     {
       if (! all_digit (half))
-	{
-	  XFREE (MTYPE_TMP, half);
-	  return 0;
-	}
+        goto out;
+      
       stream_putw (s, RD_TYPE_AS);
       stream_putw (s, atoi (half));
       stream_putl (s, atol (p + 1));
@@ -210,18 +210,21 @@
     {
       ret = inet_aton (half, &addr);
       if (! ret)
-	{
-	  XFREE (MTYPE_TMP, half);
-	  return 0;
-	}
+        goto out;
+      
       stream_putw (s, RD_TYPE_IP);
       stream_put_in_addr (s, &addr);
       stream_putw (s, atol (p + 1));
     }
   memcpy (prd->val, s->data, 8);
+  lret = 1;
 
-  XFREE(MTYPE_TMP, half);
-  return 1;
+out:
+  if (s)
+    stream_free (s);
+  if (half)
+    XFREE(MTYPE_TMP, half);
+  return lret;
 }
 
 int
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 7059e8a..3c5e6c5 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -207,7 +207,7 @@
       zlog_err ("accept_sock is nevative value %d", accept_sock);
       return -1;
     }
-  listener->thread = thread_add_read (master, bgp_accept, listener, accept_sock);
+  listener->thread = thread_add_read (bm->master, bgp_accept, listener, accept_sock);
 
   /* Accept client connection. */
   bgp_sock = sockunion_accept (accept_sock, &su);
@@ -276,6 +276,7 @@
 #ifdef SO_BINDTODEVICE
   int ret;
   struct ifreq ifreq;
+  int myerrno;
 
   if (! peer->ifname)
     return 0;
@@ -287,13 +288,15 @@
   
   ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, 
 		    &ifreq, sizeof (ifreq));
-
+  myerrno = errno;
+  
   if (bgpd_privs.change (ZPRIVS_LOWER) )
     zlog_err ("bgp_bind: could not lower privs");
 
   if (ret < 0)
     {
-      zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname);
+      zlog (peer->log, LOG_INFO, "bind to interface %s failed, errno=%d",
+            peer->ifname, myerrno);
       return ret;
     }
 #endif /* SO_BINDTODEVICE */
@@ -480,7 +483,7 @@
   listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener));
   listener->fd = sock;
   memcpy(&listener->su, sa, salen);
-  listener->thread = thread_add_read (master, bgp_accept, listener, sock);
+  listener->thread = thread_add_read (bm->master, bgp_accept, listener, sock);
   listnode_add (bm->listen_sockets, listener);
 
   return 0;
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 20302e3..145a1d8 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -529,7 +529,7 @@
 bgp_scan_timer (struct thread *t)
 {
   bgp_scan_thread =
-    thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
+    thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
 
   if (BGP_DEBUG (events, EVENTS))
     zlog_debug ("Performing BGP general scanning");
@@ -648,9 +648,9 @@
 
   addr = ifc->address;
 
+  p = *(CONNECTED_PREFIX(ifc));
   if (addr->family == AF_INET)
     {
-      PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
 
       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
@@ -674,7 +674,6 @@
 #ifdef HAVE_IPV6
   else if (addr->family == AF_INET6)
     {
-      PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
 
       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
@@ -715,9 +714,9 @@
 
   addr = ifc->address;
 
+  p = *(CONNECTED_PREFIX(ifc));
   if (addr->family == AF_INET)
     {
-      PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
 
       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
@@ -742,7 +741,6 @@
 #ifdef HAVE_IPV6
   else if (addr->family == AF_INET6)
     {
-      PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
 
       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
@@ -1105,7 +1103,7 @@
   safi_t safi;
 
   bgp_import_thread = 
-    thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
+    thread_add_timer (bm->master, bgp_import, NULL, bgp_import_interval);
 
   if (BGP_DEBUG (events, EVENTS))
     zlog_debug ("Import timer expired.");
@@ -1232,7 +1230,7 @@
     {
       thread_cancel (bgp_scan_thread);
       bgp_scan_thread = 
-	thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
+	thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
     }
 
   return CMD_SUCCESS;
@@ -1251,7 +1249,7 @@
     {
       thread_cancel (bgp_scan_thread);
       bgp_scan_thread = 
-	thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
+	thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
     }
 
   return CMD_SUCCESS;
@@ -1402,9 +1400,9 @@
 void
 bgp_scan_init (void)
 {
-  zlookup = zclient_new ();
+  zlookup = zclient_new (bm->master);
   zlookup->sock = -1;
-  zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
+  zlookup->t_connect = thread_add_event (bm->master, zlookup_connect, zlookup, 0);
 
   bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
   bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
@@ -1423,10 +1421,10 @@
 #endif /* HAVE_IPV6 */
 
   /* Make BGP scan thread. */
-  bgp_scan_thread = thread_add_timer (master, bgp_scan_timer, 
+  bgp_scan_thread = thread_add_timer (bm->master, bgp_scan_timer, 
                                       NULL, bgp_scan_interval);
   /* Make BGP import there. */
-  bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0);
+  bgp_import_thread = thread_add_timer (bm->master, bgp_import, NULL, 0);
 
   install_element (BGP_NODE, &bgp_scan_time_cmd);
   install_element (BGP_NODE, &no_bgp_scan_time_cmd);
@@ -1441,29 +1439,29 @@
 void
 bgp_scan_finish (void)
 {
-  /* Only the current one needs to be reset. */
-  bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
-
-  bgp_table_unlock (cache1_table[AFI_IP]);
+  if (cache1_table[AFI_IP])
+    bgp_table_unlock (cache1_table[AFI_IP]);
   cache1_table[AFI_IP] = NULL;
 
-  bgp_table_unlock (cache2_table[AFI_IP]);
+  if (cache2_table[AFI_IP])
+    bgp_table_unlock (cache2_table[AFI_IP]);
   cache2_table[AFI_IP] = NULL;
-
-  bgp_table_unlock (bgp_connected_table[AFI_IP]);
+  
+  if (bgp_connected_table[AFI_IP])
+    bgp_table_unlock (bgp_connected_table[AFI_IP]);
   bgp_connected_table[AFI_IP] = NULL;
 
 #ifdef HAVE_IPV6
-  /* Only the current one needs to be reset. */
-  bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
-
-  bgp_table_unlock (cache1_table[AFI_IP6]);
+  if (cache1_table[AFI_IP6])
+    bgp_table_unlock (cache1_table[AFI_IP6]);
   cache1_table[AFI_IP6] = NULL;
 
-  bgp_table_unlock (cache2_table[AFI_IP6]);
+  if (cache2_table[AFI_IP6])
+    bgp_table_unlock (cache2_table[AFI_IP6]);
   cache2_table[AFI_IP6] = NULL;
 
-  bgp_table_unlock (bgp_connected_table[AFI_IP6]);
+  if (bgp_connected_table[AFI_IP6])
+    bgp_table_unlock (bgp_connected_table[AFI_IP6]);
   bgp_connected_table[AFI_IP6] = NULL;
 #endif /* HAVE_IPV6 */
 }
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 2616351..e534bee 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1094,10 +1094,10 @@
 }
 
 void
-bgp_zebra_init (void)
+bgp_zebra_init (struct thread_master *master)
 {
   /* Set default values. */
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   zclient_init (zclient, ZEBRA_ROUTE_BGP);
   zclient->zebra_connected = bgp_zebra_connected;
   zclient->router_id_update = bgp_router_id_update;
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 8099193..50f727d 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -25,7 +25,7 @@
 
 extern struct stream *bgp_nexthop_buf;
 
-extern void bgp_zebra_init (void);
+extern void bgp_zebra_init (struct thread_master *master);
 extern int bgp_if_update_all (void);
 extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
 				      safi_t, int *);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 0068037..90e77f2 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -737,6 +737,9 @@
   if (peer->clear_node_queue)
     work_queue_free (peer->clear_node_queue);
   
+  if (peer->notify.data)
+    XFREE(MTYPE_TMP, peer->notify.data);
+  
   bgp_sync_delete (peer);
   memset (peer, 0, sizeof (struct peer));
   
@@ -1978,7 +1981,7 @@
   if (name)
     bgp->name = strdup (name);
 
-  THREAD_TIMER_ON (master, bgp->t_startup, bgp_startup_timer_expire,
+  THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
                    bgp, bgp->restart_time);
 
   return bgp;
@@ -1988,7 +1991,7 @@
 struct bgp *
 bgp_get_default (void)
 {
-  if (bm->bgp->head)
+  if (bm && bm->bgp && bm->bgp->head)
     return (listgetdata (listhead (bm->bgp)));
   return NULL;
 }
@@ -5421,7 +5424,7 @@
   bgp_vty_init ();
 
   /* Init zebra. */
-  bgp_zebra_init ();
+  bgp_zebra_init (bm->master);
 
   /* BGP inits. */
   bgp_attr_init ();
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 7ae0acb..95c16de 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -834,8 +834,6 @@
 
 extern struct bgp_master *bm;
 
-extern struct thread_master *master;
-
 /* Prototypes. */
 extern void bgp_terminate (void);
 extern void bgp_reset (void);
diff --git a/doc/ospfd.texi b/doc/ospfd.texi
index 856a2ba..7ddc9db 100644
--- a/doc/ospfd.texi
+++ b/doc/ospfd.texi
@@ -216,6 +216,7 @@
 @deffnx {OSPF Command} {network @var{a.b.c.d/m} area @var{<0-4294967295>}} {}
 @deffnx {OSPF Command} {no network @var{a.b.c.d/m} area @var{a.b.c.d}} {}
 @deffnx {OSPF Command} {no network @var{a.b.c.d/m} area @var{<0-4294967295>}} {}
+@anchor{OSPF network command}
 This command specifies the OSPF enabled interface(s).  If the interface has
 an address from range 192.168.1.0/24 then the command below enables ospf
 on this interface so router can provide network information to the other
@@ -239,6 +240,10 @@
 then we test whether the prefix in the network command contains
 the destination prefix.  Otherwise, we test whether the network command prefix
 contains the local address prefix of the interface. 
+
+In some cases it may be more convenient to enable OSPF on a per
+interface/subnet basis (@pxref{OSPF ip ospf area command}).
+
 @end deffn
 
 @node OSPF area
@@ -406,6 +411,19 @@
 @node OSPF interface
 @section OSPF interface
 
+@deffn {Interface Command} {ip ospf area @var{AREA} [@var{ADDR}]} {} 
+@deffnx {Interface Command} {no ip ospf area [@var{ADDR}]} {}
+@anchor{OSPF ip ospf area command}
+
+Enable OSPF on the interface, optionally restricted to just the IP address
+given by @var{ADDR}, putting it in the @var{AREA} area. Per interface area
+settings take precedence to network commands (@pxref{OSPF network command}).
+
+If you have a lot of interfaces, and/or a lot of subnets, then enabling OSPF
+via this command may result in a slight performance improvement.
+
+@end deffn
+
 @deffn {Interface Command} {ip ospf authentication-key @var{AUTH_KEY}} {}
 @deffnx {Interface Command} {no ip ospf authentication-key} {}
 Set OSPF authentication key to a simple password.  After setting @var{AUTH_KEY},
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 0b1dac1..0470c5b 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -1789,7 +1789,18 @@
         }
       else
         {
-          lsp_regenerate (area, lvl);
+          /*
+           * lsps are not regenerated if lsp_regenerate function is called
+           * directly. However if the lsp_regenerate call is queued for
+           * later execution it works.
+           */
+          area->lsp_regenerate_pending[lvl - 1] = 1;
+          if (lvl == IS_LEVEL_1)
+            THREAD_TIMER_ON (master, area->t_lsp_refresh[lvl - 1],
+                             lsp_l1_refresh, area, 0);
+          else if (lvl == IS_LEVEL_2)
+            THREAD_TIMER_ON (master, area->t_lsp_refresh[lvl - 1],
+                             lsp_l2_refresh, area, 0);
         }
     }
 
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index e1af71f..fba7b10 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -339,7 +339,7 @@
   /* create the global 'isis' instance */
   isis_new (1);
 
-  isis_zebra_init ();
+  isis_zebra_init (master);
 
   /* parse config file */
   /* this is needed three times! because we have interfaces before the areas */
diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c
index d202264..a9ecd40 100644
--- a/isisd/isis_pfpacket.c
+++ b/isisd/isis_pfpacket.c
@@ -230,12 +230,24 @@
 			LLC_LEN, MSG_PEEK,
 			(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
 
-  if (bytesread < 0)
+  if ((bytesread < 0) || (s_addr.sll_ifindex != (int)circuit->interface->ifindex))
     {
-      zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, "
-                 "recvfrom(): %s",
-                 circuit->interface->name, circuit->fd, bytesread,
-                 safe_strerror (errno));
+      if (bytesread < 0)
+        {
+          zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, "
+                     "bytesread %d, recvfrom(): %s",
+                     circuit->interface->name, circuit->fd, bytesread,
+                     safe_strerror (errno));
+        }
+      if (s_addr.sll_ifindex != (int)circuit->interface->ifindex)
+        {
+          zlog_warn("packet is received on multiple interfaces: "
+                    "socket interface %d, circuit interface %d, "
+                    "packet type %u",
+                    s_addr.sll_ifindex, circuit->interface->ifindex,
+                    s_addr.sll_pkttype);
+        }
+
       /* get rid of the packet */
       bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
                             MSG_DONTWAIT, (struct sockaddr *) &s_addr,
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 6d0c157..8a78417 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -602,9 +602,9 @@
 }
 
 void
-isis_zebra_init ()
+isis_zebra_init (struct thread_master *master)
 {
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   zclient_init (zclient, ZEBRA_ROUTE_ISIS);
   zclient->zebra_connected = isis_zebra_connected;
   zclient->router_id_update = isis_router_id_update_zebra;
diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h
index 889cd9b..0011478 100644
--- a/isisd/isis_zebra.h
+++ b/isisd/isis_zebra.h
@@ -24,7 +24,7 @@
 
 extern struct zclient *zclient;
 
-void isis_zebra_init (void);
+void isis_zebra_init (struct thread_master *);
 void isis_zebra_route_update (struct prefix *prefix,
 			      struct isis_route_info *route_info);
 int isis_distribute_list_update (int routetype);
diff --git a/lib/command.c b/lib/command.c
index 2084160..37767e9 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -2794,34 +2794,69 @@
   return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd);
 }
 
+/**
+ * Parse one line of config, walking up the parse tree attempting to find a match
+ *
+ * @param vty The vty context in which the command should be executed.
+ * @param cmd Pointer where the struct cmd_element* of the match command
+ *            will be stored, if any.  May be set to NULL if this info is
+ *            not needed.
+ * @param use_daemon Boolean to control whether or not we match on CMD_SUCCESS_DAEMON
+ *                   or not.
+ * @return The status of the command that has been executed or an error code
+ *         as to why no command could be executed.
+ */
+int
+command_config_read_one_line (struct vty *vty, struct cmd_element **cmd, int use_daemon)
+{
+  vector vline;
+  int saved_node;
+  int ret;
+
+  vline = cmd_make_strvec (vty->buf);
+
+  /* In case of comment line */
+  if (vline == NULL)
+    return CMD_SUCCESS;
+
+  /* Execute configuration command : this is strict match */
+  ret = cmd_execute_command_strict (vline, vty, cmd);
+
+  saved_node = vty->node;
+
+  while (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
+	 ret != CMD_SUCCESS && ret != CMD_WARNING &&
+	 ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE) {
+    vty->node = node_parent(vty->node);
+    ret = cmd_execute_command_strict (vline, vty, NULL);
+  }
+
+  // If climbing the tree did not work then ignore the command and
+  // stay at the same node
+  if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
+      ret != CMD_SUCCESS && ret != CMD_WARNING &&
+      ret != CMD_ERR_NOTHING_TODO)
+    {
+      vty->node = saved_node;
+    }
+
+  cmd_free_strvec (vline);
+
+  return ret;
+}
+
 /* Configration make from file. */
 int
 config_from_file (struct vty *vty, FILE *fp, unsigned int *line_num)
 {
   int ret;
   *line_num = 0;
-  vector vline;
 
   while (fgets (vty->buf, VTY_BUFSIZ, fp))
     {
       ++(*line_num);
-      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 */
-      while (ret != CMD_SUCCESS && ret != CMD_WARNING
-	     && ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE)
-	{
-	  vty->node = node_parent(vty->node);
-	  ret = cmd_execute_command_strict (vline, vty, NULL);
-	}
-
-      cmd_free_strvec (vline);
+      ret = command_config_read_one_line (vty, NULL, 0);
 
       if (ret != CMD_SUCCESS && ret != CMD_WARNING
 	  && ret != CMD_ERR_NOTHING_TODO)
diff --git a/lib/command.h b/lib/command.h
index bb0122f..6030069 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -527,6 +527,7 @@
 extern vector cmd_describe_command (vector, struct vty *, int *status);
 extern char **cmd_complete_command (vector, struct vty *, int *status);
 extern const char *cmd_prompt (enum node_type);
+extern int command_config_read_one_line (struct vty *vty, struct cmd_element **, int use_config_node);
 extern int config_from_file (struct vty *, FILE *, unsigned int *line_num);
 extern enum node_type node_parent (enum node_type);
 extern int cmd_execute_command (vector, struct vty *, struct cmd_element **, int);
diff --git a/lib/routemap.c b/lib/routemap.c
index 1e1510e..7302e23 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -897,6 +897,9 @@
   route_match_vec = NULL;
   vector_free (route_set_vec);
   route_set_vec = NULL;
+  /* cleanup route_map */                                                    
+  while (route_map_master.head)                                              
+    route_map_delete (route_map_master.head); 
 }
 
 /* VTY related functions. */
diff --git a/lib/smux.c b/lib/smux.c
index 70be492..03da99f 100644
--- a/lib/smux.c
+++ b/lib/smux.c
@@ -113,7 +113,7 @@
 };
 
 /* thread master */
-static struct thread_master *master;
+static struct thread_master *smux_master;
 
 static int
 oid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len)
@@ -1239,13 +1239,13 @@
   switch (event)
     {
     case SMUX_SCHEDULE:
-      smux_connect_thread = thread_add_event (master, smux_connect, NULL, 0);
+      smux_connect_thread = thread_add_event (smux_master, smux_connect, NULL, 0);
       break;
     case SMUX_CONNECT:
-      smux_connect_thread = thread_add_timer (master, smux_connect, NULL, 10);
+      smux_connect_thread = thread_add_timer (smux_master, smux_connect, NULL, 10);
       break;
     case SMUX_READ:
-      smux_read_thread = thread_add_read (master, smux_read, NULL, sock);
+      smux_read_thread = thread_add_read (smux_master, smux_read, NULL, sock);
       break;
     default:
       break;
@@ -1474,7 +1474,7 @@
 smux_init (struct thread_master *tm)
 {
   /* copy callers thread master */
-  master = tm;
+  smux_master = tm;
   
   /* Make MIB tree. */
   treelist = list_new();
diff --git a/lib/vty.c b/lib/vty.c
index 5c4a23b..8befcb0 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2573,7 +2573,7 @@
 }
 
 /* Master of the threads. */
-static struct thread_master *master;
+static struct thread_master *vty_master;
 
 static void
 vty_event (enum event event, int sock, struct vty *vty)
@@ -2583,23 +2583,23 @@
   switch (event)
     {
     case VTY_SERV:
-      vty_serv_thread = thread_add_read (master, vty_accept, vty, sock);
+      vty_serv_thread = thread_add_read (vty_master, vty_accept, vty, sock);
       vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
       break;
 #ifdef VTYSH
     case VTYSH_SERV:
-      vty_serv_thread = thread_add_read (master, vtysh_accept, vty, sock);
+      vty_serv_thread = thread_add_read (vty_master, vtysh_accept, vty, sock);
       vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
       break;
     case VTYSH_READ:
-      vty->t_read = thread_add_read (master, vtysh_read, vty, sock);
+      vty->t_read = thread_add_read (vty_master, vtysh_read, vty, sock);
       break;
     case VTYSH_WRITE:
-      vty->t_write = thread_add_write (master, vtysh_write, vty, sock);
+      vty->t_write = thread_add_write (vty_master, vtysh_write, vty, sock);
       break;
 #endif /* VTYSH */
     case VTY_READ:
-      vty->t_read = thread_add_read (master, vty_read, vty, sock);
+      vty->t_read = thread_add_read (vty_master, vty_read, vty, sock);
 
       /* Time out treatment. */
       if (vty->v_timeout)
@@ -2607,12 +2607,12 @@
 	  if (vty->t_timeout)
 	    thread_cancel (vty->t_timeout);
 	  vty->t_timeout = 
-	    thread_add_timer (master, vty_timeout, vty, vty->v_timeout);
+	    thread_add_timer (vty_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);
+	vty->t_write = thread_add_write (vty_master, vty_flush, vty, sock);
       break;
     case VTY_TIMEOUT_RESET:
       if (vty->t_timeout)
@@ -2623,7 +2623,7 @@
       if (vty->v_timeout)
 	{
 	  vty->t_timeout = 
-	    thread_add_timer (master, vty_timeout, vty, vty->v_timeout);
+	    thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout);
 	}
       break;
     }
@@ -3035,7 +3035,7 @@
 
   vtyvec = vector_init (VECTOR_MIN_SIZE);
 
-  master = master_thread;
+  vty_master = master_thread;
 
   atexit (vty_stdio_reset);
 
diff --git a/lib/zclient.c b/lib/zclient.c
index 0ce46fe..bfff9a3 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -39,8 +39,6 @@
 /* Prototype for event manager. */
 static void zclient_event (enum event, struct zclient *);
 
-extern struct thread_master *master;
-
 const char *zclient_serv_path = NULL;
 
 /* This file local debug flag. */
@@ -48,7 +46,7 @@
 
 /* Allocate zclient structure. */
 struct zclient *
-zclient_new ()
+zclient_new (struct thread_master *master)
 {
   struct zclient *zclient;
   zclient = XCALLOC (MTYPE_ZCLIENT, sizeof (struct zclient));
@@ -56,6 +54,7 @@
   zclient->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
   zclient->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
   zclient->wb = buffer_new(0);
+  zclient->master = master;
 
   return zclient;
 }
@@ -258,8 +257,8 @@
       return zclient_failed(zclient);
       break;
     case BUFFER_PENDING:
-      zclient->t_write = thread_add_write(master, zclient_flush_data,
-					  zclient, zclient->sock);
+      zclient->t_write = thread_add_write (zclient->master, zclient_flush_data,
+					   zclient, zclient->sock);
       break;
     case BUFFER_EMPTY:
       break;
@@ -284,8 +283,8 @@
       THREAD_OFF(zclient->t_write);
       break;
     case BUFFER_PENDING:
-      THREAD_WRITE_ON(master, zclient->t_write,
-		      zclient_flush_data, zclient, zclient->sock);
+      THREAD_WRITE_ON (zclient->master, zclient->t_write,
+		       zclient_flush_data, zclient, zclient->sock);
       break;
     }
   return 0;
@@ -1092,7 +1091,7 @@
     case ZCLIENT_SCHEDULE:
       if (! zclient->t_connect)
 	zclient->t_connect =
-	  thread_add_event (master, zclient_connect, zclient, 0);
+	  thread_add_event (zclient->master, zclient_connect, zclient, 0);
       break;
     case ZCLIENT_CONNECT:
       if (zclient->fail >= 10)
@@ -1102,12 +1101,12 @@
 		   zclient->fail < 3 ? 10 : 60);
       if (! zclient->t_connect)
 	zclient->t_connect = 
-	  thread_add_timer (master, zclient_connect, zclient,
+	  thread_add_timer (zclient->master, zclient_connect, zclient,
 			    zclient->fail < 3 ? 10 : 60);
       break;
     case ZCLIENT_READ:
       zclient->t_read = 
-	thread_add_read (master, zclient_read, zclient, zclient->sock);
+	thread_add_read (zclient->master, zclient_read, zclient, zclient->sock);
       break;
     }
 }
diff --git a/lib/zclient.h b/lib/zclient.h
index 3490b32..aa935c1 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -40,6 +40,9 @@
 /* Structure for the zebra client. */
 struct zclient
 {
+  /* The thread master we schedule ourselves on */
+  struct thread_master *master;
+
   /* Socket to zebra daemon. */
   int sock;
 
@@ -132,7 +135,7 @@
 };
 
 /* Prototypes of zebra client service functions. */
-extern struct zclient *zclient_new (void);
+extern struct zclient *zclient_new (struct thread_master *);
 extern void zclient_init (struct zclient *, int);
 extern int zclient_start (struct zclient *);
 extern void zclient_stop (struct zclient *);
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 951e11d..d37e508 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -578,10 +578,10 @@
 }
 
 void
-ospf6_zebra_init (void)
+ospf6_zebra_init (struct thread_master *master)
 {
   /* Allocate zebra structure. */
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   zclient_init (zclient, ZEBRA_ROUTE_OSPF6);
   zclient->zebra_connected = ospf6_zebra_connected;
   zclient->router_id_update = ospf6_router_id_update_zebra;
diff --git a/ospf6d/ospf6_zebra.h b/ospf6d/ospf6_zebra.h
index a219450..05694d3 100644
--- a/ospf6d/ospf6_zebra.h
+++ b/ospf6d/ospf6_zebra.h
@@ -44,7 +44,7 @@
 extern void ospf6_zebra_no_redistribute (int);
 #define ospf6_zebra_is_redistribute(type) \
     vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT)
-extern void ospf6_zebra_init (void);
+extern void ospf6_zebra_init(struct thread_master *);
 
 extern int config_write_ospf6_debug_zebra (struct vty *vty);
 extern void install_element_ospf6_debug_zebra (void);
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index 3cdd5c1..c2baa31 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -1764,7 +1764,7 @@
   ospf6_area_init ();
   ospf6_interface_init ();
   ospf6_neighbor_init ();
-  ospf6_zebra_init ();
+  ospf6_zebra_init (master);
 
   ospf6_lsa_init ();
   ospf6_spf_init ();
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index ed698c8..2ed426f 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -30,8 +30,17 @@
 #define IF_DEF_PARAMS(I) (IF_OSPF_IF_INFO (I)->def_params)
 #define IF_OIFS(I)  (IF_OSPF_IF_INFO (I)->oifs)
 #define IF_OIFS_PARAMS(I) (IF_OSPF_IF_INFO (I)->params)
-			    
+
+/* Despite the name, this macro probably is for specialist use only */
 #define OSPF_IF_PARAM_CONFIGURED(S, P) ((S) && (S)->P##__config)
+
+/* Test whether an OSPF interface parameter is set, generally, given some
+ * existing ospf interface
+ */
+#define OSPF_IF_PARAM_IS_SET(O,P) \
+      (OSPF_IF_PARAM_CONFIGURED ((O)->params, P) || \
+      OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp)->P))
+
 #define OSPF_IF_PARAM(O, P) \
         (OSPF_IF_PARAM_CONFIGURED ((O)->params, P)?\
                         (O)->params->P:IF_DEF_PARAMS((O)->ifp)->P)
@@ -47,6 +56,7 @@
   DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */
   DECLARE_IF_PARAM (u_char, passive_interface);      /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */
   DECLARE_IF_PARAM (u_char, priority);               /* OSPF Interface priority */
+  DECLARE_IF_PARAM (struct in_addr, if_area);        /* Enable OSPF on this interface with area if_area */
   DECLARE_IF_PARAM (u_char, type);                   /* type of interface */
 #define OSPF_IF_ACTIVE                  0
 #define OSPF_IF_PASSIVE		        1
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 826fc98..1e4184f 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -298,7 +298,7 @@
 
   /* OSPFd inits. */
   ospf_if_init ();
-  ospf_zebra_init ();
+  ospf_zebra_init (master);
 
   /* OSPF vty inits. */
   ospf_vty_init ();
@@ -312,15 +312,6 @@
   ospf_opaque_init ();
 #endif /* HAVE_OPAQUE_LSA */
   
-  /* Need to initialize the default ospf structure, so the interface mode
-     commands can be duly processed if they are received before 'router ospf',
-     when quagga(ospfd) is restarted */
-  if (!ospf_get())
-    {
-      zlog_err("OSPF instance init failed: %s", strerror(errno));
-      exit (1);
-    }
-
   /* Get configuration file. */
   vty_read_config (config_file, config_default);
 
diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c
index c3bdf99..23a6417 100644
--- a/ospfd/ospf_neighbor.c
+++ b/ospfd/ospf_neighbor.c
@@ -45,8 +45,8 @@
 
 /* Fill in the the 'key' as appropriate to retrieve the entry for nbr
  * from the ospf_interface's nbrs table. Indexed by interface address
- * for all cases except Virtual-link interfaces, where neighbours are
- * indexed by router-ID instead.
+ * for all cases except Virtual-link and PointToPoint interfaces, where
+ * neighbours are indexed by router-ID instead.
  */
 static void
 ospf_nbr_key (struct ospf_interface *oi, struct ospf_neighbor *nbr,
@@ -56,7 +56,8 @@
   key->prefixlen = IPV4_MAX_BITLEN;
 
   /* vlinks are indexed by router-id */
-  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK ||
+      oi->type == OSPF_IFTYPE_POINTOPOINT)
     key->u.prefix4 = nbr->router_id;
   else
     key->u.prefix4 = nbr->src;
@@ -291,8 +292,8 @@
 #endif /* HAVE_OPAQUE_LSA */
 
 /* lookup nbr by address - use this only if you know you must
- * otherwise use the ospf_nbr_lookup() wrapper, which deals 
- * with virtual link neighbours
+ * otherwise use the ospf_nbr_lookup() wrapper, which deals
+ * with virtual link and PointToPoint neighbours
  */
 struct ospf_neighbor *
 ospf_nbr_lookup_by_addr (struct route_table *nbrs,
@@ -384,7 +385,8 @@
 ospf_nbr_lookup (struct ospf_interface *oi, struct ip *iph,
                  struct ospf_header *ospfh)
 {
-  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK ||
+      oi->type == OSPF_IFTYPE_POINTOPOINT)
     return (ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id));
   else
     return (ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src));
@@ -444,8 +446,9 @@
   key.family = AF_INET;
   key.prefixlen = IPV4_MAX_BITLEN;
 
-  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
-    key.u.prefix4 = ospfh->router_id;   /* index vlink nbrs by router-id */
+  if (oi->type == OSPF_IFTYPE_VIRTUALLINK ||
+      oi->type == OSPF_IFTYPE_POINTOPOINT)
+    key.u.prefix4 = ospfh->router_id;/* index vlink and ptp nbrs by router-id */
   else
     key.u.prefix4 = iph->ip_src;
 
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index c6f3b40..45a19c0 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -292,6 +292,41 @@
     }
 }
 
+/* get the appropriate ospf parameters structure, checking if
+ * there's a valid interface address at the argi'th argv index
+ */
+enum {
+  VTY_SET = 0,
+  VTY_UNSET,
+};
+#define OSPF_VTY_GET_IF_PARAMS(ifp,params,argi,addr,set) \
+  (params) = IF_DEF_PARAMS ((ifp));           \
+                                              \
+  if (argc == (argi) + 1)                     \
+    {                                         \
+      int ret = inet_aton(argv[(argi)], &(addr)); \
+      if (!ret)                               \
+	{                                     \
+	  vty_out (vty, "Please specify interface address by A.B.C.D%s", \
+		   VTY_NEWLINE);              \
+	  return CMD_WARNING;                 \
+	}                                     \
+      (params) = ospf_get_if_params ((ifp), (addr)); \
+                                              \
+      if (set)                                \
+        ospf_if_update_params ((ifp), (addr));  \
+      else if ((params) == NULL)              \
+        return CMD_SUCCESS;                   \
+    }
+
+#define OSPF_VTY_PARAM_UNSET(params,var,ifp,addr) \
+  UNSET_IF_PARAM ((params), var);               \
+    if ((params) != IF_DEF_PARAMS ((ifp)))        \
+    {                                             \
+      ospf_free_if_params ((ifp), (addr));        \
+      ospf_if_update_params ((ifp), (addr));      \
+    }
+
 DEFUN (ospf_passive_interface,
        ospf_passive_interface_addr_cmd,
        "passive-interface IFNAME A.B.C.D",
@@ -453,7 +488,7 @@
        "OSPF area ID in IP address format\n"
        "OSPF area ID as a decimal value\n")
 {
-  struct ospf *ospf= vty->index;
+  struct ospf *ospf = vty->index;
   struct prefix_ipv4 p;
   struct in_addr area_id;
   int ret, format;
@@ -5883,6 +5918,70 @@
        "OSPF interface commands\n"
        "Link state transmit delay\n")
 
+DEFUN (ip_ospf_area,
+       ip_ospf_area_cmd,
+       "ip ospf area (A.B.C.D|<0-4294967295>) [A.B.C.D]",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enable OSPF on this interface\n"
+       "OSPF area ID in IP address format\n"
+       "OSPF area ID as a decimal value\n"
+       "Address of interface\n")
+{
+  struct interface *ifp = vty->index;
+  struct in_addr area_id;
+  struct in_addr addr;
+  int format;
+  struct ospf_if_params *params;
+
+  VTY_GET_OSPF_AREA_ID (area_id, format, argv[0]);
+
+  OSPF_VTY_GET_IF_PARAMS(ifp, params, 1, addr, VTY_SET);
+  
+  if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
+    {
+      vty_out (vty, "There is already an interface area statement.%s",
+              VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  if (memcmp (ifp->name, "VLINK", 5) == 0)
+    {
+      vty_out (vty, "Cannot enable OSPF on a virtual link.%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  SET_IF_PARAM (params, if_area);
+  params->if_area = area_id;
+  ospf_interface_area_set (ifp);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_ospf_area,
+       no_ip_ospf_area_cmd,
+       "no ip ospf area [A.B.C.D]",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Disable OSPF on this interface\n"
+       "Address of interface\n")
+{
+  struct interface *ifp = vty->index;
+  struct ospf_if_params *params;
+  struct in_addr addr;
+
+  OSPF_VTY_GET_IF_PARAMS(ifp, params, 0, addr, VTY_UNSET);
+  
+  if (!OSPF_IF_PARAM_CONFIGURED(params, if_area))
+    return CMD_SUCCESS;
+  
+  OSPF_VTY_PARAM_UNSET(params, if_area, ifp, addr);
+  
+  ospf_interface_area_unset (ifp);
+
+  return CMD_SUCCESS;
+}
+
 DEFUN (ospf_redistribute_source,
        ospf_redistribute_source_cmd,
        "redistribute " QUAGGA_REDIST_STR_OSPFD
@@ -6947,6 +7046,15 @@
 	    vty_out (vty, "%s", VTY_NEWLINE);
 	  }
 
+	/* Area  print. */
+	if (OSPF_IF_PARAM_CONFIGURED (params, if_area))
+	  {
+	    vty_out (vty, " ip ospf area %s", inet_ntoa (params->if_area));
+	    if (params != IF_DEF_PARAMS (ifp))
+	      vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4));
+            vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+
     /* MTU ignore print. */
     if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) &&
        params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT)
@@ -7597,6 +7705,10 @@
   install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd);
   install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_cmd);
 
+  /* "ip ospf area" commands. */
+  install_element (INTERFACE_NODE, &ip_ospf_area_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd);
+
   /* These commands are compatibitliy for previous version. */
   install_element (INTERFACE_NODE, &ospf_authentication_key_cmd);
   install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 588f0fb..cf2ea81 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1304,10 +1304,10 @@
 }
 
 void
-ospf_zebra_init ()
+ospf_zebra_init (struct thread_master *master)
 {
   /* Allocate zebra structure. */
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   zclient_init (zclient, ZEBRA_ROUTE_OSPF);
   zclient->zebra_connected = ospf_zebra_connected;
   zclient->router_id_update = ospf_router_id_update_zebra;
diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h
index 148f652..32a0271 100644
--- a/ospfd/ospf_zebra.h
+++ b/ospfd/ospf_zebra.h
@@ -72,7 +72,7 @@
 			      const char *, const char *);
 extern int ospf_distance_unset (struct vty *, struct ospf *, const char *,
 				const char *, const char *);
-extern void ospf_zebra_init (void);
+extern void ospf_zebra_init (struct thread_master *);
 
 #endif /* _ZEBRA_OSPF_ZEBRA_H */
 
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 8c7d1c2..c317ed8 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -69,8 +69,10 @@
 static void ospf_network_free (struct ospf *, struct ospf_network *);
 static void ospf_area_free (struct ospf_area *);
 static void ospf_network_run (struct prefix *, struct ospf_area *);
-static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
-                                        struct interface *);
+static void ospf_network_run_interface (struct ospf *, struct interface *, 
+                                        struct prefix *, struct ospf_area *);
+static void ospf_network_run_subnet (struct ospf *, struct connected *, 
+                                     struct prefix *, struct ospf_area *);
 static int ospf_network_match_iface (const struct connected *,
 				     const struct prefix *);
 static void ospf_finish_final (struct ospf *);
@@ -256,6 +258,16 @@
   return listgetdata (listhead (om->ospf));
 }
 
+static int
+ospf_is_ready (struct ospf *ospf)
+{
+  /* OSPF must be on and Router-ID must be configured. */
+  if (!ospf || ospf->router_id.s_addr == 0)
+    return 0;
+  
+  return 1;
+}
+
 static void
 ospf_add (struct ospf *ospf)
 {
@@ -743,6 +755,70 @@
   return new;
 }
 
+static void 
+add_ospf_interface (struct connected *co, struct ospf_area *area)
+{
+  struct ospf_interface *oi;
+
+  oi = ospf_if_new (area->ospf, co->ifp, co->address);
+  oi->connected = co;
+
+  oi->area = area;
+
+  oi->params = ospf_lookup_if_params (co->ifp, oi->address->u.prefix4);
+  oi->output_cost = ospf_if_get_output_cost (oi);
+
+  /* Add pseudo neighbor. */
+  ospf_nbr_add_self (oi);
+
+  /* Relate ospf interface to ospf instance. */
+  oi->ospf = area->ospf;
+
+  /* update network type as interface flag */
+  /* If network type is specified previously,
+     skip network type setting. */
+  oi->type = IF_DEF_PARAMS (co->ifp)->type;
+
+  ospf_area_add_if (oi->area, oi);
+
+  /* if router_id is not configured, dont bring up
+   * interfaces.
+   * ospf_router_id_update() will call ospf_if_update
+   * whenever r-id is configured instead.
+   */
+  if ((area->ospf->router_id.s_addr != 0)
+      && if_is_operative (co->ifp)) 
+    ospf_if_up (oi);
+}
+
+static void
+update_redistributed (struct ospf *ospf, int add_to_ospf)
+{
+  struct route_node *rn;
+  struct external_info *ei;
+
+  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
+    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
+      for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
+	   rn; rn = route_next (rn))
+	if ((ei = rn->info) != NULL)
+	  {
+            if (add_to_ospf)
+              {
+                if (ospf_external_info_find_lsa (ospf, &ei->p))
+                  if (!ospf_distribute_check_connected (ospf, ei))
+                    ospf_external_lsa_flush (ospf, ei->type, &ei->p,
+                                              ei->ifindex /*, ei->nexthop */);
+              }
+            else
+              {
+                if (!ospf_external_info_find_lsa (ospf, &ei->p))
+                  if (ospf_distribute_check_connected (ospf, ei))
+                    ospf_external_lsa_originate (ospf, ei);
+              }
+          }
+}
+
 static void
 ospf_network_free (struct ospf *ospf, struct ospf_network *network)
 {
@@ -758,7 +834,6 @@
   struct ospf_network *network;
   struct ospf_area *area;
   struct route_node *rn;
-  struct external_info *ei;
   int ret = OSPF_AREA_ID_FORMAT_ADDRESS;
 
   rn = route_node_get (ospf->networks, (struct prefix *)p);
@@ -776,16 +851,8 @@
   ospf_network_run ((struct prefix *)p, area);
 
   /* Update connected redistribute. */
-  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
-    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
-      for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
-	   rn; rn = route_next (rn))
-	if ((ei = rn->info) != NULL)
-	  if (ospf_external_info_find_lsa (ospf, &ei->p))
-	    if (!ospf_distribute_check_connected (ospf, ei))
-	      ospf_external_lsa_flush (ospf, ei->type, &ei->p,
-				       ei->ifindex /*, ei->nexthop */);
-
+  update_redistributed(ospf, 1);
+  
   ospf_area_check_free (ospf, area_id);
 
   return 1;
@@ -797,7 +864,6 @@
 {
   struct route_node *rn;
   struct ospf_network *network;
-  struct external_info *ei;
   struct listnode *node, *nnode;
   struct ospf_interface *oi;
 
@@ -817,45 +883,66 @@
   /* Find interfaces that not configured already.  */
   for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
     {
-      int found = 0;
-      struct connected *co = oi->connected;
-      
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
         continue;
       
-      for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
-        {
-          if (rn->info == NULL)
-            continue;
-          
-          if (ospf_network_match_iface(co,&rn->p))
-            {
-              found = 1;
-              route_unlock_node (rn);
-              break;
-            }
-        }
-
-      if (found == 0)
-	{
-	  ospf_if_free (oi);
-	  ospf_area_check_free (ospf, area_id);
-	}
+      ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
     }
   
   /* Update connected redistribute. */
-  if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
-    if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT))
-      for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT));
-	   rn; rn = route_next (rn))
-	if ((ei = rn->info) != NULL)
-	  if (!ospf_external_info_find_lsa (ospf, &ei->p))
-	    if (ospf_distribute_check_connected (ospf, ei))
-	      ospf_external_lsa_originate (ospf, ei);
-
+  update_redistributed(ospf, 0);
+  
+  ospf_area_check_free (ospf, area_id);
+  
   return 1;
 }
 
+/* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means
+ * there might not be any 'router ospf' config.
+ *
+ * Otherwise, doesn't do anything different to ospf_if_update for now
+ */
+void
+ospf_interface_area_set (struct interface *ifp)
+{
+  struct ospf *ospf = ospf_get();
+  
+  ospf_if_update (ospf, ifp);
+  /* if_update does a update_redistributed */
+  
+  return;
+}
+
+void
+ospf_interface_area_unset (struct interface *ifp)
+{
+  struct route_node *rn_oi;
+  struct ospf *ospf;
+
+  if ((ospf = ospf_lookup ()) == NULL)
+    return; /* Ospf not ready yet */
+  
+  /* Find interfaces that may need to be removed. */
+  for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi))
+    {
+      struct ospf_interface *oi;
+
+      if ( (oi = rn_oi->info) == NULL)
+	continue;
+      
+      if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+	continue;
+      
+      ospf_network_run_subnet (ospf, oi->connected, NULL, NULL);
+    }
+
+  /* Update connected redistribute. */
+  update_redistributed (ospf, 0); /* interfaces possibly removed */
+  
+  return;
+}
+
+
 /* Check whether interface matches given network
  * returns: 1, true. 0, false
  */
@@ -867,8 +954,101 @@
 }
 
 static void
-ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
-                            struct interface *ifp)
+ospf_update_interface_area (struct connected *co, struct ospf_area *area)
+{
+  struct ospf_interface *oi = ospf_if_table_lookup (co->ifp, co->address);
+  
+  /* nothing to be done case */
+  if (oi && oi->area == area)
+    return;
+  
+  if (oi) 
+    ospf_if_free (oi);
+  
+  add_ospf_interface (co, area);
+}
+
+/* Run OSPF for the given subnet, taking into account the following
+ * possible sources of area configuration, in the given order of preference:
+ *
+ * - Whether there is interface+address specific area configuration
+ * - Whether there is a default area for the interface
+ * - Whether there is an area given as a parameter.
+ * - If no specific network prefix/area is supplied, whether there's
+ *   a matching network configured.
+ */
+static void
+ospf_network_run_subnet (struct ospf *ospf, struct connected *co,
+                         struct prefix *p, struct ospf_area *given_area)
+{
+  struct ospf_interface *oi;
+  struct ospf_if_params *params;
+  struct ospf_area *area = NULL;
+  struct route_node *rn;
+  int configed = 0;
+  
+  if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY))
+    return;
+  
+  if (co->address->family != AF_INET)
+    return;
+  
+  /* Try determine the appropriate area for this interface + address
+   * Start by checking interface config 
+   */   
+  if (!(params = ospf_lookup_if_params (co->ifp, co->address->u.prefix4)))
+    params = IF_DEF_PARAMS (co->ifp);
+  
+  if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
+    area = (ospf_area_get (ospf, params->if_area,
+                           OSPF_AREA_ID_FORMAT_ADDRESS));
+  
+  /* If we've found an interface and/or addr specific area, then we're
+   * done
+   */
+  if (area)
+    {
+      ospf_update_interface_area (co, area);
+      return;
+    }
+  
+  /* Otherwise, only remaining possibility is a matching network statement */
+  if (p)
+    {
+      assert (given_area != NULL);
+      
+      /* Which either was supplied as a parameter.. (e.g. cause a new
+       * network/area was just added)..
+       */
+      if (p->family == co->address->family 
+          && ospf_network_match_iface (co, p))
+        ospf_update_interface_area (co, given_area);
+      
+      return;
+    }
+  
+  /* Else we have to search the existing network/area config to see
+   * if any match..
+   */
+  for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
+    if (rn->info != NULL
+        && ospf_network_match_iface (co, &rn->p))
+      {
+        struct ospf_network *network = (struct ospf_network *) rn->info;
+        area = ospf_area_get (ospf, network->area_id, network->format);
+        ospf_update_interface_area (co, area);
+        configed = 1;
+      }
+  
+  /* If the subnet isn't in any area, deconfigure */
+  if (!configed && (oi = ospf_if_table_lookup (co->ifp, co->address)))
+    ospf_if_free (oi);
+}
+
+static void
+ospf_network_run_interface (struct ospf *ospf, struct interface *ifp,
+                            struct prefix *p,
+                            struct ospf_area *given_area)
 {
   struct listnode *cnode;
   struct connected *co;
@@ -876,51 +1056,14 @@
   if (memcmp (ifp->name, "VLINK", 5) == 0)
     return;
   
+  /* Network prefix without area is nonsensical */
+  if (p)
+    assert (given_area != NULL);
+  
   /* if interface prefix is match specified prefix,
      then create socket and join multicast group. */
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
-    {
-
-      if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
-        continue;
-
-      if (p->family == co->address->family 
-	  && ! ospf_if_table_lookup(ifp, co->address)
-          && ospf_network_match_iface(co,p))
-        {
-           struct ospf_interface *oi;
-            
-            oi = ospf_if_new (area->ospf, ifp, co->address);
-            oi->connected = co;
-            
-            oi->area = area;
-
-            oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
-            oi->output_cost = ospf_if_get_output_cost (oi);
-            
-            /* Add pseudo neighbor. */
-            ospf_nbr_add_self (oi);
-
-            /* Relate ospf interface to ospf instance. */
-            oi->ospf = area->ospf;
-
-            /* update network type as interface flag */
-            /* If network type is specified previously,
-               skip network type setting. */
-            oi->type = IF_DEF_PARAMS (ifp)->type;
-            
-            ospf_area_add_if (oi->area, oi);
-            
-            /* if router_id is not configured, dont bring up
-             * interfaces.
-             * ospf_router_id_update() will call ospf_if_update
-             * whenever r-id is configured instead.
-             */
-            if ((area->ospf->router_id.s_addr != 0)
-                && if_is_operative (ifp)) 
-              ospf_if_up (oi);
-          }
-    }
+    ospf_network_run_subnet (ospf, co, p, given_area);  
 }
 
 static void
@@ -935,7 +1078,7 @@
   
   /* Get target interface. */
   for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
-    ospf_network_run_interface (p, area, ifp);
+    ospf_network_run_interface (area->ospf, ifp, p, area);
 }
 
 void
@@ -968,25 +1111,17 @@
 void
 ospf_if_update (struct ospf *ospf, struct interface *ifp)
 {
-  struct route_node *rn;
-  struct ospf_network *network;
-  struct ospf_area *area;
-  
   if (!ospf)
     ospf = ospf_lookup ();
 
-  /* OSPF must be on and Router-ID must be configured. */
-  if (!ospf || ospf->router_id.s_addr == 0)
+  /* OSPF must be ready. */
+  if (!ospf_is_ready (ospf))
     return;
   
-  /* Run each netowrk for this interface. */
-  for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
-    if (rn->info != NULL)
-      {
-        network = (struct ospf_network *) rn->info;
-        area = ospf_area_get (ospf, network->area_id, network->format);
-        ospf_network_run_interface (&rn->p, area, ifp);
-      }
+  ospf_network_run_interface (ospf, ifp, NULL, NULL);
+  
+  /* Update connected redistribute. */
+  update_redistributed(ospf, 1);
 }
 
 void
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index c50e615..595c04f 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -563,6 +563,9 @@
 extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *);
 extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *);
 
+extern void ospf_interface_area_set (struct interface *);
+extern void ospf_interface_area_unset (struct interface *);
+
 extern void ospf_route_map_init (void);
 extern void ospf_snmp_init (void);
 
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 6f806a1..930dad0 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -249,35 +249,6 @@
   pim_hello_restart_now(ifp);         /* send hello and restart timer */
 }
 
-static void on_primary_address_change(struct interface *ifp,
-				      const char *caller,
-				      struct in_addr old_addr,
-				      struct in_addr new_addr)
-{
-  struct pim_interface *pim_ifp;
-
-  {
-    char old_str[100];
-    char new_str[100];
-    pim_inet4_dump("<old?>", old_addr, old_str, sizeof(old_str));
-    pim_inet4_dump("<new?>", new_addr, new_str, sizeof(new_str));
-    zlog_info("%s: %s: primary address changed from %s to %s on interface %s",
-	      __PRETTY_FUNCTION__, caller,
-	      old_str, new_str, ifp->name);
-  }
-
-  pim_ifp = ifp->info;
-  if (!pim_ifp) {
-    return;
-  }
-
-  if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
-    return;
-  }
-
-  pim_addr_change(ifp);
-}
-
 static int detect_primary_address_change(struct interface *ifp,
 					 int force_prim_as_any,
 					 const char *caller)
@@ -309,10 +280,13 @@
   }
 
   if (changed) {
-    struct in_addr old_addr = pim_ifp->primary_address;
     pim_ifp->primary_address = new_prim_addr;
 
-    on_primary_address_change(ifp, caller, old_addr, new_prim_addr);
+    if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
+      return changed;
+    }
+
+    pim_addr_change(ifp);
   }
 
   return changed;
@@ -329,14 +303,9 @@
     return;
 
   changed = 1; /* true */
-  zlog_debug("FIXME T31 C15 %s: on interface %s: acting on any addr change",
-	     __PRETTY_FUNCTION__, ifp->name);
-
-  if (PIM_DEBUG_ZEBRA) {
-    zlog_debug("%s: on interface %s: %s",
-	       __PRETTY_FUNCTION__, 
-	       ifp->name, changed ? "changed" : "unchanged");
-  }
+  if (PIM_DEBUG_ZEBRA)
+    zlog_debug("FIXME T31 C15 %s: on interface %s: acting on any addr change",
+	      __PRETTY_FUNCTION__, ifp->name);
 
   if (!changed) {
     return;
@@ -382,7 +351,7 @@
   if (!if_is_operative(ifp))
     return;
 
-  /* if (PIM_DEBUG_ZEBRA) */ {
+  if (PIM_DEBUG_ZEBRA) {
     char buf[BUFSIZ];
     prefix2str(ifc->address, buf, BUFSIZ);
     zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
@@ -501,7 +470,7 @@
   ifp = ifc->ifp;
   zassert(ifp);
 
-  /* if (PIM_DEBUG_ZEBRA) */ {
+  if (PIM_DEBUG_ZEBRA) {
     char buf[BUFSIZ];
     prefix2str(ifc->address, buf, BUFSIZ);
     zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
@@ -1055,14 +1024,14 @@
     return -4;
   }
 
-  {
+  if (PIM_DEBUG_IGMP_EVENTS) {
     char group_str[100];
     char source_str[100];
     pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
     pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
     zlog_debug("%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
-	       __PRETTY_FUNCTION__,
-	       source_str, group_str, ifp->name);
+	      __PRETTY_FUNCTION__,
+	      source_str, group_str, ifp->name);
   }
 
   return 0;
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index e253a0e..e801f4e 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -103,9 +103,11 @@
   enum pim_ifjoin_state old_state = ch->ifjoin_state;
 
   if (old_state == new_state) {
-    zlog_debug("%s calledby %s: non-transition on state %d (%s)",
-	       __PRETTY_FUNCTION__, caller, new_state,
-	       pim_ifchannel_ifjoin_name(new_state));
+    if (PIM_DEBUG_PIM_EVENTS) {
+      zlog_debug("%s calledby %s: non-transition on state %d (%s)",
+		 __PRETTY_FUNCTION__, caller, new_state,
+		 pim_ifchannel_ifjoin_name(new_state));
+    }
     return;
   }
 
@@ -286,7 +288,7 @@
   if (ch->local_ifmembership == membership)
     return;
 
-  /* if (PIM_DEBUG_PIM_EVENTS) */ {
+  if (PIM_DEBUG_PIM_EVENTS) {
     char src_str[100];
     char grp_str[100];
     pim_inet4_dump("<src?>", ch->source_addr, src_str, sizeof(src_str));
diff --git a/pimd/pim_igmp_join.c b/pimd/pim_igmp_join.c
index b48adb7..62e32c6 100644
--- a/pimd/pim_igmp_join.c
+++ b/pimd/pim_igmp_join.c
@@ -47,18 +47,20 @@
 			 struct in_addr source_addr)
 {
   struct group_source_req req;
-  struct sockaddr_in *group_sa = (struct sockaddr_in *) &req.gsr_group;
-  struct sockaddr_in *source_sa = (struct sockaddr_in *) &req.gsr_source;
+  struct sockaddr_in group;
+  struct sockaddr_in source;
 
-  memset(group_sa, 0, sizeof(*group_sa));
-  group_sa->sin_family = AF_INET;
-  group_sa->sin_addr = group_addr;
-  group_sa->sin_port = htons(0);
+  memset(&group, 0, sizeof(group));
+  group.sin_family = AF_INET;
+  group.sin_addr = group_addr;
+  group.sin_port = htons(0);
+  memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in));
 
-  memset(source_sa, 0, sizeof(*source_sa));
-  source_sa->sin_family = AF_INET;
-  source_sa->sin_addr = source_addr;
-  source_sa->sin_port = htons(0);
+  memset(&source, 0, sizeof(source));
+  source.sin_family = AF_INET;
+  source.sin_addr = source_addr;
+  source.sin_port = htons(0);
+  memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in));
 
   req.gsr_interface = ifindex;
 
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index 95c1816..5f4711e 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -205,7 +205,7 @@
   /*
    * Initialize zclient "update" and "lookup" sockets
    */
-  pim_zebra_init(zebra_sock_path);
+  pim_zebra_init (master, zebra_sock_path);
 
   zlog_notice("Loading configuration - begin");
 
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index 72a3538..8932dc3 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -125,7 +125,7 @@
   /* DR changed ? */
   if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
 
-    /* if (PIM_DEBUG_PIM_EVENTS) */ {
+    if (PIM_DEBUG_PIM_EVENTS) {
       char dr_old_str[100];
       char dr_new_str[100];
       pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str));
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index cd8a290..66fc59b 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -206,6 +206,20 @@
 	       pim_version, pim_type, pim_msg_len, checksum);
   }
 
+  if (pim_type == PIM_MSG_TYPE_REGISTER  ||
+      pim_type == PIM_MSG_TYPE_REG_STOP  ||
+      pim_type == PIM_MSG_TYPE_BOOTSTRAP ||
+      pim_type == PIM_MSG_TYPE_GRAFT     ||
+      pim_type == PIM_MSG_TYPE_GRAFT_ACK ||
+      pim_type == PIM_MSG_TYPE_CANDIDATE)
+    {
+      if (PIM_DEBUG_PIM_PACKETS) {
+	zlog_debug("Recv PIM packet type %d which is not currently understood",
+		   pim_type);
+      }
+      return -1;
+    }
+
   if (pim_type == PIM_MSG_TYPE_HELLO) {
     int result = pim_hello_recv(ifp,
                  ip_hdr->ip_src,
diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h
index 6be1a3e..4b378fb 100644
--- a/pimd/pim_pim.h
+++ b/pimd/pim_pim.h
@@ -41,8 +41,14 @@
 #define PIM_DEFAULT_T_PERIODIC                   (60)   /* RFC 4601: 4.11.  Timer Values */
 
 #define PIM_MSG_TYPE_HELLO      (0)
+#define PIM_MSG_TYPE_REGISTER   (1)
+#define PIM_MSG_TYPE_REG_STOP   (2)
 #define PIM_MSG_TYPE_JOIN_PRUNE (3)
+#define PIM_MSG_TYPE_BOOTSTRAP  (4)
 #define PIM_MSG_TYPE_ASSERT     (5)
+#define PIM_MSG_TYPE_GRAFT      (6)
+#define PIM_MSG_TYPE_GRAFT_ACK  (7)
+#define PIM_MSG_TYPE_CANDIDATE  (8)
 
 #define PIM_MSG_HDR_OFFSET_VERSION(pim_msg) (pim_msg)
 #define PIM_MSG_HDR_OFFSET_TYPE(pim_msg) (pim_msg)
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index dedc60a..38339da 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -61,7 +61,7 @@
   if (num_ifindex > 1) {
     char addr_str[100];
     pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-    zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
+    zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
 	      __FILE__, __PRETTY_FUNCTION__,
 	      num_ifindex, addr_str, first_ifindex);
     /* debug warning only, do not return */
@@ -136,22 +136,22 @@
   }
 
   rpf->rpf_addr = pim_rpf_find_rpf_addr(up);
-  if (PIM_INADDR_IS_ANY(rpf->rpf_addr)) {
+  if (PIM_INADDR_IS_ANY(rpf->rpf_addr) && PIM_DEBUG_PIM_EVENTS) {
     /* RPF'(S,G) not found */
     char src_str[100];
     char grp_str[100];
     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
-    zlog_warn("%s %s: RPF'(%s,%s) not found: won't send join upstream",
-              __FILE__, __PRETTY_FUNCTION__,
-              src_str, grp_str);
+    zlog_debug("%s %s: RPF'(%s,%s) not found: won't send join upstream",
+	       __FILE__, __PRETTY_FUNCTION__,
+	       src_str, grp_str);
     /* warning only */
   }
 
   /* detect change in pim_nexthop */
   if (nexthop_mismatch(&rpf->source_nexthop, &save_nexthop)) {
 
-    /* if (PIM_DEBUG_PIM_EVENTS) */ {
+    if (PIM_DEBUG_PIM_EVENTS) {
       char src_str[100];
       char grp_str[100];
       char nhaddr_str[100];
@@ -176,7 +176,7 @@
   /* detect change in RPF_interface(S) */
   if (save_nexthop.interface != rpf->source_nexthop.interface) {
 
-    /* if (PIM_DEBUG_PIM_EVENTS) */ {
+    if (PIM_DEBUG_PIM_EVENTS) {
       char src_str[100];
       char grp_str[100];
       pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
diff --git a/pimd/pim_signals.c b/pimd/pim_signals.c
index dcf4922..3549331 100644
--- a/pimd/pim_signals.c
+++ b/pimd/pim_signals.c
@@ -37,7 +37,7 @@
 
 static void pim_sighup()
 {
-  zlog_debug ("SIGHUP received, ignoring");
+  zlog_info ("SIGHUP received, ignoring");
 }
 
 static void pim_sigint()
@@ -56,7 +56,7 @@
 
 static void pim_sigusr1()
 {
-  zlog_debug ("SIGUSR1 received");
+  zlog_info ("SIGUSR1 received");
   zlog_rotate (NULL);
 }
 
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index 512c0e6..810dbe8 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -157,18 +157,24 @@
       }
 
       /* IF ip igmp query-interval */
-      vty_out(vty, " %s %d%s",
-	      PIM_CMD_IP_IGMP_QUERY_INTERVAL,
-	      pim_ifp->igmp_default_query_interval,
-	      VTY_NEWLINE);
-      ++writes;
+      if (pim_ifp->igmp_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL)
+	{
+	  vty_out(vty, " %s %d%s",
+		  PIM_CMD_IP_IGMP_QUERY_INTERVAL,
+		  pim_ifp->igmp_default_query_interval,
+		  VTY_NEWLINE);
+	  ++writes;
+	}
 
       /* IF ip igmp query-max-response-time */
-      vty_out(vty, " %s %d%s",
-	      PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC,
-	      pim_ifp->igmp_query_max_response_time_dsec,
-	      VTY_NEWLINE);
-      ++writes;
+      if (pim_ifp->igmp_query_max_response_time_dsec != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC)
+	{
+	  vty_out(vty, " %s %d%s",
+		  PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC,
+		  pim_ifp->igmp_query_max_response_time_dsec,
+		  VTY_NEWLINE);
+	  ++writes;
+	}
 
       /* IF ip igmp join */
       if (pim_ifp->igmp_join_list) {
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index dfc871b..3c739d2 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -150,8 +150,6 @@
   if (!ifp)
     return 0;
 
-  zlog_info("INTERFACE UP: %s ifindex=%d", ifp->name, ifp->ifindex);
-
   if (PIM_DEBUG_ZEBRA) {
     zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
 	       __PRETTY_FUNCTION__,
@@ -182,8 +180,6 @@
   if (!ifp)
     return 0;
 
-  zlog_info("INTERFACE DOWN: %s ifindex=%d", ifp->name, ifp->ifindex);
-
   if (PIM_DEBUG_ZEBRA) {
     zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
 	       __PRETTY_FUNCTION__,
@@ -242,8 +238,6 @@
   struct connected *c;
   struct prefix *p;
 
-  zassert(command == ZEBRA_INTERFACE_ADDRESS_ADD);
-
   /*
     zebra api notifies address adds/dels events by using the same call
     interface_add_read below, see comments in lib/zclient.c
@@ -278,17 +272,19 @@
 
     struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
     if (primary_addr.s_addr != p->u.prefix4.s_addr) {
-      /* but we had a primary address already */
+      if (PIM_DEBUG_ZEBRA) {
+	/* but we had a primary address already */
 
-      char buf[BUFSIZ];
-      char old[100];
+	char buf[BUFSIZ];
+	char old[100];
 
-      prefix2str(p, buf, BUFSIZ);
-      pim_inet4_dump("<old?>", primary_addr, old, sizeof(old));
+	prefix2str(p, buf, BUFSIZ);
+	pim_inet4_dump("<old?>", primary_addr, old, sizeof(old));
 
-      zlog_warn("%s: %s primary addr old=%s: forcing secondary flag on new=%s",
-		__PRETTY_FUNCTION__,
-		c->ifp->name, old, buf);
+	zlog_warn("%s: %s primary addr old=%s: forcing secondary flag on new=%s",
+		  __PRETTY_FUNCTION__,
+		  c->ifp->name, old, buf);
+      }
       SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
     }
   }
@@ -304,8 +300,6 @@
   struct connected *c;
   struct prefix *p;
 
-  zassert(command == ZEBRA_INTERFACE_ADDRESS_DELETE);
-
   /*
     zebra api notifies address adds/dels events by using the same call
     interface_add_read below, see comments in lib/zclient.c
@@ -655,7 +649,7 @@
   zclient_send_requests(zclient, VRF_DEFAULT);
 }
 
-void pim_zebra_init(char *zebra_sock_path)
+void pim_zebra_init (struct thread_master *master, char *zebra_sock_path)
 {
   int i;
 
@@ -669,7 +663,7 @@
 #endif
 
   /* Socket for receiving updates from Zebra daemon */
-  qpim_zclient_update = zclient_new();
+  qpim_zclient_update = zclient_new (master);
 
   qpim_zclient_update->zebra_connected          = pim_zebra_connected;
   qpim_zclient_update->router_id_update         = pim_router_id_update_zebra;
@@ -762,7 +756,7 @@
   if (num_ifindex > 1) {
     char addr_str[100];
     pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-    zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
+    zlog_info("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
 	       __FILE__, __PRETTY_FUNCTION__,
 	       num_ifindex, addr_str, first_ifindex);
     /* debug warning only, do not return */
diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h
index d624c86..af5baef 100644
--- a/pimd/pim_zebra.h
+++ b/pimd/pim_zebra.h
@@ -26,7 +26,7 @@
 #include "pim_igmp.h"
 #include "pim_ifchannel.h"
 
-void pim_zebra_init(char *zebra_sock_path);
+void pim_zebra_init (struct thread_master *master, char *zebra_sock_path);
 
 void pim_scan_oil(void);
 
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 67896d9..b5b219e 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -122,7 +122,7 @@
 {
   struct zclient *zlookup;
 
-  zlookup = zclient_new();
+  zlookup = zclient_new (master);
   if (!zlookup) {
     zlog_err("%s: zclient_new() failure",
 	     __PRETTY_FUNCTION__);
@@ -283,14 +283,14 @@
       nexthop_tab[num_ifindex].ifindex             = 0;
       nexthop_tab[num_ifindex].protocol_distance   = distance;
       nexthop_tab[num_ifindex].route_metric        = metric;
-      {
+      if (PIM_DEBUG_ZEBRA) {
 	char addr_str[100];
 	char nexthop_str[100];
 	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
 	pim_inet4_dump("<nexthop?>", nexthop_tab[num_ifindex].nexthop_addr, nexthop_str, sizeof(nexthop_str));
-	zlog_warn("%s %s: zebra returned recursive nexthop %s for address %s",
-		  __FILE__, __PRETTY_FUNCTION__,
-		  nexthop_str, addr_str);
+	zlog_debug("%s %s: zebra returned recursive nexthop %s for address %s",
+		   __FILE__, __PRETTY_FUNCTION__,
+		   nexthop_str, addr_str);
       }
       ++num_ifindex;
       break;
@@ -375,7 +375,7 @@
 
     num_ifindex = zclient_lookup_nexthop_once(qpim_zclient_lookup, nexthop_tab,
 					      PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr);
-    if (num_ifindex < 1) {
+    if ((num_ifindex < 1) && PIM_DEBUG_ZEBRA) {
       char addr_str[100];
       pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
       zlog_warn("%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s",
@@ -400,15 +400,15 @@
     if (first_ifindex > 0) {
       /* found: first ifindex is non-recursive nexthop */
 
-      if (lookup > 0) {
+      if ((lookup > 0) && PIM_DEBUG_ZEBRA) {
 	/* Report non-recursive success after first lookup */
 	char addr_str[100];
 	pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-	zlog_info("%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d",
-		  __FILE__, __PRETTY_FUNCTION__,
-		  lookup, max_lookup, first_ifindex, addr_str,
-		  nexthop_tab[0].protocol_distance,
-		  nexthop_tab[0].route_metric);
+	zlog_debug("%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d",
+		   __FILE__, __PRETTY_FUNCTION__,
+		   lookup, max_lookup, first_ifindex, addr_str,
+		   nexthop_tab[0].protocol_distance,
+		   nexthop_tab[0].route_metric);
 
 	/* use last address as nexthop address */
 	nexthop_tab[0].nexthop_addr = addr;
@@ -421,12 +421,12 @@
       return num_ifindex;
     }
 
-    {
+    if (PIM_DEBUG_ZEBRA) {
       char addr_str[100];
       char nexthop_str[100];
       pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
       pim_inet4_dump("<nexthop?>", nexthop_addr, nexthop_str, sizeof(nexthop_str));
-      zlog_warn("%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d",
+      zlog_debug("%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d",
 		__FILE__, __PRETTY_FUNCTION__,
 		lookup, max_lookup, nexthop_str, addr_str,
 		nexthop_tab[0].protocol_distance,
@@ -437,11 +437,13 @@
 
   } /* for (max_lookup) */
 
-  char addr_str[100];
-  pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-  zlog_warn("%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s",
-	    __FILE__, __PRETTY_FUNCTION__,
-	    lookup, max_lookup, addr_str);
+  if (PIM_DEBUG_ZEBRA) {
+    char addr_str[100];
+    pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+    zlog_warn("%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s",
+	      __FILE__, __PRETTY_FUNCTION__,
+	      lookup, max_lookup, addr_str);
+  }
 
   return -2;
 }
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index 95b1f6d..4ead9b0 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -286,7 +286,7 @@
   /* RIP related initialization. */
   rip_init ();
   rip_if_init ();
-  rip_zclient_init ();
+  rip_zclient_init (master);
   rip_peer_init ();
 
   /* Get configuration file. */
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index de98162..0b6c22a 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -710,10 +710,10 @@
 }
 
 void
-rip_zclient_init ()
+rip_zclient_init (struct thread_master *master)
 {
   /* Set default value to the zebra client structure. */
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   zclient_init (zclient, ZEBRA_ROUTE_RIP);
   zclient->zebra_connected = rip_zebra_connected;
   zclient->interface_add = rip_interface_add;
diff --git a/ripd/ripd.c b/ripd/ripd.c
index b42ca72..b708889 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -1168,7 +1168,8 @@
   struct prefix_ipv4 ifaddr;
   struct prefix_ipv4 ifaddrclass;
   int subnetted;
-      
+
+  memset(&ifaddr, 0, sizeof(ifaddr));
   /* We don't know yet. */
   subnetted = -1;
 
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 4f40e79..a768ccc 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -389,7 +389,7 @@
 extern void rip_route_map_init (void);
 extern void rip_route_map_reset (void);
 extern void rip_snmp_init (void);
-extern void rip_zclient_init (void);
+extern void rip_zclient_init (struct thread_master *);
 extern void rip_zclient_start (void);
 extern void rip_zclient_reset (void);
 extern void rip_offset_init (void);
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index d8f2241..1c184e2 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -281,7 +281,7 @@
 
   /* RIPngd inits. */
   ripng_init ();
-  zebra_init ();
+  zebra_init (master);
   ripng_peer_init ();
 
   /* Get configuration file. */
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index 58f8860..13b1853 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -541,10 +541,10 @@
 
 /* Initialize zebra structure and it's commands. */
 void
-zebra_init ()
+zebra_init (struct thread_master *master)
 {
   /* Allocate zebra structure. */
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   zclient_init (zclient, ZEBRA_ROUTE_RIPNG);
 
   zclient->zebra_connected = ripng_zebra_connected;
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 28ca41b..6cbbd84 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -358,7 +358,7 @@
 extern void ripng_route_map_reset (void);
 extern void ripng_terminate (void);
  /* zclient_init() is done by ripng_zebra.c:zebra_init() */
-extern void zebra_init (void);
+extern void zebra_init (struct thread_master *);
 extern void ripng_zclient_start (void);
 extern void ripng_zclient_reset (void);
 extern void ripng_offset_init (void);
diff --git a/tests/bgp_mpath_test.c b/tests/bgp_mpath_test.c
index 3594753..ed54d9c 100644
--- a/tests/bgp_mpath_test.c
+++ b/tests/bgp_mpath_test.c
@@ -376,7 +376,7 @@
 global_test_init (void)
 {
   master = thread_master_create ();
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   bgp_master_init ();
   bgp_option_set (BGP_OPT_NO_LISTEN);
   
diff --git a/tests/test-stream.c b/tests/test-stream.c
index 5997b47..7ef6374 100644
--- a/tests/test-stream.c
+++ b/tests/test-stream.c
@@ -24,7 +24,7 @@
 #include <stream.h>
 #include <thread.h>
 
-static long int ham = 0xdeadbeefdeadbeef;
+static unsigned long long ham = 0xdeadbeefdeadbeef;
 struct thread_master *master;
 
 static void
@@ -32,7 +32,7 @@
 {
   size_t getp = stream_get_getp (s);
   
-  printf ("endp: %ld, readable: %ld, writeable: %ld\n",
+  printf ("endp: %zu, readable: %zu, writeable: %zu\n",
           stream_get_endp (s),
           STREAM_READABLE (s),
           STREAM_WRITEABLE (s));
@@ -70,7 +70,7 @@
   printf ("c: 0x%hhx\n", stream_getc (s));
   printf ("w: 0x%hx\n", stream_getw (s));
   printf ("l: 0x%x\n", stream_getl (s));
-  printf ("q: 0x%lx\n", stream_getq (s));
+  printf ("q: 0x%" PRIu64 "\n", stream_getq (s));
   
   return 0;
 }
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 91791e2..b55c671 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -251,14 +251,6 @@
     }
 }
 
-static void
-vtysh_exit_ripd_only (void)
-{
-  if (ripd_client)
-    vtysh_client_execute (ripd_client, "exit", stdout);
-}
-
-
 void
 vtysh_pager_init (void)
 {
@@ -457,53 +449,11 @@
 vtysh_config_from_file (struct vty *vty, FILE *fp)
 {
   int ret;
-  vector vline;
   struct cmd_element *cmd;
 
   while (fgets (vty->buf, VTY_BUFSIZ, fp))
     {
-      if (vty->buf[0] == '!' || vty->buf[1] == '#')
-	continue;
-
-      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, &cmd);
-
-      /* Try again with setting node to CONFIG_NODE. */
-      if (ret != CMD_SUCCESS 
-	  && ret != CMD_SUCCESS_DAEMON
-	  && ret != CMD_WARNING)
-	{
-	  if (vty->node == KEYCHAIN_KEY_NODE)
-	    {
-	      vty->node = KEYCHAIN_NODE;
-	      vtysh_exit_ripd_only ();
-	      ret = cmd_execute_command_strict (vline, vty, &cmd);
-
-	      if (ret != CMD_SUCCESS 
-		  && ret != CMD_SUCCESS_DAEMON 
-		  && ret != CMD_WARNING)
-		{
-		  vtysh_exit_ripd_only ();
-		  vty->node = CONFIG_NODE;
-		  ret = cmd_execute_command_strict (vline, vty, &cmd);
-		}
-	    }
-	  else
-	    {
-	      vtysh_execute ("end");
-	      vtysh_execute ("configure terminal");
-	      vty->node = CONFIG_NODE;
-	      ret = cmd_execute_command_strict (vline, vty, &cmd);
-	    }
-	}	  
-
-      cmd_free_strvec (vline);
+      ret = command_config_read_one_line (vty, &cmd, 1);
 
       switch (ret)
 	{
@@ -1808,6 +1758,34 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (vtysh_write_terminal_daemon,
+       vtysh_write_terminal_daemon_cmd,
+       "write terminal (zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|babeld)",
+       "Write running configuration to memory, network, or terminal\n"
+       "Write to terminal\n"
+       "For the zebra daemon\n"
+       "For the rip daemon\n"
+       "For the ripng daemon\n"
+       "For the ospf daemon\n"
+       "For the ospfv6 daemon\n"
+       "For the bgp daemon\n"
+       "For the isis daemon\n"
+       "For the babel daemon\n")
+{
+  unsigned int i;
+  int ret = CMD_SUCCESS;
+
+  for (i = 0; i < array_size(vtysh_client); i++)
+    {
+      if (strcmp(vtysh_client[i].name, argv[0]) == 0)
+	break;
+    }
+
+  ret = vtysh_client_execute(&vtysh_client[i], "show running-config\n", stdout);
+
+  return ret;
+}
+
 DEFUN (vtysh_integrated_config,
        vtysh_integrated_config_cmd,
        "service integrated-vtysh-config",
@@ -1926,6 +1904,20 @@
        SHOW_STR
        "Current operating configuration\n")
 
+ALIAS (vtysh_write_terminal_daemon,
+       vtysh_show_running_config_daemon_cmd,
+       "show running-config (zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|babeld)",
+       SHOW_STR
+       "Current operating configuration\n"
+       "For the zebra daemon\n"
+       "For the rip daemon\n"
+       "For the ripng daemon\n"
+       "For the ospf daemon\n"
+       "For the ospfv6 daemon\n"
+       "For the bgp daemon\n"
+       "For the isis daemon\n"
+       "For the babel daemon\n")
+
 DEFUN (vtysh_terminal_length,
        vtysh_terminal_length_cmd,
        "terminal length <0-512>",
@@ -2447,12 +2439,14 @@
   install_element (CONFIG_NODE, &vtysh_interface_vrf_cmd);
   install_element (CONFIG_NODE, &vtysh_no_interface_vrf_cmd);
   install_element (ENABLE_NODE, &vtysh_show_running_config_cmd);
+  install_element (ENABLE_NODE, &vtysh_show_running_config_daemon_cmd);
   install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd);
   install_element (ENABLE_NODE, &vtysh_write_file_cmd);
   install_element (ENABLE_NODE, &vtysh_write_cmd);
 
   /* "write terminal" command. */
   install_element (ENABLE_NODE, &vtysh_write_terminal_cmd);
+  install_element (ENABLE_NODE, &vtysh_write_terminal_daemon_cmd);
  
   install_element (CONFIG_NODE, &vtysh_integrated_config_cmd);
   install_element (CONFIG_NODE, &no_vtysh_integrated_config_cmd);
diff --git a/zebra/client_main.c b/zebra/client_main.c
index 06afc56..43ab299 100644
--- a/zebra/client_main.c
+++ b/zebra/client_main.c
@@ -193,13 +193,15 @@
 int
 main (int argc, char **argv)
 {
+  struct thread_master *master;
   FILE *fp;
 
   if (argc == 1)
       usage_exit ();
 
+  master = thread_master_create ();
   /* Establish connection to zebra. */
-  zclient = zclient_new ();
+  zclient = zclient_new (master);
   zclient->enable = 1;
 #ifdef HAVE_TCP_ZEBRA
   zclient->sock = zclient_socket ();