Browse Source

Merge branch 'quagga' into google-bgp-multipath

Conflicts:
	bgpd/bgp_route.c
Avneesh Sachdev 8 years ago
parent
commit
3cf6c2b4e4
100 changed files with 11323 additions and 1705 deletions
  1. 0 30
      .cvsignore
  2. 0 357
      HACKING
  3. 5 0
      HACKING.pending
  4. 462 0
      HACKING.tex
  5. 0 2
      INSTALL.quagga.txt
  6. 12 2
      Makefile.am
  7. 7 0
      babeld/.gitignore
  8. 36 0
      babeld/LICENCE
  9. 29 0
      babeld/Makefile.am
  10. 124 0
      babeld/babel_filter.c
  11. 49 0
      babeld/babel_filter.h
  12. 1022 0
      babeld/babel_interface.c
  13. 152 0
      babeld/babel_interface.h
  14. 532 0
      babeld/babel_main.c
  15. 57 0
      babeld/babel_main.h
  16. 378 0
      babeld/babel_zebra.c
  17. 50 0
      babeld/babel_zebra.h
  18. 728 0
      babeld/babeld.c
  19. 30 0
      babeld/babeld.conf.sample
  20. 141 0
      babeld/babeld.h
  21. 76 0
      babeld/kernel.c
  22. 69 0
      babeld/kernel.h
  23. 275 0
      babeld/kernel_zebra.c
  24. 1561 0
      babeld/message.c
  25. 111 0
      babeld/message.h
  26. 343 0
      babeld/neighbour.c
  27. 66 0
      babeld/neighbour.h
  28. 239 0
      babeld/net.c
  29. 44 0
      babeld/net.h
  30. 330 0
      babeld/resend.c
  31. 77 0
      babeld/resend.h
  32. 1019 0
      babeld/route.c
  33. 135 0
      babeld/route.h
  34. 180 0
      babeld/source.c
  35. 67 0
      babeld/source.h
  36. 445 0
      babeld/util.c
  37. 165 0
      babeld/util.h
  38. 237 0
      babeld/xroute.c
  39. 59 0
      babeld/xroute.h
  40. 0 15
      bgpd/.cvsignore
  41. 5 5
      bgpd/bgp_advertise.c
  42. 79 81
      bgpd/bgp_aspath.c
  43. 2 2
      bgpd/bgp_aspath.h
  44. 632 378
      bgpd/bgp_attr.c
  45. 24 6
      bgpd/bgp_attr.h
  46. 2 2
      bgpd/bgp_clist.c
  47. 7 6
      bgpd/bgp_community.c
  48. 1 1
      bgpd/bgp_community.h
  49. 4 0
      bgpd/bgp_debug.c
  50. 24 23
      bgpd/bgp_ecommunity.c
  51. 2 2
      bgpd/bgp_ecommunity.h
  52. 4 4
      bgpd/bgp_fsm.c
  53. 8 1
      bgpd/bgp_main.c
  54. 6 2
      bgpd/bgp_mplsvpn.c
  55. 44 50
      bgpd/bgp_network.c
  56. 90 56
      bgpd/bgp_nexthop.c
  57. 1 1
      bgpd/bgp_nexthop.h
  58. 16 24
      bgpd/bgp_open.c
  59. 82 45
      bgpd/bgp_packet.c
  60. 62 60
      bgpd/bgp_route.c
  61. 3 1
      bgpd/bgp_route.h
  62. 138 15
      bgpd/bgp_routemap.c
  63. 78 203
      bgpd/bgp_vty.c
  64. 25 18
      bgpd/bgp_zebra.c
  65. 2 2
      bgpd/bgp_zebra.h
  66. 11 7
      bgpd/bgpd.c
  67. 5 4
      bgpd/bgpd.h
  68. 91 29
      configure.ac
  69. 0 31
      doc/.cvsignore
  70. 14 16
      doc/BGP-TypeCode
  71. 5 5
      doc/Makefile.am
  72. 118 0
      doc/babeld.texi
  73. 2 2
      doc/basic.texi
  74. 30 0
      doc/bgpd.texi
  75. 33 21
      doc/ipv6.texi
  76. 0 2
      doc/mpls/.cvsignore
  77. 1 5
      doc/ospfd.texi
  78. 2 0
      doc/quagga.texi
  79. 4 4
      doc/ripd.texi
  80. 0 7
      guile/.cvsignore
  81. 0 3
      init/.cvsignore
  82. 0 12
      isisd/.cvsignore
  83. 0 3
      isisd/dict.c
  84. 0 3
      isisd/include-netbsd/.cvsignore
  85. 1 1
      isisd/isis_adjacency.c
  86. 65 5
      isisd/isis_circuit.c
  87. 1 0
      isisd/isis_circuit.h
  88. 1 0
      isisd/isis_common.h
  89. 6 3
      isisd/isis_csm.c
  90. 20 3
      isisd/isis_lsp.c
  91. 0 1
      isisd/isis_lsp.h
  92. 16 10
      isisd/isis_main.c
  93. 178 100
      isisd/isis_pdu.c
  94. 2 3
      isisd/isis_pdu.h
  95. 4 0
      isisd/isis_pfpacket.c
  96. 37 28
      isisd/isis_spf.c
  97. 6 2
      isisd/isis_tlv.c
  98. 5 0
      isisd/isis_zebra.c
  99. 12 1
      isisd/isisd.c
  100. 0 0
      isisd/isisd.h

+ 0 - 30
.cvsignore

@@ -1,30 +0,0 @@
-config.log
-config.h
-config.cache
-config.status
-config.guess
-config.sub
-ltmain.sh
-stamp-h
-stamp-h[0-9]*
-*-stamp
-Makefile
-INSTALL
-.deps
-depcomp
-missing
-install-sh
-autom4te*.cache
-configure.lineno
-configure
-config.h.in
-aclocal.m4
-Makefile.in
-zebra-[0-9.][0-9.][0-9.]*.tar.gz
-quagga-[0-9.][0-9.][0-9.]*.tar.gz
-quagga-[0-9.][0-9.][0-9.]*.tar.gz.asc
-.nfs*
-libtool
-.arch-inventory
-.arch-ids
-{arch}

+ 0 - 357
HACKING

@@ -1,357 +0,0 @@
--*- mode: text; -*-
-$QuaggaId: Format:%an, %ai, %h$ $
-
-Contents:
-
-* GUIDELINES FOR HACKING ON QUAGGA
-* COMPILE-TIME CONDITIONAL CODE
-* COMMIT MESSAGE
-* HACKING THE BUILD SYSTEM
-* RELEASE PROCEDURE
-* SHARED LIBRARY VERSIONING
-* RELEASE PROCEDURE
-* TOOL VERSIONS
-* SHARED LIBRARY VERSIONING
-* PATCH SUBMISSION
-* PATCH APPLICATION
-* STABLE PLATFORMS AND DAEMONS
-* IMPORT OR UPDATE VENDOR SPECIFIC ROUTING PROTOCOLS
-
-
-GUIDELINES FOR HACKING ON QUAGGA
-
-[this is a draft in progress]
-
-GNU coding standards apply.  Indentation follows the result of
-invoking GNU indent (as of 2.2.8a) with no arguments.  Note that this
-uses tabs instead of spaces where possible for leading whitespace, and
-assumes that tabs are every 8 columns.  Do not attempt to redefine the
-location of tab stops.  Note also that some indentation does not
-follow GNU style.  This is a historical accident, and we generally
-only clean up whitespace when code is unmaintainable due to whitespace
-issues, as fewer changes from zebra lead to easier merges.
-
-For GNU emacs, use indentation style "gnu".
-
-For Vim, use the following lines (note that tabs are at 8, and that
-softtabstop sets the indentation level):
-
-set tabstop=8
-set softtabstop=2
-set shiftwidth=2
-set noexpandtab
-
-Be particularly careful not to break platforms/protocols that you
-cannot test.
-
-New code should have good comments, and 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 for an example;
-
-This placeholder string will be expanded out by the 'git archive' commands,
-wihch 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:
-
-  lib/log.h	logging levels and usage guidance
-  [more to be added]
-
-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, ie:
-
-/* Deprecated: 20050406 */
-#if !defined(QUAGGA_NO_DEPRECATED_INTERFACES)
-#warning "Using deprecated <libname> (interface(s)|function(s))"
-...
-#endif /* QUAGGA_NO_DEPRECATED_INTERFACES */
-
-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. Deprecated commands should be excised in the next
-unstable cycle. A list of deprecated commands should be collated for each
-release.
-
-See also below regarding SHARED LIBRARY VERSIONING.
-
-
-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 gratuitious --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. 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 should 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.
-
-* An optional introduction, discussing the general intent of the change.
-* A short description of each change made, preferably:
-  * file by file
-    * function by function (use of "ditto", or globs is allowed)
-
-to provide a short description of the general intent of the patch, in terms
-of the problem it solves and how it achieves it, to help reviewers
-understand.
-
-The one-line summary must be limited to 54 characters, and all other
-lines to 72 characters.
-
-The reason for such itemised commit messages is to encourage the author to
-self-review every line of the patch, as well as provide reviewers an index
-of which changes are intended, along with a short description for each.
-Some discretion is obviously required.  A C-to-english description is not
-desireable.  For short patches, a per-function/file break-down may be
-redundant.  For longer patches, such a break-down may be essential.
-
-An example (where the general discussion is obviously somewhat redundant,
-given the one-line summary):
-
-zebra: Enhance frob FSM to detect loss of frob
-
-* (general) 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.
-
-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 apppropriate 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:
-
-    git-clone git:///code.quagga.net/quagga.git quagga
-    git-archive --remote=git://code.quagga.net/quagga.git \
-        --prefix=quagga-release/ master | tar -xf -
-    cd quagga-release
-
-    autoreconf -i
-    ./configure
-    make
-    make dist
-
-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
-
-[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 SUBSMISSION
-
-The preferred method for changes is to provide git commits via a
-publically-accessible git repository.
-
-All content guidelines in PATCH SUBMISSION apply.
-
-
-PATCH SUBMISSION
-
-* 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 repostory.
-
-  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.
-
-* 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
-  mailinglist.
-
-* 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 ..'
-
-* By committing a patch, you are responsible for fixing problems
-  resulting from it (or backing it out).
-
-
-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) # without capabilities
-  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.

+ 5 - 0
HACKING.pending

@@ -14,6 +14,11 @@ collected in his git repository.
 
 * public git repositories
 
+** git remote add quagga-re git://github.com/Quagga-RE/quagga-RE.git
+
+Maintained by Denis Ovsienko, and geared towards producing a
+production-ready branch of Quagga, in the Quagga-RE-stable branch.
+
 ** git remote add equinox git://git.spaceboyz.net/equinox/quagga.git/
 
 This repository has topic branches for patches intended for inclusion

+ 462 - 0
HACKING.tex

@@ -0,0 +1,462 @@
+%% -*- 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 no arguments.  Note that this
+uses tabs instead of spaces where possible for leading whitespace, and
+assumes that tabs are every 8 columns.  Do not attempt to redefine the
+location of tab stops.  Note also that some indentation does not
+follow GNU style.  This is a historical accident, and we generally
+only clean up whitespace when code is unmaintainable due to whitespace
+issues, to minimise merging conflicts.
+
+For GNU emacs, use indentation style ``gnu''.
+
+For Vim, use the following lines (note that tabs are at 8, and that
+softtabstop sets the indentation level):
+
+set tabstop=8
+set softtabstop=2
+set shiftwidth=2
+set noexpandtab
+
+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,
+wihch 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, ie:
+
+\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{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 gratuitious --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 desireable - 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 apppropriate 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}
+    git-clone git:///code.quagga.net/quagga.git quagga
+    git-archive --remote=git://code.quagga.net/quagga.git \
+        --prefix=quagga-release/ master | tar -xf -
+    cd quagga-release
+
+    autoreconf -i
+    ./configure
+    make
+    make dist
+  \end{verbatim}
+\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
+publically-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 contraversial and most
+      trivial are first, and the most complex or more contraversial 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
+      mailinglist.
+
+\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}

+ 0 - 2
INSTALL.quagga.txt

@@ -1,5 +1,3 @@
-# $Id$
-
 --------------------------------------------------------------------------
 Building and Installing Quagga from releases or snapshots:
 

+ 12 - 2
Makefile.am

@@ -1,10 +1,10 @@
 ## Process this file with automake to produce Makefile.in.
 
-SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ \
+SUBDIRS = lib @ZEBRA@ @BGPD@ @RIPD@ @RIPNGD@ @OSPFD@ @OSPF6D@ @BABELD@ \
          @ISISD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
          redhat @SOLARIS@
 
-DIST_SUBDIRS = lib zebra bgpd ripd ripngd ospfd ospf6d \
+DIST_SUBDIRS = lib zebra bgpd ripd ripngd ospfd ospf6d babeld \
 	  isisd watchquagga vtysh ospfclient doc m4 pkgsrc redhat tests \
 	  solaris
 
@@ -14,4 +14,14 @@ EXTRA_DIST = aclocal.m4 SERVICES TODO REPORTING-BUGS INSTALL.quagga.txt \
 	tools/mrlg.cgi tools/rrcheck.pl tools/rrlookup.pl tools/zc.pl \
 	tools/zebra.el tools/multiple-bgpd.sh
 
+if HAVE_LATEX
+
+HACKING.pdf: HACKING.tex
+	$(LATEXMK) -pdf $<
+
+clean-local:
+	-$(LATEXMK) -C HACKING.tex
+
+endif
+
 ACLOCAL_AMFLAGS = -I m4

+ 7 - 0
babeld/.gitignore

@@ -0,0 +1,7 @@
+*
+!*.c
+!*.h
+!LICENCE
+!Makefile.am
+!babeld.conf.sample
+!.gitignore

+ 36 - 0
babeld/LICENCE

@@ -0,0 +1,36 @@
+Code in this directory is made available under the following licence:
+
+  ---------------------------------------------------------------------------
+  Copyright (c) 2007, 2008 by Juliusz Chroboczek
+  
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+  
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+  
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+  ---------------------------------------------------------------------------
+
+The code also makes calls to and links with the "libzebra" code of Quagga,
+in the lib/ directory of this project, which is subject to the GPL licence
+as given in the top-level COPYING file included with Quagga.
+
+Contributors to the code in babeld/ are asked to make their work available
+under the same MIT/X11 licence as given immediately above.  Please indicate
+your assent to this by updating this file and appending the appropriate
+
+  Copyright <year> <Author name>, <author contact details>
+
+line to the existing copyright assertion lines in the MIT/X11 licence text
+above in this file.

+ 29 - 0
babeld/Makefile.am

@@ -0,0 +1,29 @@
+## Process this file with automake to produce Makefile.in.
+
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib @SNMP_INCLUDES@
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+INSTALL_SDATA=@INSTALL@ -m 600
+
+AM_CFLAGS = $(PICFLAGS)
+AM_LDFLAGS = $(PILDFLAGS)
+
+noinst_LIBRARIES = libbabel.a
+sbin_PROGRAMS = babeld
+
+libbabel_a_SOURCES = \
+	babel_zebra.c net.c kernel.c util.c source.c neighbour.c	\
+	route.c xroute.c message.c resend.c babel_interface.c babeld.c	\
+	babel_filter.c
+
+noinst_HEADERS = \
+	babel_zebra.h net.h kernel.h util.h source.h neighbour.h	\
+	route.h xroute.h message.h resend.h babel_interface.h babeld.h	\
+	babel_filter.h
+
+babeld_SOURCES = \
+	babel_main.c $(libbabel_a_SOURCES)
+
+babeld_LDADD = ../lib/libzebra.la @LIBCAP@
+
+examplesdir = $(exampledir)
+dist_examples_DATA = babeld.conf.sample

+ 124 - 0
babeld/babel_filter.c

@@ -0,0 +1,124 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *  
+
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "babel_filter.h"
+#include "vty.h"
+#include "filter.h"
+#include "log.h"
+#include "plist.h"
+#include "distribute.h"
+#include "util.h"
+
+int
+babel_filter(int output, const unsigned char *prefix, unsigned short plen,
+             unsigned int ifindex)
+{
+    struct interface *ifp = if_lookup_by_index(ifindex);
+    babel_interface_nfo *babel_ifp = ifp ? babel_get_if_nfo(ifp) : NULL;
+    struct prefix p;
+    struct distribute *dist;
+    struct access_list *alist;
+    struct prefix_list *plist;
+    int filter = output ? BABEL_FILTER_OUT : BABEL_FILTER_IN;
+    int distribute = output ? DISTRIBUTE_OUT : DISTRIBUTE_IN;
+
+    p.family = v4mapped(prefix) ? AF_INET : AF_INET6;
+    p.prefixlen = v4mapped(prefix) ? plen - 96 : plen;
+    if (p.family == AF_INET)
+        uchar_to_inaddr(&p.u.prefix4, prefix);
+    else
+        uchar_to_in6addr(&p.u.prefix6, prefix);
+
+    if (babel_ifp != NULL && babel_ifp->list[filter]) {
+        if (access_list_apply (babel_ifp->list[filter], &p)
+            == FILTER_DENY) {
+            debugf(BABEL_DEBUG_FILTER,
+                   "%s/%d filtered by distribute in",
+                   p.family == AF_INET ?
+                   inet_ntoa(p.u.prefix4) :
+                   inet6_ntoa (p.u.prefix6),
+                   p.prefixlen);
+            return INFINITY;
+	}
+    }
+    if (babel_ifp != NULL && babel_ifp->prefix[filter]) {
+        if (prefix_list_apply (babel_ifp->prefix[filter], &p)
+            == PREFIX_DENY) {
+            debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in",
+                        p.family == AF_INET ?
+                        inet_ntoa(p.u.prefix4) :
+                        inet6_ntoa (p.u.prefix6),
+                        p.prefixlen);
+            return INFINITY;
+	}
+    }
+
+    /* All interface filter check. */
+    dist = distribute_lookup (NULL);
+    if (dist) {
+        if (dist->list[distribute]) {
+            alist = access_list_lookup (AFI_IP6, dist->list[distribute]);
+
+            if (alist) {
+                if (access_list_apply (alist, &p) == FILTER_DENY) {
+                    debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in",
+                                p.family == AF_INET ?
+                                inet_ntoa(p.u.prefix4) :
+                                inet6_ntoa (p.u.prefix6),
+                                p.prefixlen);
+                    return INFINITY;
+		}
+	    }
+	}
+        if (dist->prefix[distribute]) {
+            plist = prefix_list_lookup (AFI_IP6, dist->prefix[distribute]);
+            if (plist) {
+                if (prefix_list_apply (plist, &p) == PREFIX_DENY) {
+                    debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in",
+                                p.family == AF_INET ?
+                                inet_ntoa(p.u.prefix4) :
+                                inet6_ntoa (p.u.prefix6),
+                                p.prefixlen);
+                    return INFINITY;
+		}
+	    }
+	}
+    }
+    return 0;
+}

+ 49 - 0
babeld/babel_filter.h

@@ -0,0 +1,49 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *  
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef BABELD_BABEL_FILTER_H
+#define BABELD_BABEL_FILTER_H
+
+#include <zebra.h>
+#include "prefix.h"
+#include "babel_interface.h"
+
+int babel_filter(int output, const unsigned char *prefix, unsigned short plen,
+                 unsigned int index);
+
+#endif /* BABELD_BABEL_FILTER_H */

File diff suppressed because it is too large
+ 1022 - 0
babeld/babel_interface.c


+ 152 - 0
babeld/babel_interface.h

@@ -0,0 +1,152 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *  
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef BABEL_INTERFACE_H
+#define BABEL_INTERFACE_H
+
+#include <zebra.h>
+#include "zclient.h"
+#include "vty.h"
+
+#define CONFIG_DEFAULT 0
+#define CONFIG_NO 1
+#define CONFIG_YES 2
+
+/* babeld interface informations */
+struct babel_interface {
+    unsigned short flags;                     /* see below */
+    unsigned short cost;
+    int channel;
+    struct timeval hello_timeout;
+    struct timeval update_timeout;
+    struct timeval flush_timeout;
+    struct timeval update_flush_timeout;
+    unsigned char *ipv4;
+    int buffered;
+    int bufsize;
+    char have_buffered_hello;
+    char have_buffered_id;
+    char have_buffered_nh;
+    char have_buffered_prefix;
+    unsigned char buffered_id[16];
+    unsigned char buffered_nh[4];
+    unsigned char buffered_prefix[16];
+    unsigned char *sendbuf;
+    struct buffered_update *buffered_updates;
+    int num_buffered_updates;
+    int update_bufsize;
+    time_t bucket_time;
+    unsigned int bucket;
+    time_t last_update_time;
+    unsigned short hello_seqno;
+    unsigned hello_interval;
+    unsigned update_interval;
+
+    /* For filter type slot. */
+#define BABEL_FILTER_IN  0
+#define BABEL_FILTER_OUT 1
+#define BABEL_FILTER_MAX 2
+    struct access_list *list[BABEL_FILTER_MAX];               /* Access-list. */
+    struct prefix_list *prefix[BABEL_FILTER_MAX];             /* Prefix-list. */
+};
+
+typedef struct babel_interface babel_interface_nfo;
+static inline babel_interface_nfo* babel_get_if_nfo(struct interface *ifp)
+{
+    return ((babel_interface_nfo*) ifp->info);
+}
+
+/* babel_interface_nfo flags */
+#define BABEL_IF_IS_UP         (1 << 0)
+#define BABEL_IF_WIRED         (1 << 1)
+#define BABEL_IF_SPLIT_HORIZON (1 << 2)
+#define BABEL_IF_LQ            (1 << 3)
+#define BABEL_IF_FARAWAY       (1 << 4)
+
+/* Only INTERFERING can appear on the wire. */
+#define BABEL_IF_CHANNEL_UNKNOWN 0
+#define BABEL_IF_CHANNEL_INTERFERING 255
+#define BABEL_IF_CHANNEL_NONINTERFERING -2
+
+static inline int
+if_up(struct interface *ifp)
+{
+    return (if_is_operative(ifp) &&
+            ifp->connected != NULL &&
+            (babel_get_if_nfo(ifp)->flags & BABEL_IF_IS_UP));
+}
+
+/* types:
+ struct interface _ifp, struct listnode node */
+#define FOR_ALL_INTERFACES(_ifp, _node)                                              \
+    for(ALL_LIST_ELEMENTS_RO(iflist, _node, _ifp))
+
+/* types:
+ struct interface *ifp, struct connected *_connected, struct listnode *node */
+#define FOR_ALL_INTERFACES_ADDRESSES(ifp, _connected, _node)                   \
+    for(ALL_LIST_ELEMENTS_RO(ifp->connected, _node, _connected))
+
+struct buffered_update {
+    unsigned char id[8];
+    unsigned char prefix[16];
+    unsigned char plen;
+    unsigned char pad[3];
+};
+
+
+/* init function */
+void babel_if_init(void);
+
+/* Callback functions for zebra client */
+int babel_interface_up (int, struct zclient *, zebra_size_t);
+int babel_interface_down (int, struct zclient *, zebra_size_t);
+int babel_interface_add (int, struct zclient *, zebra_size_t);
+int babel_interface_delete (int, struct zclient *, zebra_size_t);
+int babel_interface_address_add (int, struct zclient *, zebra_size_t);
+int babel_interface_address_delete (int, struct zclient *, zebra_size_t);
+
+unsigned jitter(babel_interface_nfo *, int);
+unsigned update_jitter(babel_interface_nfo *babel_ifp, int urgent);
+/* return "true" if "address" is one of our ipv6 addresses */
+int is_interface_ll_address(struct interface *ifp, const unsigned char *address);
+/* Send retraction to all, and reset all interfaces statistics. */
+void babel_interface_close_all(void);
+extern int babel_enable_if_config_write (struct vty *);
+
+
+#endif

+ 532 - 0
babeld/babel_main.c

@@ -0,0 +1,532 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *  
+
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/* include zebra library */
+#include <zebra.h>
+#include "getopt.h"
+#include "if.h"
+#include "log.h"
+#include "thread.h"
+#include "privs.h"
+#include "sigevent.h"
+#include "version.h"
+#include "command.h"
+#include "vty.h"
+#include "memory.h"
+
+#include "babel_main.h"
+#include "babeld.h"
+#include "util.h"
+#include "kernel.h"
+#include "babel_interface.h"
+#include "neighbour.h"
+#include "route.h"
+#include "xroute.h"
+#include "message.h"
+#include "resend.h"
+#include "babel_zebra.h"
+
+
+static void babel_init (int argc, char **argv);
+static char *babel_get_progname(char *argv_0);
+static void babel_fail(void);
+static void babel_init_random(void);
+static void babel_replace_by_null(int fd);
+static void babel_init_signals(void);
+static void babel_exit_properly(void);
+static void babel_save_state_file(void);
+
+
+struct thread_master *master;     /* quagga's threads handler */
+struct timeval babel_now;         /* current time             */
+
+unsigned char myid[8];            /* unique id (mac address of an interface) */
+int debug = 0;
+
+int resend_delay = -1;
+static const char *pidfile = PATH_BABELD_PID;
+
+const unsigned char zeroes[16] = {0};
+const unsigned char ones[16] =
+    {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+static const char *state_file = DAEMON_VTY_DIR "/babel-state";
+
+unsigned char protocol_group[16]; /* babel's link-local multicast address */
+int protocol_port;                /* babel's port */
+int protocol_socket = -1;         /* socket: communicate with others babeld */
+
+static char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
+static char *babel_config_file = NULL;
+static char *babel_vty_addr = NULL;
+static int babel_vty_port = BABEL_VTY_PORT;
+
+/* Babeld options. */
+struct option longopts[] =
+{
+    { "daemon",      no_argument,       NULL, 'd'},
+    { "config_file", required_argument, NULL, 'f'},
+    { "pid_file",    required_argument, NULL, 'i'},
+    { "socket",      required_argument, NULL, 'z'},
+    { "help",        no_argument,       NULL, 'h'},
+    { "vty_addr",    required_argument, NULL, 'A'},
+    { "vty_port",    required_argument, NULL, 'P'},
+    { "user",        required_argument, NULL, 'u'},
+    { "group",       required_argument, NULL, 'g'},
+    { "version",     no_argument,       NULL, 'v'},
+    { 0 }
+};
+
+/* babeld privileges */
+static zebra_capabilities_t _caps_p [] =
+{
+    ZCAP_NET_RAW,
+    ZCAP_BIND
+};
+static struct zebra_privs_t babeld_privs =
+{
+#if defined(QUAGGA_USER)
+    .user = QUAGGA_USER,
+#endif
+#if defined QUAGGA_GROUP
+    .group = QUAGGA_GROUP,
+#endif
+#ifdef VTY_GROUP
+    .vty_group = VTY_GROUP,
+#endif
+    .caps_p = _caps_p,
+    .cap_num_p = 2,
+    .cap_num_i = 0
+};
+
+
+int
+main(int argc, char **argv)
+{
+    struct thread thread;
+    /* and print banner too */
+    babel_init(argc, argv);
+    while (thread_fetch (master, &thread)) {
+        thread_call (&thread);
+    }
+    return 0;
+}
+
+static void
+babel_usage (char *progname, int status)
+{
+  if (status != 0)
+    fprintf (stderr, "Try `%s --help' for more information.\n", progname);
+  else
+    {
+      printf ("Usage : %s [OPTION...]\n\
+Daemon which manages Babel routing protocol.\n\n\
+-d, --daemon       Runs in daemon mode\n\
+-f, --config_file  Set configuration file name\n\
+-i, --pid_file     Set process identifier file name\n\
+-z, --socket       Set path of zebra socket\n\
+-A, --vty_addr     Set vty's bind address\n\
+-P, --vty_port     Set vty's port number\n\
+-u, --user         User to run as\n\
+-g, --group        Group to run as\n\
+-v, --version      Print program version\n\
+-h, --help         Display this help and exit\n\
+\n\
+Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+    }
+  exit (status);
+}
+
+/* make initialisations witch don't need infos about kernel(interfaces, etc.) */
+static void
+babel_init(int argc, char **argv)
+{
+    int rc, opt;
+    int do_daemonise = 0;
+    char *progname = NULL;
+
+    /* Set umask before anything for security */
+    umask (0027);
+    progname = babel_get_progname(argv[0]);
+
+    /* set default log (lib/log.h) */
+    zlog_default = openzlog(progname, ZLOG_BABEL,
+                            LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+    /* set log destination as stdout until the config file is read */
+    zlog_set_level(NULL, ZLOG_DEST_STDOUT, LOG_WARNING);
+
+    babel_init_random();
+
+    /* set the Babel's default link-local multicast address and Babel's port */
+    parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
+    protocol_port = 6696;
+
+    /* get options */
+    while(1) {
+        opt = getopt_long(argc, argv, "df:i:z:hA:P:u:g:v", longopts, 0);
+        if(opt < 0)
+            break;
+
+        switch(opt) {
+            case 0:
+                break;
+            case 'd':
+                do_daemonise = -1;
+                break;
+            case 'f':
+                babel_config_file = optarg;
+                break;
+            case 'i':
+                pidfile = optarg;
+                break;
+            case 'z':
+                zclient_serv_path_set (optarg);
+                break;
+            case 'A':
+                babel_vty_addr = optarg;
+                break;
+            case 'P':
+                babel_vty_port = atoi (optarg);
+                if (babel_vty_port <= 0 || babel_vty_port > 0xffff)
+                    babel_vty_port = BABEL_VTY_PORT;
+                break;
+            case 'u':
+                babeld_privs.user = optarg;
+                break;
+            case 'g':
+                babeld_privs.group = optarg;
+                break;
+            case 'v':
+                print_version (progname);
+                exit (0);
+                break;
+            case 'h':
+                babel_usage (progname, 0);
+                break;
+            default:
+                babel_usage (progname, 1);
+                break;
+        }
+    }
+
+    /* create the threads handler */
+    master = thread_master_create ();
+
+    /* Library inits. */
+    zprivs_init (&babeld_privs);
+    babel_init_signals();
+    cmd_init (1);
+    vty_init (master);
+    memory_init ();
+
+    resend_delay = BABEL_DEFAULT_RESEND_DELAY;
+
+    babel_replace_by_null(STDIN_FILENO);
+
+    if (do_daemonise && daemonise() < 0) {
+        zlog_err("daemonise: %s", safe_strerror(errno));
+        exit (1);
+    }
+
+    /* write pid file */
+    if (pid_output(pidfile) < 0) {
+        zlog_err("error while writing pidfile");
+        exit (1);
+    };
+
+    /* init some quagga's dependencies, and babeld's commands */
+    babeld_quagga_init();
+    /* init zebra client's structure and it's commands */
+    /* this replace kernel_setup && kernel_setup_socket */
+    babelz_zebra_init ();
+
+    /* Sort all installed commands. */
+    sort_node ();
+
+    /* Get zebra configuration file. */
+    zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
+    vty_read_config (babel_config_file, babel_config_default);
+
+    /* Create VTY socket */
+    vty_serv_sock (babel_vty_addr, babel_vty_port, BABEL_VTYSH_PATH);
+
+    /* init buffer */
+    rc = resize_receive_buffer(1500);
+    if(rc < 0)
+        babel_fail();
+
+    schedule_neighbours_check(5000, 1);
+
+    zlog_notice ("BABELd %s starting: vty@%d", BABEL_VERSION, babel_vty_port);
+}
+
+/* return the progname (without path, example: "./x/progname" --> "progname") */
+static char *
+babel_get_progname(char *argv_0) {
+    char *p = strrchr (argv_0, '/');
+    return (p ? ++p : argv_0);
+}
+
+static void
+babel_fail(void)
+{
+    exit(1);
+}
+
+/* initialize random value, and set 'babel_now' by the way. */
+static void
+babel_init_random(void)
+{
+    gettime(&babel_now);
+    int rc;
+    unsigned int seed;
+
+    rc = read_random_bytes(&seed, sizeof(seed));
+    if(rc < 0) {
+        zlog_err("read(random): %s", safe_strerror(errno));
+        seed = 42;
+    }
+
+    seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
+    srandom(seed);
+}
+
+/*
+ close fd, and replace it by "/dev/null"
+ exit if error
+ */
+static void
+babel_replace_by_null(int fd)
+{
+    int fd_null;
+    int rc;
+
+    fd_null = open("/dev/null", O_RDONLY);
+    if(fd_null < 0) {
+        zlog_err("open(null): %s", safe_strerror(errno));
+        exit(1);
+    }
+
+    rc = dup2(fd_null, fd);
+    if(rc < 0) {
+        zlog_err("dup2(null, 0): %s", safe_strerror(errno));
+        exit(1);
+    }
+
+    close(fd_null);
+}
+
+/*
+ Load the state file: check last babeld's running state, usefull in case of
+ "/etc/init.d/babeld restart"
+ */
+void
+babel_load_state_file(void)
+{
+    int fd;
+    int rc;
+
+    fd = open(state_file, O_RDONLY);
+    if(fd < 0 && errno != ENOENT)
+        zlog_err("open(babel-state: %s)", safe_strerror(errno));
+    rc = unlink(state_file);
+    if(fd >= 0 && rc < 0) {
+        zlog_err("unlink(babel-state): %s", safe_strerror(errno));
+        /* If we couldn't unlink it, it's probably stale. */
+        close(fd);
+        fd = -1;
+    }
+    if(fd >= 0) {
+        char buf[100];
+        char buf2[100];
+        int s;
+        long t;
+        rc = read(fd, buf, 99);
+        if(rc < 0) {
+            zlog_err("read(babel-state): %s", safe_strerror(errno));
+        } else {
+            buf[rc] = '\0';
+            rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
+            if(rc == 3 && s >= 0 && s <= 0xFFFF) {
+                unsigned char sid[8];
+                rc = parse_eui64(buf2, sid);
+                if(rc < 0) {
+                    zlog_err("Couldn't parse babel-state.");
+                } else {
+                    struct timeval realnow;
+                    debugf(BABEL_DEBUG_COMMON,
+                           "Got %s %d %ld from babel-state.",
+                           format_eui64(sid), s, t);
+                    gettimeofday(&realnow, NULL);
+                    if(memcmp(sid, myid, 8) == 0)
+                        myseqno = seqno_plus(s, 1);
+                    else
+                        zlog_err("ID mismatch in babel-state. id=%s; old=%s",
+                                 format_eui64(myid),
+                                 format_eui64(sid));
+                }
+            } else {
+                zlog_err("Couldn't parse babel-state.");
+            }
+        }
+        close(fd);
+        fd = -1;
+    }
+}
+
+static void
+babel_sigexit(void)
+{
+    zlog_notice("Terminating on signal");
+
+    babel_exit_properly();
+}
+
+static void
+babel_sigusr1 (void)
+{
+    zlog_rotate (NULL);
+}
+
+static void
+babel_init_signals(void)
+{
+    static struct quagga_signal_t babel_signals[] =
+    {
+        {
+            .signal = SIGUSR1,
+            .handler = &babel_sigusr1,
+        },
+        {
+            .signal = SIGINT,
+            .handler = &babel_sigexit,
+        },
+        {
+            .signal = SIGTERM,
+            .handler = &babel_sigexit,
+        },
+    };
+
+    signal_init (master, Q_SIGC(babel_signals), babel_signals);
+}
+
+static void
+babel_exit_properly(void)
+{
+    debugf(BABEL_DEBUG_COMMON, "Exiting...");
+    usleep(roughly(10000));
+    gettime(&babel_now);
+
+    /* Uninstall and flush all routes. */
+    debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
+    flush_all_routes();
+    babel_interface_close_all();
+    babel_zebra_close_connexion();
+    babel_save_state_file();
+    debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
+    if(pidfile)
+        unlink(pidfile);
+    debugf(BABEL_DEBUG_COMMON, "Done.");
+
+    exit(0);
+}
+
+static void
+babel_save_state_file(void)
+{
+    int fd;
+    int rc;
+
+    debugf(BABEL_DEBUG_COMMON, "Save state file.");
+    fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
+    if(fd < 0) {
+        zlog_err("creat(babel-state): %s", safe_strerror(errno));
+        unlink(state_file);
+    } else {
+        struct timeval realnow;
+        char buf[100];
+        gettimeofday(&realnow, NULL);
+        rc = snprintf(buf, 100, "%s %d %ld\n",
+                      format_eui64(myid), (int)myseqno,
+                      (long)realnow.tv_sec);
+        if(rc < 0 || rc >= 100) {
+            zlog_err("write(babel-state): overflow.");
+            unlink(state_file);
+        } else {
+            rc = write(fd, buf, rc);
+            if(rc < 0) {
+                zlog_err("write(babel-state): %s", safe_strerror(errno));
+                unlink(state_file);
+            }
+            fsync(fd);
+        }
+        close(fd);
+    }
+}
+
+void
+show_babel_main_configuration (struct vty *vty)
+{
+    vty_out(vty,
+            "pid file                = %s%s"
+            "state file              = %s%s"
+            "configuration file      = %s%s"
+            "protocol informations:%s"
+            "  multicast address     = %s%s"
+            "  port                  = %d%s"
+            "vty address             = %s%s"
+            "vty port                = %d%s"
+            "id                      = %s%s"
+            "allow_duplicates        = %s%s"
+            "kernel_metric           = %d%s",
+            pidfile, VTY_NEWLINE,
+            state_file, VTY_NEWLINE,
+            babel_config_file ? babel_config_file : babel_config_default,
+            VTY_NEWLINE,
+            VTY_NEWLINE,
+            format_address(protocol_group), VTY_NEWLINE,
+            protocol_port, VTY_NEWLINE,
+            babel_vty_addr ? babel_vty_addr : "None",
+            VTY_NEWLINE,
+            babel_vty_port, VTY_NEWLINE,
+            format_eui64(myid), VTY_NEWLINE,
+            format_bool(allow_duplicates), VTY_NEWLINE,
+            kernel_metric, VTY_NEWLINE);
+}

+ 57 - 0
babeld/babel_main.h

@@ -0,0 +1,57 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *  
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "vty.h"
+
+extern struct timeval babel_now;         /* current time             */
+extern struct thread_master *master;     /* quagga's threads handler */
+extern int debug;
+extern int resend_delay;
+
+extern unsigned char myid[8];
+
+extern const unsigned char zeroes[16], ones[16];
+
+extern int protocol_port;
+extern unsigned char protocol_group[16];
+extern int protocol_socket;
+extern int kernel_socket;
+extern int max_request_hopcount;
+
+void babel_load_state_file(void);
+void show_babel_main_configuration (struct vty *vty);

+ 378 - 0
babeld/babel_zebra.c

@@ -0,0 +1,378 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/* quagga's includes */
+#include <zebra.h>
+#include "command.h"
+#include "zclient.h"
+#include "stream.h"
+
+/* babel's includes*/
+#include "babel_zebra.h"
+#include "babel_interface.h"
+#include "xroute.h"
+#include "util.h"
+
+void babelz_zebra_init(void);
+
+
+/* we must use a pointer because of zclient.c's functions (new, free). */
+struct zclient *zclient;
+static int zebra_config_write (struct vty *vty);
+
+/* Debug types */
+static struct {
+    int type;
+    int str_min_len;
+    const char *str;
+} debug_type[] = {
+    {BABEL_DEBUG_COMMON,  1, "common"},
+    {BABEL_DEBUG_KERNEL,  1, "kernel"},
+    {BABEL_DEBUG_FILTER,  1, "filter"},
+    {BABEL_DEBUG_TIMEOUT, 1, "timeout"},
+    {BABEL_DEBUG_IF,      1, "interface"},
+    {BABEL_DEBUG_ROUTE,   1, "route"},
+    {BABEL_DEBUG_ALL,     1, "all"},
+    {0, 0, NULL}
+};
+
+/* Zebra node structure. */
+struct cmd_node zebra_node =
+{
+    ZEBRA_NODE,
+    "%s(config-router)# ",
+    1 /* vtysh? yes */
+};
+
+
+/* Zebra route add and delete treatment (ipv6). */
+static int
+babel_zebra_read_ipv6 (int command, struct zclient *zclient,
+		       zebra_size_t length)
+{
+    struct stream *s;
+    struct zapi_ipv6 api;
+    unsigned long ifindex = -1;
+    struct in6_addr nexthop;
+    struct prefix_ipv6 prefix;
+
+    s = zclient->ibuf;
+    ifindex = 0;
+    memset (&nexthop, 0, sizeof (struct in6_addr));
+    memset (&api, 0, sizeof(struct zapi_ipv6));
+    memset (&prefix, 0, sizeof (struct prefix_ipv6));
+
+    /* Type, flags, message. */
+    api.type = stream_getc (s);
+    api.flags = stream_getc (s);
+    api.message = stream_getc (s);
+
+    /* IPv6 prefix. */
+    prefix.family = AF_INET6;
+    prefix.prefixlen = stream_getc (s);
+    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
+
+    /* Nexthop, ifindex, distance, metric. */
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
+        api.nexthop_num = stream_getc (s);
+        stream_get (&nexthop, s, sizeof(nexthop));
+    }
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
+        api.ifindex_num = stream_getc (s);
+        ifindex = stream_getl (s);
+    }
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+        api.distance = stream_getc (s);
+    else
+        api.distance = 0;
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+        api.metric = stream_getl (s);
+    else
+        api.metric = 0;
+
+    if (command == ZEBRA_IPV6_ROUTE_ADD)
+        babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop);
+    else
+        babel_ipv6_route_delete(&api, &prefix, ifindex);
+
+    return 0;
+}
+
+static int
+babel_zebra_read_ipv4 (int command, struct zclient *zclient,
+		       zebra_size_t length)
+{
+    struct stream *s;
+    struct zapi_ipv4 api;
+    unsigned long ifindex = -1;
+    struct in_addr nexthop;
+    struct prefix_ipv4 prefix;
+
+    s = zclient->ibuf;
+    ifindex = 0;
+    memset (&nexthop, 0, sizeof (struct in_addr));
+    memset (&api, 0, sizeof(struct zapi_ipv4));
+    memset (&prefix, 0, sizeof (struct prefix_ipv4));
+
+    /* Type, flags, message. */
+    api.type = stream_getc (s);
+    api.flags = stream_getc (s);
+    api.message = stream_getc (s);
+
+    /* IPv6 prefix. */
+    prefix.family = AF_INET;
+    prefix.prefixlen = stream_getc (s);
+    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
+
+    /* Nexthop, ifindex, distance, metric. */
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
+        api.nexthop_num = stream_getc (s);
+        stream_get (&nexthop, s, sizeof(nexthop));
+    }
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
+        api.ifindex_num = stream_getc (s);
+        ifindex = stream_getl (s);
+    }
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+        api.distance = stream_getc (s);
+    else
+        api.distance = 0;
+    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+        api.metric = stream_getl (s);
+    else
+        api.metric = 0;
+
+    if (command == ZEBRA_IPV6_ROUTE_ADD) {
+        babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
+    } else {
+        babel_ipv4_route_delete(&api, &prefix, ifindex);
+    }
+
+    return 0;
+}
+
+/* [Babel Command] */
+DEFUN (babel_redistribute_type,
+       babel_redistribute_type_cmd,
+       "redistribute " QUAGGA_REDIST_STR_BABELD,
+       "Redistribute\n"
+       QUAGGA_REDIST_HELP_STR_BABELD)
+{
+    int type;
+
+    type = proto_redistnum(AFI_IP6, argv[0]);
+
+    if (type < 0)
+        type = proto_redistnum(AFI_IP, argv[0]);
+
+    if (type < 0) {
+        vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
+        return CMD_WARNING;
+    }
+
+    zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
+    return CMD_SUCCESS;
+}
+
+/* [Babel Command] */
+DEFUN (no_babel_redistribute_type,
+       no_babel_redistribute_type_cmd,
+       "no redistribute " QUAGGA_REDIST_STR_BABELD,
+       NO_STR
+       "Redistribute\n"
+       QUAGGA_REDIST_HELP_STR_BABELD)
+{
+    int type;
+
+    type = proto_redistnum(AFI_IP6, argv[0]);
+
+    if (type < 0)
+        type = proto_redistnum(AFI_IP, argv[0]);
+
+    if (type < 0) {
+        vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
+        return CMD_WARNING;
+    }
+
+    zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+    /* perhaps should we remove xroutes having the same type... */
+    return CMD_SUCCESS;
+}
+
+#ifndef NO_DEBUG
+/* [Babel Command] */
+DEFUN (debug_babel,
+       debug_babel_cmd,
+       "debug babel (common|kernel|filter|timeout|interface|route|all)",
+       "Enable debug messages for specific or all part.\n"
+       "Babel information\n"
+       "Common messages (default)\n"
+       "Kernel messages\n"
+       "Filter messages\n"
+       "Timeout messages\n"
+       "Interface messages\n"
+       "Route messages\n"
+       "All messages\n")
+{
+    int i;
+
+    for(i = 0; debug_type[i].str != NULL; i++) {
+        if (strncmp (debug_type[i].str, argv[0],
+                     debug_type[i].str_min_len) == 0) {
+            debug |= debug_type[i].type;
+            return CMD_SUCCESS;
+        }
+    }
+
+    vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
+
+    return CMD_WARNING;
+}
+
+/* [Babel Command] */
+DEFUN (no_debug_babel,
+       no_debug_babel_cmd,
+       "no debug babel (common|kernel|filter|timeout|interface|route|all)",
+       NO_STR
+       "Disable debug messages for specific or all part.\n"
+       "Babel information\n"
+       "Common messages (default)\n"
+       "Kernel messages\n"
+       "Filter messages\n"
+       "Timeout messages\n"
+       "Interface messages\n"
+       "Route messages\n"
+       "All messages\n")
+{
+    int i;
+
+    for (i = 0; debug_type[i].str; i++) {
+        if (strncmp(debug_type[i].str, argv[0],
+                    debug_type[i].str_min_len) == 0) {
+            debug &= ~debug_type[i].type;
+            return CMD_SUCCESS;
+        }
+    }
+
+    vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE);
+
+    return CMD_WARNING;
+}
+#endif /* NO_DEBUG */
+
+/* Output "debug" statement lines, if necessary. */
+int
+debug_babel_config_write (struct vty * vty)
+{
+#ifdef NO_DEBUG
+    return 0;
+#else
+    int i, lines = 0;
+
+    if (debug == BABEL_DEBUG_ALL)
+    {
+        vty_out (vty, "debug babel all%s", VTY_NEWLINE);
+        lines++;
+    }
+    else
+        for (i = 0; debug_type[i].str != NULL; i++)
+            if
+            (
+                debug_type[i].type != BABEL_DEBUG_ALL
+                && CHECK_FLAG (debug, debug_type[i].type)
+            )
+            {
+                vty_out (vty, "debug babel %s%s", debug_type[i].str, VTY_NEWLINE);
+                lines++;
+            }
+    if (lines)
+    {
+        vty_out (vty, "!%s", VTY_NEWLINE);
+        lines++;
+    }
+    return lines;
+#endif /* NO_DEBUG */
+}
+
+void babelz_zebra_init(void)
+{
+    zclient = zclient_new();
+    zclient_init(zclient, ZEBRA_ROUTE_BABEL);
+
+    zclient->interface_add = babel_interface_add;
+    zclient->interface_delete = babel_interface_delete;
+    zclient->interface_up = babel_interface_up;
+    zclient->interface_down = babel_interface_down;
+    zclient->interface_address_add = babel_interface_address_add;
+    zclient->interface_address_delete = babel_interface_address_delete;
+    zclient->ipv4_route_add = babel_zebra_read_ipv4;
+    zclient->ipv4_route_delete = babel_zebra_read_ipv4;
+    zclient->ipv6_route_add = babel_zebra_read_ipv6;
+    zclient->ipv6_route_delete = babel_zebra_read_ipv6;
+
+    install_node (&zebra_node, zebra_config_write);
+    install_element(BABEL_NODE, &babel_redistribute_type_cmd);
+    install_element(BABEL_NODE, &no_babel_redistribute_type_cmd);
+    install_element(ENABLE_NODE, &debug_babel_cmd);
+    install_element(ENABLE_NODE, &no_debug_babel_cmd);
+    install_element(CONFIG_NODE, &debug_babel_cmd);
+    install_element(CONFIG_NODE, &no_debug_babel_cmd);
+}
+
+static int
+zebra_config_write (struct vty *vty)
+{
+    if (! zclient->enable)
+    {
+        vty_out (vty, "no router zebra%s", VTY_NEWLINE);
+        return 1;
+    }
+    else if (! zclient->redist[ZEBRA_ROUTE_BABEL])
+    {
+        vty_out (vty, "router zebra%s", VTY_NEWLINE);
+        vty_out (vty, " no redistribute babel%s", VTY_NEWLINE);
+        return 1;
+    }
+    return 0;
+}
+
+void
+babel_zebra_close_connexion(void)
+{
+    zclient_stop(zclient);
+}

+ 50 - 0
babeld/babel_zebra.h

@@ -0,0 +1,50 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *  
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef BABEL_ZEBRA_H
+#define BABEL_ZEBRA_H
+
+#include "vty.h"
+
+extern struct zclient *zclient;
+
+void babelz_zebra_init(void);
+void babel_zebra_close_connexion(void);
+extern int debug_babel_config_write (struct vty *);
+
+#endif

+ 728 - 0
babeld/babeld.c

@@ -0,0 +1,728 @@
+/*  
+ *  This file is free software: you may copy, redistribute and/or modify it  
+ *  under the terms of the GNU General Public License as published by the  
+ *  Free Software Foundation, either version 2 of the License, or (at your  
+ *  option) any later version.  
+ *  
+ *  This file is distributed in the hope that it will be useful, but  
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of  
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
+ *  General Public License for more details.  
+ *  
+ *  You should have received a copy of the GNU General Public License  
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
+ *  
+ * This file incorporates work covered by the following copyright and  
+ * permission notice:  
+ *  
+
+Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <zebra.h>
+#include "command.h"
+#include "prefix.h"
+#include "memory.h"
+#include "memtypes.h"
+#include "table.h"
+#include "distribute.h"
+#include "prefix.h"
+#include "filter.h"
+#include "plist.h"
+
+#include "babel_main.h"
+#include "babeld.h"
+#include "util.h"
+#include "net.h"
+#include "kernel.h"
+#include "babel_interface.h"
+#include "neighbour.h"
+#include "route.h"
+#include "message.h"
+#include "resend.h"
+#include "babel_filter.h"
+#include "babel_zebra.h"
+
+
+static int babel_init_routing_process(struct thread *thread);
+static void babel_get_myid(void);
+static void babel_initial_noise(void);
+static int babel_read_protocol (struct thread *thread);
+static int babel_main_loop(struct thread *thread);
+static void babel_set_timer(struct timeval *timeout);
+static void babel_fill_with_next_timeout(struct timeval *tv);
+
+
+/* Informations relative to the babel running daemon. */
+static struct babel *babel_routing_process = NULL;
+static unsigned char *receive_buffer = NULL;
+static int receive_buffer_size = 0;
+
+/* timeouts */
+struct timeval check_neighbours_timeout;
+static time_t expiry_time;
+static time_t source_expiry_time;
+
+/* Babel node structure. */
+static struct cmd_node cmd_babel_node =
+{
+    .node   = BABEL_NODE,
+    .prompt = "%s(config-router)# ",
+    .vtysh  = 1,
+};
+
+/* print current babel configuration on vty */
+static int
+babel_config_write (struct vty *vty)
+{
+    int lines = 0;
+    int i;
+
+    /* list enabled debug modes */
+    lines += debug_babel_config_write (vty);
+
+    if (!babel_routing_process)
+        return lines;
+    vty_out (vty, "router babel%s", VTY_NEWLINE);
+    if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
+    {
+        vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE);
+        lines++;
+    }
+    /* list enabled interfaces */
+    lines = 1 + babel_enable_if_config_write (vty);
+    /* list redistributed protocols */
+    for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+        if (i != zclient->redist_default && zclient->redist[i])
+        {
+            vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE);
+            lines++;
+        }
+
+    return lines;
+}
+
+
+static int
+babel_create_routing_process (void)
+{
+    assert (babel_routing_process == NULL);
+
+    /* Allocaste Babel instance. */
+    babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
+
+    /* Initialize timeouts */
+    gettime(&babel_now);
+    expiry_time = babel_now.tv_sec + roughly(30);
+    source_expiry_time = babel_now.tv_sec + roughly(300);
+
+    /* Make socket for Babel protocol. */
+    protocol_socket = babel_socket(protocol_port);
+    if (protocol_socket < 0) {
+        zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
+        goto fail;
+    }
+
+    /* Threads. */
+    babel_routing_process->t_read =
+    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
+    /* wait a little: zebra will announce interfaces, addresses, routes... */
+    babel_routing_process->t_update =
+    thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L);
+    return 0;
+
+fail:
+    XFREE(MTYPE_BABEL, babel_routing_process);
+    babel_routing_process = NULL;
+    return -1;
+}
+
+/* thread reading entries form others babel daemons */
+static int
+babel_read_protocol (struct thread *thread)
+{
+    int rc;
+    struct interface *ifp = NULL;
+    struct sockaddr_in6 sin6;
+    struct listnode *linklist_node = NULL;
+
+    assert(babel_routing_process != NULL);
+    assert(protocol_socket >= 0);
+
+    rc = babel_recv(protocol_socket,
+                    receive_buffer, receive_buffer_size,
+                    (struct sockaddr*)&sin6, sizeof(sin6));
+    if(rc < 0) {
+        if(errno != EAGAIN && errno != EINTR) {
+            zlog_err("recv: %s", safe_strerror(errno));
+        }
+    } else {
+        FOR_ALL_INTERFACES(ifp, linklist_node) {
+            if(!if_up(ifp))
+                continue;
+            if(ifp->ifindex == sin6.sin6_scope_id) {
+                parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
+                             receive_buffer, rc);
+                break;
+            }
+        }
+    }
+
+    /* re-add thread */
+    babel_routing_process->t_read =
+    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
+    return 0;
+}
+
+/* Zebra will give some information, especially about interfaces. This function
+ must be call with a litte timeout wich may give zebra the time to do his job,
+ making these inits have sense. */
+static int
+babel_init_routing_process(struct thread *thread)
+{
+    myseqno = (random() & 0xFFFF);
+    babel_get_myid();
+    babel_load_state_file();
+    debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
+    babel_initial_noise();
+    babel_main_loop(thread);/* this function self-add to the t_update thread */
+    return 0;
+}
+
+/* fill "myid" with an unique id (only if myid != {0}). */
+static void
+babel_get_myid(void)
+{
+    struct interface *ifp = NULL;
+    struct listnode *linklist_node = NULL;
+    int rc;
+    int i;
+
+    /* if we already have an id (from state file), we return. */
+    if (memcmp(myid, zeroes, 8) != 0) {
+        return;
+    }
+
+    FOR_ALL_INTERFACES(ifp, linklist_node) {
+        /* ifp->ifindex is not necessarily valid at this point */
+        int ifindex = if_nametoindex(ifp->name);
+        if(ifindex > 0) {
+            unsigned char eui[8];
+            rc = if_eui64(ifp->name, ifindex, eui);
+            if(rc < 0)
+                continue;
+            memcpy(myid, eui, 8);
+            return;
+        }
+    }
+
+    /* We failed to get a global EUI64 from the interfaces we were given.
+     Let's try to find an interface with a MAC address. */
+    for(i = 1; i < 256; i++) {
+        char buf[IF_NAMESIZE], *ifname;
+        unsigned char eui[8];
+        ifname = if_indextoname(i, buf);
+        if(ifname == NULL)
+            continue;
+        rc = if_eui64(ifname, i, eui);
+        if(rc < 0)
+            continue;
+        memcpy(myid, eui, 8);
+        return;
+    }
+
+    zlog_err("Warning: couldn't find router id -- using random value.");
+
+    rc = read_random_bytes(myid, 8);
+    if(rc < 0) {
+        zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
+        exit(1);
+    }
+    /* Clear group and global bits */
+    myid[0] &= ~3;
+}
+
+/* Make some noise so that others notice us, and send retractions in
+ case we were restarted recently */
+static void
+babel_initial_noise(void)
+{
+    struct interface *ifp = NULL;
+    struct listnode *linklist_node = NULL;
+
+    FOR_ALL_INTERFACES(ifp, linklist_node) {
+        if(!if_up(ifp))
+            continue;
+        /* Apply jitter before we send the first message. */
+        usleep(roughly(10000));
+        gettime(&babel_now);
+        send_hello(ifp);
+        send_wildcard_retraction(ifp);
+    }
+
+    FOR_ALL_INTERFACES(ifp, linklist_node) {
+        if(!if_up(ifp))
+            continue;
+        usleep(roughly(10000));
+        gettime(&babel_now);
+        send_hello(ifp);
+        send_wildcard_retraction(ifp);
+        send_self_update(ifp);
+        send_request(ifp, NULL, 0);
+        flushupdates(ifp);
+        flushbuf(ifp);
+    }
+}
+
+/* Delete all the added babel routes, make babeld only speak to zebra. */
+static void
+babel_clean_routing_process()
+{
+    flush_all_routes();
+    babel_interface_close_all();
+
+    /* cancel threads */
+    if (babel_routing_process->t_read != NULL) {
+        thread_cancel(babel_routing_process->t_read);
+    }
+    if (babel_routing_process->t_update != NULL) {
+        thread_cancel(babel_routing_process->t_update);
+    }
+
+    XFREE(MTYPE_BABEL, babel_routing_process);
+    babel_routing_process = NULL;
+}
+
+/* Function used with timeout. */
+static int
+babel_main_loop(struct thread *thread)
+{
+    struct timeval tv;
+    struct interface *ifp = NULL;
+    struct listnode *linklist_node = NULL;
+
+    while(1) {
+        gettime(&babel_now);
+
+        /* timeouts --------------------------------------------------------- */
+        /* get the next timeout */
+        babel_fill_with_next_timeout(&tv);
+        /* if there is no timeout, we must wait. */
+        if(timeval_compare(&tv, &babel_now) > 0) {
+            timeval_minus(&tv, &tv, &babel_now);
+            debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
+                   tv.tv_sec * 1000 + tv.tv_usec / 1000);
+            /* it happens often to have less than 1 ms, it's bad. */
+            timeval_add_msec(&tv, &tv, 300);
+            babel_set_timer(&tv);
+            return 0;
+        }
+
+        gettime(&babel_now);
+
+        /* update database -------------------------------------------------- */
+        if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
+            int msecs;
+            msecs = check_neighbours();
+            msecs = MAX(msecs, 10);
+            schedule_neighbours_check(msecs, 1);
+        }
+
+        if(babel_now.tv_sec >= expiry_time) {
+            expire_routes();
+            expire_resend();
+            expiry_time = babel_now.tv_sec + roughly(30);
+        }
+
+        if(babel_now.tv_sec >= source_expiry_time) {
+            expire_sources();
+            source_expiry_time = babel_now.tv_sec + roughly(300);
+        }
+
+        FOR_ALL_INTERFACES(ifp, linklist_node) {
+            babel_interface_nfo *babel_ifp = NULL;
+            if(!if_up(ifp))
+                continue;
+            babel_ifp = babel_get_if_nfo(ifp);
+            if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
+                send_hello(ifp);
+            if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
+                send_update(ifp, 0, NULL, 0);
+            if(timeval_compare(&babel_now,
+                               &babel_ifp->update_flush_timeout) >= 0)
+                flushupdates(ifp);
+        }
+
+        if(resend_time.tv_sec != 0) {
+            if(timeval_compare(&babel_now, &resend_time) >= 0)
+                do_resend();
+        }
+
+        if(unicast_flush_timeout.tv_sec != 0) {
+            if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
+                flush_unicast(1);
+        }
+
+        FOR_ALL_INTERFACES(ifp, linklist_node) {
+            babel_interface_nfo *babel_ifp = NULL;
+            if(!if_up(ifp))
+                continue;
+            babel_ifp = babel_get_if_nfo(ifp);
+            if(babel_ifp->flush_timeout.tv_sec != 0) {
+                if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
+                    flushbuf(ifp);
+            }
+        }
+    }
+
+    assert(0); /* this line should never be reach */
+}
+
+static void
+printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
+{
+    static struct timeval curr_tv;
+    static char buffer[200];
+    static const char *curr_tag = NULL;
+
+    switch (cmd) {
+        case 0: /* reset timeval */
+            curr_tv = *tv;
+            if(ifname != NULL) {
+                snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
+                curr_tag = buffer;
+            } else {
+                curr_tag = tag;
+            }
+            break;
+        case 1: /* take the min */
+            if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
+                break;
+            }
+            if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
+                                               tv->tv_usec < curr_tv.tv_usec)) {
+                curr_tv = *tv;
+                if(ifname != NULL) {
+                    snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
+                    curr_tag = buffer;
+                } else {
+                    curr_tag = tag;
+                }
+            }
+            break;
+        case 2: /* print message */
+            debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
+            break;
+        default:
+            break;
+    }
+}
+
+static void
+babel_fill_with_next_timeout(struct timeval *tv)
+{
+#if (defined NO_DEBUG)
+#define printIfMin(a,b,c,d)
+#else
+#define printIfMin(a,b,c,d) \
+  if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
+
+    struct interface *ifp = NULL;
+    struct listnode *linklist_node = NULL;
+
+    *tv = check_neighbours_timeout;
+    printIfMin(tv, 0, "check_neighbours_timeout", NULL);
+    timeval_min_sec(tv, expiry_time);
+    printIfMin(tv, 1, "expiry_time", NULL);
+    timeval_min_sec(tv, source_expiry_time);
+    printIfMin(tv, 1, "source_expiry_time", NULL);
+    timeval_min(tv, &resend_time);
+    printIfMin(tv, 1, "resend_time", NULL);
+    FOR_ALL_INTERFACES(ifp, linklist_node) {
+        babel_interface_nfo *babel_ifp = NULL;
+        if(!if_up(ifp))
+            continue;
+        babel_ifp = babel_get_if_nfo(ifp);
+        timeval_min(tv, &babel_ifp->flush_timeout);
+        printIfMin(tv, 1, "flush_timeout", ifp->name);
+        timeval_min(tv, &babel_ifp->hello_timeout);
+        printIfMin(tv, 1, "hello_timeout", ifp->name);
+        timeval_min(tv, &babel_ifp->update_timeout);
+        printIfMin(tv, 1, "update_timeout", ifp->name);
+        timeval_min(tv, &babel_ifp->update_flush_timeout);
+        printIfMin(tv, 1, "update_flush_timeout",ifp->name);
+    }
+    timeval_min(tv, &unicast_flush_timeout);
+    printIfMin(tv, 1, "unicast_flush_timeout", NULL);
+    printIfMin(tv, 2, NULL, NULL);
+#undef printIfMin
+#endif
+}
+
+/* set the t_update thread of the babel routing process to be launch in
+ 'timeout' (approximate at the milisecond) */
+static void
+babel_set_timer(struct timeval *timeout)
+{
+    long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+    if (babel_routing_process->t_update != NULL) {